feat: add date range selection to credit note, debit note, and receipt management

This commit is contained in:
puriphatt 2025-04-17 17:38:09 +07:00
parent 1e6be274e2
commit ac42ee60d8
6 changed files with 61 additions and 15 deletions

View file

@ -24,6 +24,7 @@ import { pageTabs, columns, hslaColors } from './constants';
import { CreditNoteStatus, useCreditNote } from 'src/stores/credit-note'; import { CreditNoteStatus, useCreditNote } from 'src/stores/credit-note';
import TableCreditNote from './TableCreditNote.vue'; import TableCreditNote from './TableCreditNote.vue';
import { dialogWarningClose } from 'src/stores/utils'; import { dialogWarningClose } from 'src/stores/utils';
import AdvanceSearch from 'src/components/shared/AdvanceSearch.vue';
const $q = useQuasar(); const $q = useQuasar();
const { t } = useI18n(); const { t } = useI18n();
@ -46,6 +47,7 @@ const pageState = reactive({
total: 0, total: 0,
creditDialog: false, creditDialog: false,
searchDate: [],
}); });
const fieldSelectedOption = computed(() => { const fieldSelectedOption = computed(() => {
@ -64,6 +66,8 @@ async function getList(opts?: { page?: number; pageSize?: number }) {
pageSize: opts?.pageSize || pageSize.value, pageSize: opts?.pageSize || pageSize.value,
query: pageState.inputSearch === '' ? undefined : pageState.inputSearch, query: pageState.inputSearch === '' ? undefined : pageState.inputSearch,
creditNoteStatus: pageState.currentTab as CreditNoteStatus | undefined, creditNoteStatus: pageState.currentTab as CreditNoteStatus | undefined,
startDate: pageState.searchDate[0],
endDate: pageState.searchDate[1],
}); });
if (res) { if (res) {
@ -133,6 +137,7 @@ watch(
() => pageState.inputSearch, () => pageState.inputSearch,
() => pageSize.value, () => pageSize.value,
() => pageState.statusFilter, () => pageState.statusFilter,
() => pageState.searchDate,
], ],
() => { () => {
getList(); getList();
@ -228,6 +233,10 @@ watch(
<template #prepend> <template #prepend>
<q-icon name="mdi-magnify" /> <q-icon name="mdi-magnify" />
</template> </template>
<template v-slot:append>
<q-separator vertical inset class="q-mr-xs" />
<AdvanceSearch v-model="pageState.searchDate" />
</template>
</q-input> </q-input>
<div class="row col-md-5 justify-end" style="white-space: nowrap"> <div class="row col-md-5 justify-end" style="white-space: nowrap">

View file

@ -24,6 +24,7 @@ import { pageTabs, columns, hslaColors } from './constants';
import { DebitNoteStatus, useDebitNote } from 'src/stores/debit-note'; import { DebitNoteStatus, useDebitNote } from 'src/stores/debit-note';
import { dialogWarningClose } from 'src/stores/utils'; import { dialogWarningClose } from 'src/stores/utils';
import { useQuasar } from 'quasar'; import { useQuasar } from 'quasar';
import AdvanceSearch from 'src/components/shared/AdvanceSearch.vue';
const $q = useQuasar(); const $q = useQuasar();
const { t } = useI18n(); const { t } = useI18n();
@ -46,6 +47,7 @@ const pageState = reactive({
total: 0, total: 0,
debitDialog: false, debitDialog: false,
searchDate: [],
}); });
const fieldSelectedOption = computed(() => { const fieldSelectedOption = computed(() => {
@ -68,6 +70,8 @@ async function getList(opts?: { page?: number; pageSize?: number }) {
? undefined ? undefined
: pageState.currentTab) as DebitNoteStatus, : pageState.currentTab) as DebitNoteStatus,
includeRegisteredBranch: true, includeRegisteredBranch: true,
startDate: pageState.searchDate[0],
endDate: pageState.searchDate[1],
}); });
if (res) { if (res) {
@ -149,6 +153,7 @@ watch(
() => pageState.inputSearch, () => pageState.inputSearch,
() => pageSize.value, () => pageSize.value,
() => pageState.statusFilter, () => pageState.statusFilter,
() => pageState.searchDate,
], ],
() => getList(), () => getList(),
); );
@ -256,6 +261,10 @@ watch(
<template #prepend> <template #prepend>
<q-icon name="mdi-magnify" /> <q-icon name="mdi-magnify" />
</template> </template>
<template v-slot:append>
<q-separator vertical inset class="q-mr-xs" />
<AdvanceSearch v-model="pageState.searchDate" />
</template>
</q-input> </q-input>
<div class="row col-md-5 justify-end" style="white-space: nowrap"> <div class="row col-md-5 justify-end" style="white-space: nowrap">

View file

@ -17,7 +17,8 @@ import { columns, hslaColors } from './constants';
import useFlowStore from 'src/stores/flow'; import useFlowStore from 'src/stores/flow';
import { usePayment, useReceipt } from 'src/stores/payment'; import { usePayment, useReceipt } from 'src/stores/payment';
import { PaymentDataStatus } from 'src/stores/payment/types'; import { PaymentDataStatus } from 'src/stores/payment/types';
import { QSelect, useQuasar } from 'quasar'; import { useQuasar } from 'quasar';
import AdvanceSearch from 'src/components/shared/AdvanceSearch.vue';
const $q = useQuasar(); const $q = useQuasar();
const navigatorStore = useNavigator(); const navigatorStore = useNavigator();
@ -26,7 +27,6 @@ const receiptStore = useReceipt();
const { data, page, pageMax, pageSize } = storeToRefs(receiptStore); const { data, page, pageMax, pageSize } = storeToRefs(receiptStore);
// NOTE: Variable // NOTE: Variable
const refFilter = ref<InstanceType<typeof QSelect>>();
const pageState = reactive({ const pageState = reactive({
hideStat: false, hideStat: false,
@ -35,6 +35,7 @@ const pageState = reactive({
fieldSelected: [...columns.map((v) => v.name)], fieldSelected: [...columns.map((v) => v.name)],
gridView: false, gridView: false,
total: 0, total: 0,
searchDate: [],
}); });
const fieldSelectedOption = computed(() => { const fieldSelectedOption = computed(() => {
@ -49,6 +50,8 @@ async function fetchList(opts?: { rotateFlowId?: boolean }) {
page: page.value, page: page.value,
pageSize: pageSize.value, pageSize: pageSize.value,
query: pageState.inputSearch, query: pageState.inputSearch,
startDate: pageState.searchDate[0],
endDate: pageState.searchDate[1],
}); });
if (ret) { if (ret) {
data.value = $q.screen.xs ? [...data.value, ...ret.result] : ret.result; data.value = $q.screen.xs ? [...data.value, ...ret.result] : ret.result;
@ -95,6 +98,7 @@ watch(
() => pageState.inputSearch, () => pageState.inputSearch,
() => pageState.statusFilter, () => pageState.statusFilter,
() => pageSize.value, () => pageSize.value,
() => pageState.searchDate,
], ],
() => { () => {
page.value = 1; page.value = 1;
@ -172,25 +176,43 @@ watch(
<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"
ref="refFilter"
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',
},
]"
/> />
</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" ref="refFilter"
v-model="pageState.statusFilter" v-model="pageState.statusFilter"
outlined outlined

View file

@ -28,6 +28,8 @@ export async function getCreditNoteList(params?: {
pageSize?: number; pageSize?: number;
query?: string; query?: string;
creditNoteStatus?: Status; creditNoteStatus?: Status;
startDate?: string;
endDate?: string;
}) { }) {
const res = await api.get<PaginationResult<Data>>(`/${ENDPOINT}`, { const res = await api.get<PaginationResult<Data>>(`/${ENDPOINT}`, {
params, params,

View file

@ -28,6 +28,8 @@ export async function getDebitNoteList(params?: {
query?: string; query?: string;
status?: Status; status?: Status;
includeRegisteredBranch?: boolean; includeRegisteredBranch?: boolean;
startDate?: string;
endDate?: string;
}) { }) {
const res = await api.get<PaginationResult<Data>>(`/${ENDPOINT}`, { const res = await api.get<PaginationResult<Data>>(`/${ENDPOINT}`, {
params, params,

View file

@ -101,6 +101,8 @@ export const useReceipt = defineStore('receipt-store', () => {
debitNoteId?: string; debitNoteId?: string;
debitNoteOnly?: boolean; debitNoteOnly?: boolean;
quotationOnly?: boolean; quotationOnly?: boolean;
startDate?: string;
endDate?: string;
}) { }) {
const res = await api.get<PaginationResult<Receipt>>('/receipt', { const res = await api.get<PaginationResult<Receipt>>('/receipt', {
params: opts, params: opts,