feat: integrate date range selection in property management and workflow lists
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 8s

This commit is contained in:
puriphatt 2025-04-17 16:23:52 +07:00
parent fd5d4b7979
commit efeb1b51eb
3 changed files with 53 additions and 27 deletions

View file

@ -283,8 +283,8 @@ async function fetchWorkflowList(mobileFetch?: boolean) {
: statusFilter.value === 'statusACTIVE' : statusFilter.value === 'statusACTIVE'
? 'ACTIVE' ? 'ACTIVE'
: 'INACTIVE', : 'INACTIVE',
startDate: pageState.searchDate[0] || undefined, startDate: pageState.searchDate[0],
endDate: pageState.searchDate[1] || undefined, endDate: pageState.searchDate[1],
}); });
if (res) { if (res) {
workflowData.value = workflowData.value =
@ -533,12 +533,12 @@ watch(
class="col surface-2 flex items-center justify-center" class="col surface-2 flex items-center justify-center"
> >
<NoData <NoData
v-if="pageState.total !== 0" v-if="pageState.total !== 0 || pageState.searchDate.length > 0"
:not-found="!!pageState.inputSearch" :not-found="!!pageState.inputSearch"
/> />
<CreateButton <CreateButton
v-if="pageState.total === 0" v-if="pageState.total === 0 && pageState.searchDate.length === 0"
@click="triggerDialog('add')" @click="triggerDialog('add')"
label="general.add" label="general.add"
:i18n-args="{ text: $t('flow.title') }" :i18n-args="{ text: $t('flow.title') }"

View file

@ -2,7 +2,7 @@
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { onMounted, reactive, ref } from 'vue'; import { onMounted, reactive, ref } from 'vue';
import { QSelect, QTableProps } from 'quasar'; import { QTableProps } from 'quasar';
import { useNavigator } from 'src/stores/navigator'; import { useNavigator } from 'src/stores/navigator';
import { useProperty } from 'src/stores/property'; import { useProperty } from 'src/stores/property';
import { useQuasar } from 'quasar'; import { useQuasar } from 'quasar';
@ -17,6 +17,7 @@ import { Property } from 'src/stores/property/types';
import { dialog, toCamelCase } from 'src/stores/utils'; import { dialog, toCamelCase } from 'src/stores/utils';
import CreateButton from 'src/components/AddButton.vue'; import CreateButton from 'src/components/AddButton.vue';
import useOptionStore from 'stores/options'; import useOptionStore from 'stores/options';
import AdvanceSearch from 'src/components/shared/AdvanceSearch.vue';
const { t, locale } = useI18n(); const { t, locale } = useI18n();
const $q = useQuasar(); const $q = useQuasar();
@ -38,7 +39,6 @@ const formProperty = ref<Property>({
type: {}, type: {},
}); });
const statusFilter = ref<'all' | 'statusACTIVE' | 'statusINACTIVE'>('all'); const statusFilter = ref<'all' | 'statusACTIVE' | 'statusINACTIVE'>('all');
const refFilter = ref<InstanceType<typeof QSelect>>();
const fieldSelected = ref<('order' | 'name' | 'type')[]>([ const fieldSelected = ref<('order' | 'name' | 'type')[]>([
'order', 'order',
'name', 'name',
@ -118,6 +118,7 @@ const pageState = reactive({
addModal: false, addModal: false,
viewDrawer: false, viewDrawer: false,
isDrawerEdit: true, isDrawerEdit: true,
searchDate: [],
}); });
async function fetchPropertyList(mobileFetch?: boolean) { async function fetchPropertyList(mobileFetch?: boolean) {
@ -134,6 +135,8 @@ async function fetchPropertyList(mobileFetch?: boolean) {
: statusFilter.value === 'statusACTIVE' : statusFilter.value === 'statusACTIVE'
? 'ACTIVE' ? 'ACTIVE'
: 'INACTIVE', : 'INACTIVE',
startDate: pageState.searchDate[0],
endDate: pageState.searchDate[1],
}); });
if (res) { if (res) {
propertyData.value = propertyData.value =
@ -317,11 +320,14 @@ watch(
fetchPropertyList(); fetchPropertyList();
}, },
); );
watch([() => pageState.inputSearch, propertyPageSize], () => { watch(
propertyData.value = []; [() => pageState.inputSearch, propertyPageSize, () => pageState.searchDate],
propertyPage.value = 1; () => {
fetchPropertyList(); propertyData.value = [];
}); propertyPage.value = 1;
fetchPropertyList();
},
);
</script> </script>
<template> <template>
<FloatingActionButton <FloatingActionButton
@ -398,26 +404,44 @@ watch([() => pageState.inputSearch, propertyPageSize], () => {
<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 && statusFilter !== 'all'"
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="statusFilter"
outlined
dense
option-value="value"
option-label="label"
map-options
emit-value
:for="'field-select-status'"
:options="[
{ label: $t('general.all'), value: 'all' },
{ label: $t('general.active'), value: 'statusACTIVE' },
{
label: $t('general.inactive'),
value: 'statusINACTIVE',
},
]"
/> />
</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="statusFilter" v-model="statusFilter"
outlined outlined
dense dense
@ -512,11 +536,11 @@ watch([() => pageState.inputSearch, propertyPageSize], () => {
class="col surface-2 flex items-center justify-center" class="col surface-2 flex items-center justify-center"
> >
<NoData <NoData
v-if="pageState.total !== 0" v-if="pageState.total !== 0 || pageState.searchDate.length > 0"
:not-found="!!pageState.inputSearch" :not-found="!!pageState.inputSearch"
/> />
<CreateButton <CreateButton
v-if="pageState.total === 0" v-if="pageState.total === 0 && pageState.searchDate.length === 0"
@click="triggerDialog('add')" @click="triggerDialog('add')"
label="general.add" label="general.add"
:i18n-args="{ text: $t('flow.title') }" :i18n-args="{ text: $t('flow.title') }"

View file

@ -25,6 +25,8 @@ export const useProperty = defineStore('property-store', () => {
query?: string; query?: string;
status?: Status; status?: Status;
activeOnly?: boolean; activeOnly?: boolean;
startDate?: string;
endDate?: string;
}) { }) {
const res = await api.get<PaginationResult<Property>>('/property', { const res = await api.get<PaginationResult<Property>>('/property', {
params, params,