feat: add date range selection to request list filtering

This commit is contained in:
puriphatt 2025-04-17 17:25:37 +07:00
parent 73562a59c1
commit ea21ec4632
2 changed files with 69 additions and 21 deletions

View file

@ -3,7 +3,7 @@
import { computed, onMounted, reactive, ref, watch } from 'vue'; import { computed, onMounted, reactive, ref, watch } from 'vue';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { QSelect, useQuasar } from 'quasar'; import { useQuasar } from 'quasar';
// NOTE: Components // NOTE: Components
import StatCardComponent from 'src/components/StatCardComponent.vue'; import StatCardComponent from 'src/components/StatCardComponent.vue';
@ -26,6 +26,7 @@ import { CancelButton, SaveButton } from 'src/components/button';
import { getRole } from 'src/services/keycloak'; import { getRole } from 'src/services/keycloak';
import FloatingActionButton from 'src/components/FloatingActionButton.vue'; import FloatingActionButton from 'src/components/FloatingActionButton.vue';
import RequestListAction from './RequestListAction .vue'; import RequestListAction from './RequestListAction .vue';
import AdvanceSearch from 'src/components/shared/AdvanceSearch.vue';
const $q = useQuasar(); const $q = useQuasar();
const navigatorStore = useNavigator(); const navigatorStore = useNavigator();
@ -35,7 +36,6 @@ const { t } = useI18n();
const { data, stats, page, pageMax, pageSize } = storeToRefs(requestListStore); const { data, stats, page, pageMax, pageSize } = storeToRefs(requestListStore);
const requestListActionData = ref<RequestData[]>(); const requestListActionData = ref<RequestData[]>();
const refFilter = ref<InstanceType<typeof QSelect>>();
// NOTE: Variable // NOTE: Variable
const pageState = reactive({ const pageState = reactive({
@ -49,6 +49,7 @@ const pageState = reactive({
rejectCancelReason: '', rejectCancelReason: '',
requestId: '', requestId: '',
requestListActionDialog: false, requestListActionDialog: false,
searchDate: [],
}); });
const fieldSelectedOption = computed(() => { const fieldSelectedOption = computed(() => {
@ -64,6 +65,8 @@ async function fetchList(opts?: { rotateFlowId?: boolean }) {
query: pageState.inputSearch, query: pageState.inputSearch,
page: page.value, page: page.value,
pageSize: pageSize.value, pageSize: pageSize.value,
startDate: pageState.searchDate[0],
endDate: pageState.searchDate[1],
requestDataStatus: requestDataStatus:
pageState.statusFilter === 'None' ? undefined : pageState.statusFilter, pageState.statusFilter === 'None' ? undefined : pageState.statusFilter,
// responsibleOnly: true, // responsibleOnly: true,
@ -170,11 +173,18 @@ onMounted(async () => {
await fetchList({ rotateFlowId: true }); await fetchList({ rotateFlowId: true });
}); });
watch([() => pageState.inputSearch, () => pageState.statusFilter], () => { watch(
page.value = 1; [
data.value = []; () => pageState.inputSearch,
fetchList({ rotateFlowId: true }); () => pageState.statusFilter,
}); () => pageState.searchDate,
],
() => {
page.value = 1;
data.value = [];
fetchList({ rotateFlowId: true });
},
);
</script> </script>
<template> <template>
<FloatingActionButton <FloatingActionButton
@ -276,26 +286,62 @@ watch([() => pageState.inputSearch, () => pageState.statusFilter], () => {
<template #prepend> <template #prepend>
<q-icon name="mdi-magnify" /> <q-icon name="mdi-magnify" />
</template> </template>
<template v-if="$q.screen.lt.md" v-slot:append> <template v-slot:append>
<span class="row"> <q-separator vertical inset class="q-mr-xs" />
<q-separator vertical /> <AdvanceSearch
<q-btn v-model="pageState.searchDate"
icon="mdi-filter-variant" :active="$q.screen.lt.md && pageState.statusFilter !== 'None'"
unelevated >
class="q-ml-sm" <div
padding="4px" v-if="$q.screen.lt.md"
size="sm" class="q-mt-sm text-weight-medium"
rounded >
@click="refFilter?.showPopup" {{ $t('general.status') }}
</div>
<q-select
v-if="$q.screen.lt.md"
v-model="pageState.statusFilter"
outlined
dense
option-value="value"
option-label="label"
map-options
emit-value
:for="'field-select-status'"
:options="[
{
label: $t('general.all'),
value: 'None',
},
{
label: $t('requestList.status.Pending'),
value: RequestDataStatus.Pending,
},
{
label: $t('requestList.status.Ready'),
value: RequestDataStatus.Ready,
},
{
label: $t('requestList.status.InProgress'),
value: RequestDataStatus.InProgress,
},
{
label: $t('requestList.status.Completed'),
value: RequestDataStatus.Completed,
},
{
label: $t('requestList.status.Canceled'),
value: RequestDataStatus.Canceled,
},
]"
/> />
</span> </AdvanceSearch>
</template> </template>
</q-input> </q-input>
<div class="row col-md-5" style="white-space: nowrap"> <div class="row col-md-5" style="white-space: nowrap">
<q-select <q-select
v-show="$q.screen.gt.sm" v-if="$q.screen.gt.sm"
ref="refFilter"
v-model="pageState.statusFilter" v-model="pageState.statusFilter"
outlined outlined
dense dense

View file

@ -210,6 +210,8 @@ export const useRequestList = defineStore('request-list', () => {
responsibleOnly?: boolean; responsibleOnly?: boolean;
quotationId?: string; quotationId?: string;
incomplete?: boolean; incomplete?: boolean;
startDate?: string;
endDate?: string;
}) { }) {
const res = await api.get<PaginationResult<RequestData>>('/request-data', { const res = await api.get<PaginationResult<RequestData>>('/request-data', {
params, params,