import { dialog } from 'stores/utils'; import { defineStore } from 'pinia'; import { useI18n } from 'vue-i18n'; import { ref } from 'vue'; // NOTE: Import types import { QuotationPayload, EmployeeWorker, QuotationFull, } from 'src/stores/quotations/types'; // NOTE: Import stores import { useQuotationStore } from 'stores/quotations'; import useEmployeeStore from 'stores/employee'; import { getName } from 'src/services/keycloak'; const DEFAULT_DATA: QuotationPayload = { productServiceList: [], urgent: false, customerBranchId: '', worker: [], payBillDate: new Date(), paySplit: [], paySplitCount: 0, payCondition: 'Full', dueDate: new Date(), discount: 0, documentReceivePoint: '', contactTel: '', contactName: '', workName: '', registeredBranchId: '', _count: { worker: 0 }, status: 'CREATED', remark: undefined, }; export const useQuotationForm = defineStore('form-quotation', () => { const { t } = useI18n(); const quotationStore = useQuotationStore(); const employeeStore = useEmployeeStore(); const quotationFull = ref(undefined); const newWorkerList = ref< (EmployeeWorker & { attachment?: { name?: string; group?: string; url?: string; file?: File; _meta?: Record; }[]; })[] >([]); let resetFormData = structuredClone(DEFAULT_DATA); const fileItemNewWorker = ref< { employeeIndex: number; name?: string; group: 'passport' | 'visa' | 'in-country-notice'; url?: string; file?: File; _meta?: Record; }[] >([]); const currentFormData = ref( structuredClone(resetFormData), ); const currentFormState = ref<{ mode: null | 'info' | 'create' | 'edit'; createdBy: (locale: string) => string; }>({ mode: null, createdBy: (_) => getName() || '', }); function isFormDataDifferent() { const { ...resetData } = resetFormData; const { ...currData } = currentFormData.value; return JSON.stringify(resetData) !== JSON.stringify(currData); } function resetForm(clean = false) { if (clean) { currentFormData.value = structuredClone(DEFAULT_DATA); resetFormData = structuredClone(DEFAULT_DATA); fileItemNewWorker.value = []; newWorkerList.value = []; return; } currentFormData.value = structuredClone(resetFormData); currentFormState.value.mode = 'info'; } async function assignFormData( id: string, mode: 'info' | 'edit' | 'assign' = 'info', ) { const data = await quotationStore.getQuotation(id); if (!data) return; // NOTE: Error should be handled globally by axios instance quotationFull.value = data; resetFormData = Object.assign(data, { productServiceList: data.productServiceList.map((v) => ({ ...v, workerIndex: v.worker.map((a) => data.worker.findIndex((b) => b.employeeId === a.employeeId), ), })), dueDate: new Date(data.dueDate), payBillDate: data.payBillDate ? new Date(data.payBillDate) : undefined, paySplit: data.paySplit.map((p, index) => ({ no: index + 1, date: p.date, amount: p.amount, })), worker: data.worker.map((v) => Object.assign(v.employee, { dateOfBirth: new Date(v.employee.dateOfBirth), }), ), }); currentFormData.value = structuredClone(resetFormData); currentFormState.value.createdBy = (locale) => locale === 'eng' ? data.createdBy.firstNameEN + ' ' + data.createdBy.lastNameEN : data.createdBy.firstName + ' ' + data.createdBy.lastName; if (mode === 'assign') return; currentFormState.value.mode = mode; } async function submitQuotation() { if (currentFormState.value.mode === 'create') { const res = await quotationStore.createQuotation(currentFormData.value); if (res !== null) { fileItemNewWorker.value.forEach(async (v) => { if (v.group === undefined) return; await employeeStore.postMeta({ group: v.group, parentId: res.worker[v.employeeIndex].employeeId, meta: v._meta, file: v.file, }); }); return true; } } if (currentFormState.value.mode === 'edit' && currentFormData.value.id) { if (currentFormData.value.status === 'CREATED') { delete currentFormData.value?.['status']; } const res = await quotationStore.editQuotation({ ...currentFormData.value, id: currentFormData.value.id, }); if (res) return true; } currentFormState.value.mode = 'info'; currentFormState.value.createdBy = (_) => getName() || ''; } function injectNewEmployee( obj: { data: EmployeeWorker & { attachment?: { name?: string; group?: string; url?: string; file?: File; _meta?: Record; }[]; }; }, callback?: () => void, ) { newWorkerList.value.push({ // passportNo: obj.data.passportNo, wait api add //documentExpireDate: obj.data.documentExpireDate, lastNameEN: obj.data.lastNameEN, lastName: obj.data.lastName, middleNameEN: obj.data.middleNameEN, middleName: obj.data.middleName, firstNameEN: obj.data.firstNameEN, firstName: obj.data.firstName, namePrefix: obj.data.namePrefix, nationality: obj.data.nationality, gender: obj.data.gender, dateOfBirth: obj.data.dateOfBirth, attachment: obj.data.attachment, }); callback?.(); } function dialogDelete(callback: () => void) { dialog({ color: 'negative', icon: 'mdi-alert', title: t('dialog.title.confirmDelete'), actionText: t('general.delete'), persistent: true, message: t('dialog.message.confirmDelete'), action: async () => { callback(); }, cancel: () => {}, }); } return { DEFAULT_DATA, currentFormState, currentFormData, newWorkerList, fileItemNewWorker, quotationFull, isFormDataDifferent, injectNewEmployee, assignFormData, dialogDelete, resetForm, submitQuotation, }; });