feat: add AdvanceSearch component for date range selection
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 8s
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 8s
This commit is contained in:
parent
08b0dcbce0
commit
4e86a90b0e
1 changed files with 188 additions and 0 deletions
188
src/components/shared/AdvanceSearch.vue
Normal file
188
src/components/shared/AdvanceSearch.vue
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { dateFormatJS } from 'src/utils/datetime';
|
||||
import SelectInput from './SelectInput.vue';
|
||||
import VueDatePicker from '@vuepic/vue-datepicker';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
defineProps<{
|
||||
active?: boolean;
|
||||
}>();
|
||||
|
||||
const date = defineModel<Date[]>();
|
||||
|
||||
const dateRange = ref<string>('');
|
||||
const isDateSelect = ref(false);
|
||||
|
||||
function mapDateRange(val: string) {
|
||||
const today = dayjs();
|
||||
let start: dayjs.Dayjs, end: dayjs.Dayjs;
|
||||
|
||||
switch (val) {
|
||||
case 'toDay':
|
||||
start = today.startOf('day');
|
||||
end = today.endOf('day');
|
||||
break;
|
||||
case 'yesterday':
|
||||
start = today.subtract(1, 'day').startOf('day');
|
||||
end = today.subtract(1, 'day').endOf('day');
|
||||
break;
|
||||
case 'thisWeek':
|
||||
start = today.startOf('week');
|
||||
end = today.endOf('week');
|
||||
break;
|
||||
case 'lastWeek':
|
||||
start = today.subtract(1, 'week').startOf('week');
|
||||
end = today.subtract(1, 'week').endOf('week');
|
||||
break;
|
||||
case 'thisMonth':
|
||||
start = today.startOf('month');
|
||||
end = today.endOf('month');
|
||||
break;
|
||||
case 'lastMonth':
|
||||
start = today.subtract(1, 'month').startOf('month');
|
||||
end = today.subtract(1, 'month').endOf('month');
|
||||
break;
|
||||
case 'thisYear':
|
||||
start = today.startOf('year');
|
||||
end = today.endOf('year');
|
||||
break;
|
||||
case 'lastYear':
|
||||
start = today.subtract(1, 'year').startOf('year');
|
||||
end = today.subtract(1, 'year').endOf('year');
|
||||
break;
|
||||
case 'last7Days':
|
||||
start = today.subtract(6, 'day').startOf('day');
|
||||
end = today.endOf('day');
|
||||
break;
|
||||
case 'last30Days':
|
||||
start = today.subtract(29, 'day').startOf('day');
|
||||
end = today.endOf('day');
|
||||
break;
|
||||
case 'last90Days':
|
||||
start = today.subtract(89, 'day').startOf('day');
|
||||
end = today.endOf('day');
|
||||
break;
|
||||
case 'customDateRange':
|
||||
// Do nothing or allow manual date picking
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
return [start.toDate(), end.toDate()];
|
||||
}
|
||||
|
||||
watch(
|
||||
() => dateRange.value,
|
||||
() => {
|
||||
if (!dateRange.value) return;
|
||||
date.value = mapDateRange(dateRange.value);
|
||||
},
|
||||
);
|
||||
|
||||
watch(
|
||||
() => date.value,
|
||||
() => {
|
||||
if (date.value && date.value.length === 0) dateRange.value = '';
|
||||
},
|
||||
);
|
||||
</script>
|
||||
<template>
|
||||
<q-btn
|
||||
size="xs"
|
||||
round
|
||||
dense
|
||||
unelevated
|
||||
icon="mdi-tune-variant"
|
||||
:flat="active ? false : !dateRange"
|
||||
:color="active || dateRange ? 'info' : undefined"
|
||||
>
|
||||
<q-menu
|
||||
:offset="[5, 10]"
|
||||
max-width="300px"
|
||||
class="bordered"
|
||||
:persistent="isDateSelect"
|
||||
>
|
||||
<div class="q-pa-sm">
|
||||
<div class="text-weight-medium">
|
||||
{{ $t('general.advanceSearch') }}
|
||||
</div>
|
||||
<SelectInput
|
||||
v-model="dateRange"
|
||||
:label="$t('general.period')"
|
||||
:option="[
|
||||
{ label: $t('dateRange.today'), value: 'toDay' },
|
||||
{ label: $t('dateRange.yesterday'), value: 'yesterday' },
|
||||
{ label: $t('dateRange.thisWeek'), value: 'thisWeek' },
|
||||
{ label: $t('dateRange.lastWeek'), value: 'lastWeek' },
|
||||
{ label: $t('dateRange.thisMonth'), value: 'thisMonth' },
|
||||
{ label: $t('dateRange.lastMonth'), value: 'lastMonth' },
|
||||
{ label: $t('dateRange.thisYear'), value: 'thisYear' },
|
||||
{ label: $t('dateRange.lastYear'), value: 'lastYear' },
|
||||
{ label: $t('dateRange.last7Days'), value: 'last7Days' },
|
||||
{ label: $t('dateRange.last30Days'), value: 'last30Days' },
|
||||
{ label: $t('dateRange.last90Days'), value: 'last90Days' },
|
||||
{
|
||||
label: $t('dateRange.customDateRange'),
|
||||
value: 'customDateRange',
|
||||
},
|
||||
]"
|
||||
clearable
|
||||
@clear="() => (date = [])"
|
||||
/>
|
||||
|
||||
<VueDatePicker
|
||||
v-if="dateRange === 'customDateRange'"
|
||||
utc
|
||||
range
|
||||
teleport
|
||||
auto-apply
|
||||
for="select-date-range"
|
||||
class="q-mt-sm"
|
||||
v-model="date"
|
||||
:dark="$q.dark.isActive"
|
||||
:locale="$i18n.locale === 'tha' ? 'th' : 'en'"
|
||||
@open="() => (isDateSelect = true)"
|
||||
@closed="() => (isDateSelect = false)"
|
||||
>
|
||||
<template #trigger>
|
||||
<q-input
|
||||
placeholder="DD/MM/YYYY"
|
||||
hide-bottom-space
|
||||
dense
|
||||
outlined
|
||||
for="select-date-range"
|
||||
:model-value="
|
||||
date
|
||||
? dateFormatJS({ date: date[0] }) +
|
||||
' - ' +
|
||||
dateFormatJS({ date: date[1] })
|
||||
: ''
|
||||
"
|
||||
>
|
||||
<template #prepend>
|
||||
<q-icon name="mdi-calendar-outline" class="app-text-muted" />
|
||||
</template>
|
||||
<q-tooltip>
|
||||
{{
|
||||
date
|
||||
? dateFormatJS({ date: date[0] }) +
|
||||
' - ' +
|
||||
dateFormatJS({ date: date[1] })
|
||||
: ''
|
||||
}}
|
||||
</q-tooltip>
|
||||
</q-input>
|
||||
</template>
|
||||
</VueDatePicker>
|
||||
|
||||
<slot></slot>
|
||||
<!-- <SelectInput :label="$t('general.documentStatus')" :option="[]" /> -->
|
||||
</div>
|
||||
</q-menu>
|
||||
<q-tooltip v-if="$q.screen.gt.sm">
|
||||
{{ $t('general.advanceSearch') }}
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
</template>
|
||||
Loading…
Add table
Add a link
Reference in a new issue