jws-frontend/src/pages/05_quotation/form.ts
2024-12-23 11:30:15 +07:00

299 lines
7.7 KiB
TypeScript

import { dialog } from 'stores/utils';
import { defineStore } from 'pinia';
import { useI18n } from 'vue-i18n';
import { ref } from 'vue';
// NOTE: Import types
import {
QuotationPayload,
QuotationFull,
EmployeeWorker,
} from 'src/stores/quotations/types';
import { Employee } from 'src/stores/employee/types';
import { InvoicePayload } from 'src/stores/payment/types';
import { RequestData, RequestDataStatus } from 'src/stores/request-list/types';
// NOTE: Import stores
import { useQuotationStore } from 'stores/quotations';
import { useInvoice } from 'stores/payment';
import useEmployeeStore from 'stores/employee';
import { getName } from 'src/services/keycloak';
const DEFAULT_DATA: QuotationPayload = {
productServiceList: [],
urgent: false,
customerBranchId: '',
worker: [],
workerMax: 1,
payBillDate: new Date(),
paySplit: [],
paySplitCount: 0,
payCondition: 'Full',
dueDate: new Date(),
discount: 0,
contactTel: '',
contactName: '',
workName: '',
registeredBranchId: '',
_count: { worker: 0 },
status: 'CREATED',
remark: '#[quotation-labor]<br/><br/>#[quotation-payment]',
};
const DEFAULT_DATA_INVOICE: InvoicePayload = {
quotationId: '',
amount: 0,
installmentNo: [],
};
export const useQuotationForm = defineStore('form-quotation', () => {
const { t } = useI18n();
const quotationStore = useQuotationStore();
const employeeStore = useEmployeeStore();
const invoiceStore = useInvoice();
const quotationFull = ref<QuotationFull | undefined>(undefined);
const invoicePayload = ref<InvoicePayload & { id?: string }>(
DEFAULT_DATA_INVOICE,
);
const newWorkerList = ref<
(EmployeeWorker & {
attachment?: {
name?: string;
group?: string;
url?: string;
file?: File;
_meta?: Record<string, any>;
}[];
})[]
>([]);
let resetFormData = structuredClone(DEFAULT_DATA);
const fileItemNewWorker = ref<
{
employeeIndex: number;
name?: string;
group: 'passport' | 'visa' | 'in-country-notice';
url?: string;
file?: File;
_meta?: Record<string, any>;
}[]
>([]);
const currentFormData = ref<QuotationPayload & { id?: string }>(
structuredClone(resetFormData),
);
const currentFormState = ref<{
mode: null | 'info' | 'create' | 'edit';
source?: QuotationFull;
createdAt: string | Date;
createdBy: (locale: string) => string;
inputSearchRequest: string | undefined;
statusFilterRequest: RequestDataStatus | 'All';
}>({
mode: null,
createdBy: (_) => getName() || '',
createdAt: '',
inputSearchRequest: undefined,
statusFilterRequest: 'All',
});
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
currentFormState.value.source = data;
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) => ({
no: p.no,
invoiceId: p.invoiceId || undefined,
name: p.name,
amount: p.amount,
})),
worker: data.worker.map((v) => v.employee),
});
currentFormData.value = structuredClone(resetFormData);
currentFormState.value.createdBy = (locale) =>
locale === 'eng'
? data.createdBy.firstNameEN + ' ' + data.createdBy.lastNameEN
: data.createdBy.firstName + ' ' + data.createdBy.lastName;
currentFormState.value.createdAt = data.createdAt;
if (mode === 'assign') return;
currentFormState.value.mode = mode;
}
async function submitQuotation() {
let status = false;
if (currentFormState.value.mode === 'create') {
const res = await quotationStore.createQuotation(currentFormData.value);
if (res !== null) {
currentFormData.value.id = res.id;
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,
});
});
status = 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) status = true;
}
currentFormState.value.mode = 'info';
if (currentFormData.value.id !== undefined) {
assignFormData(currentFormData.value.id, 'info');
}
currentFormState.value.createdBy = (_) => getName() || '';
return status;
}
function injectNewEmployee(
obj: {
data: EmployeeWorker & {
attachment?: {
name?: string;
group?: string;
url?: string;
file?: File;
_meta?: Record<string, any>;
}[];
};
},
callback?: () => void,
) {
newWorkerList.value.push({
//passportNo: obj.data.passportNo,
//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: () => {},
});
}
async function accepted(id: string) {
const res = await quotationStore.changeStatus(id, 'Accepted');
if (res) {
return true;
}
return false;
}
async function submitInvoice() {
let status = false;
if (invoicePayload.value.id === undefined) {
const res = await invoiceStore.createInvoice(invoicePayload.value);
if (res) status = true;
}
if (invoicePayload.value.id !== undefined) {
const res = await invoiceStore.editInvoice(invoicePayload.value);
if (res) status = true;
}
return status;
}
return {
DEFAULT_DATA,
currentFormState,
currentFormData,
newWorkerList,
fileItemNewWorker,
quotationFull,
invoicePayload,
isFormDataDifferent,
injectNewEmployee,
assignFormData,
dialogDelete,
resetForm,
submitInvoice,
accepted,
submitQuotation,
};
});