feat: implement functionality to filter request list by same office area
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 10s

This commit is contained in:
puriphatt 2025-04-17 15:35:13 +07:00
parent 550ed55de0
commit d95d72806d
3 changed files with 80 additions and 9 deletions

View file

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref } from 'vue'; import { reactive, ref, watch } from 'vue';
import { RequestData } from 'src/stores/request-list'; import { RequestData } from 'src/stores/request-list';
import { DialogContainer, DialogHeader } from 'src/components/dialog'; import { DialogContainer, DialogHeader } from 'src/components/dialog';
import { import {
@ -8,12 +8,11 @@ import {
MainButton, MainButton,
SaveButton, SaveButton,
} from 'src/components/button'; } from 'src/components/button';
import TableProductAndService from 'src/components/shared/table/TableProductAndService.vue';
import { Product } from 'src/stores/product-service/types';
import FormResponsibleUser from './FormResponsibleUser.vue'; import FormResponsibleUser from './FormResponsibleUser.vue';
import FormGroupHead from './FormGroupHead.vue'; import FormGroupHead from './FormGroupHead.vue';
import TableRequestList from './TableRequestList.vue'; import TableRequestList from './TableRequestList.vue';
import { column } from './constants'; import { column } from './constants';
import useAddressStore from 'src/stores/address';
defineProps<{ defineProps<{
requestList: RequestData[]; requestList: RequestData[];
@ -37,6 +36,7 @@ enum Step {
const open = defineModel<boolean>({ default: false }); const open = defineModel<boolean>({ default: false });
const step = ref<Step>(Step.RequestList); const step = ref<Step>(Step.RequestList);
const selected = ref<RequestData[]>([]); const selected = ref<RequestData[]>([]);
const listSameArea = ref<string[]>([]);
const form = reactive({ const form = reactive({
responsibleUserLocal: false, responsibleUserLocal: false,
responsibleUserId: '', responsibleUserId: '',
@ -51,8 +51,18 @@ function reset() {
function prev() { function prev() {
step.value = Step.RequestList; step.value = Step.RequestList;
console.log(selected.value[0]);
} }
watch(
() => selected.value,
async () => {
if (selected.value.length === 1) {
const districtId = selected.value[0].quotation.customerBranch.districtId;
const ret = await useAddressStore().listSameOfficeArea(districtId);
if (ret) listSameArea.value = ret;
}
},
);
</script> </script>
<template> <template>
<DialogContainer v-model="open" :onOpen="reset"> <DialogContainer v-model="open" :onOpen="reset">
@ -89,6 +99,7 @@ function prev() {
hide-action hide-action
hide-view hide-view
checkable checkable
:list-same-area="listSameArea"
:columns="column" :columns="column"
:rows="requestList" :rows="requestList"
:visible-columns="[...column.map((col) => col.name)]" :visible-columns="[...column.map((col) => col.name)]"
@ -116,6 +127,7 @@ function prev() {
</FormGroupHead> </FormGroupHead>
<FormResponsibleUser <FormResponsibleUser
:district-id="listSameArea[0]"
v-model:responsible-user-id="form.responsibleUserId" v-model:responsible-user-id="form.responsibleUserId"
v-model:responsible-user-local="form.responsibleUserLocal" v-model:responsible-user-local="form.responsibleUserLocal"
/> />

View file

@ -24,6 +24,7 @@ const props = withDefaults(
hideAction?: boolean; hideAction?: boolean;
hideView?: boolean; hideView?: boolean;
checkable?: boolean; checkable?: boolean;
listSameArea?: string[];
}>(), }>(),
{ {
row: () => [], row: () => [],
@ -39,7 +40,7 @@ defineEmits<{
(e: 'rejectCancel', data: RequestData): void; (e: 'rejectCancel', data: RequestData): void;
}>(); }>();
const selected = defineModel<unknown[]>('selected'); const selected = defineModel<RequestData[]>('selected');
function responsiblePerson(quotation: QuotationFull): CreatedBy[] | undefined { function responsiblePerson(quotation: QuotationFull): CreatedBy[] | undefined {
const productServiceList = quotation.productServiceList; const productServiceList = quotation.productServiceList;
@ -97,7 +98,7 @@ function getEmployeeName(
return ( return (
{ {
['eng']: `${useOptionStore().mapOption(employee?.namePrefix || '')} ${employee?.firstNameEN} ${employee?.lastNameEN}`, ['eng']: `${useOptionStore().mapOption(employee?.namePrefix || '')} ${employee?.firstNameEN} ${employee?.lastNameEN}`,
['tha']: `${useOptionStore().mapOption(employee?.namePrefix || '')} ${employee?.firstName} ${employee?.lastName}`, ['tha']: `${useOptionStore().mapOption(employee?.namePrefix || '')} ${employee?.firstName || employee?.firstNameEN} ${employee?.lastName || employee?.lastNameEN}`,
}[opts?.locale || 'eng'] || '-' }[opts?.locale || 'eng'] || '-'
); );
} }
@ -119,6 +120,17 @@ function toEmployee(employee: RequestData['employee']) {
window.open(url.toString(), '_blank'); window.open(url.toString(), '_blank');
} }
function handleCheckAll() {
const filteredRows = props.rows.filter((row) =>
props.listSameArea?.includes(row.quotation.customerBranch.districtId),
);
if (selected.value.length === filteredRows.length) {
selected.value = [];
} else {
selected.value = filteredRows;
}
}
</script> </script>
<template> <template>
<q-table <q-table
@ -146,7 +158,18 @@ function toEmployee(employee: RequestData['employee']) {
:props="props" :props="props"
> >
<q-th v-if="checkable"> <q-th v-if="checkable">
<q-checkbox v-model="props.selected" size="sm" /> <q-checkbox
v-if="selected.length > 0"
:model-value="
selected.length ===
rows.filter((row) =>
listSameArea?.includes(row.quotation.customerBranch.districtId),
).length
"
size="sm"
@click="handleCheckAll"
/>
<div v-else style="width: 35px; height: 35px"></div>
</q-th> </q-th>
<q-th v-for="col in props.cols" :key="col.name" :props="props"> <q-th v-for="col in props.cols" :key="col.name" :props="props">
{{ col.label && $t(col.label) }} {{ col.label && $t(col.label) }}
@ -161,11 +184,29 @@ function toEmployee(employee: RequestData['employee']) {
} & Omit<Parameters<QTableSlots['body']>[0], 'row'>" } & Omit<Parameters<QTableSlots['body']>[0], 'row'>"
> >
<q-tr <q-tr
:class="{ urgent: props.row.quotation.urgent, dark: $q.dark.isActive }" :class="{
urgent: props.row.quotation.urgent,
dark: $q.dark.isActive,
'disabled-row':
selected &&
selected.length > 0 &&
!listSameArea.includes(
props.row.quotation.customerBranch.districtId,
),
}"
class="text-center" class="text-center"
> >
<q-td v-if="checkable"> <q-td v-if="checkable">
<q-checkbox v-model="props.selected" size="sm" /> <q-checkbox
:disable="
selected.length > 0 &&
!listSameArea.includes(
props.row.quotation.customerBranch.districtId,
)
"
v-model="props.selected"
size="sm"
/>
</q-td> </q-td>
<q-td v-if="visibleColumns.includes('order')"> <q-td v-if="visibleColumns.includes('order')">
{{ props.rowIndex + 1 }} {{ props.rowIndex + 1 }}
@ -487,4 +528,9 @@ function toEmployee(employee: RequestData['employee']) {
text-decoration: underline; text-decoration: underline;
cursor: pointer; cursor: pointer;
} }
.disabled-row {
opacity: 0.3;
filter: grayscale(1);
}
</style> </style>

View file

@ -102,12 +102,25 @@ const useAddressStore = defineStore('api-address', () => {
return subDistrict.value[districtId]; return subDistrict.value[districtId];
} }
async function listSameOfficeArea(districtId: string) {
const res = await api.post<string[]>(
`/employment-office/list-same-office-area`,
{ districtId: districtId },
);
if (!res) return false;
return res.data;
}
return { return {
fetchOffice, fetchOffice,
fetchOfficeById, fetchOfficeById,
fetchProvince, fetchProvince,
fetchDistrictByProvinceId, fetchDistrictByProvinceId,
fetchSubDistrictByProvinceId, fetchSubDistrictByProvinceId,
listSameOfficeArea,
}; };
}); });