refactor: change form employee
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 6s

This commit is contained in:
Thanaphon Frappet 2025-04-08 15:04:03 +07:00
parent 7fcb4d7744
commit bd38c008a6
9 changed files with 1686 additions and 703 deletions

View file

@ -41,6 +41,12 @@ let prefixNameFilter: (
update: (callbackFn: () => void, afterFn?: (ref: QSelect) => void) => void,
) => void;
const prefixNameOptionsEn = ref<Record<string, unknown>[]>([]);
let prefixNameFilterEn: (
value: string,
update: (callbackFn: () => void, afterFn?: (ref: QSelect) => void) => void,
) => void;
const genderOptions = ref<Record<string, unknown>[]>([]);
let genderFilter: (
value: string,
@ -66,6 +72,13 @@ onMounted(() => {
prefixNameOptions,
'label',
);
prefixNameFilterEn = selectFilterOptionRefMod(
ref(optionStore.rawOption?.eng.prefix),
prefixNameOptionsEn,
'label',
);
genderFilter = selectFilterOptionRefMod(
ref(optionStore.globalOption?.gender),
genderOptions,
@ -96,6 +109,12 @@ watch(
nationalityOptions,
'label',
);
prefixNameFilterEn = selectFilterOptionRefMod(
ref(optionStore.rawOption?.eng.prefix),
prefixNameOptionsEn,
'label',
);
},
);
@ -177,6 +196,7 @@ watch(
(v) => (typeof v === 'string' ? (prefixName = v) : '')
"
@clear="prefixName = ''"
:rules="[(val: string) => !!val || $t('form.error.required')]"
>
<template v-slot:no-option>
<q-item>
@ -235,25 +255,41 @@ watch(
class="col-12 row"
style="display: flex; gap: var(--size-2)"
>
<q-input
:for="`${prefixId}-input-first-name`"
:dense="dense"
<q-select
outlined
use-input
fill-input
emit-value
map-options
hide-selected
hide-bottom-space
:readonly="readonly"
:disable="!readonly"
input-debounce="0"
option-label="label"
option-value="value"
hide-dropdown-icon
autocomplete="off"
class="col-md-1 col-6"
label="Title"
:model-value="
readonly
? capitalize(prefixName || '') || '-'
: capitalize(prefixName || '')
"
:dense="dense"
:readonly="readonly"
:options="prefixNameOptionsEn"
:for="`${prefixId}-select-prefix-name-en`"
label="Prefix"
@filter="prefixNameFilter"
:model-value="readonly ? prefixName || '-' : prefixName"
@update:model-value="
(v) => (typeof v === 'string' ? (prefixName = v) : '')
"
@clear="prefixName = ''"
/>
:rules="[(val: string) => !!val || $t('form.error.required')]"
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
{{ $t('general.noData') }}
</q-item-section>
</q-item>
</template>
</q-select>
<q-input
:for="`${prefixId}-input-first-name-en`"

View file

@ -3,6 +3,7 @@ import { QSelect } from 'quasar';
import { CustomerBranch } from 'stores/customer/types';
import { selectFilterOptionRefMod } from 'stores/utils';
import { onMounted, ref, watch } from 'vue';
import SelectCustomer from 'components/shared/select/SelectCustomer.vue';
import {
EditButton,
DeleteButton,
@ -22,6 +23,13 @@ const optionsBranch = defineModel<{ id: string; name: string }[]>(
);
// employee
const customerBranchId = defineModel<string>('customerBranchId');
const currentCustomerBranch = defineModel<CustomerBranch>(
'currentCustomerBranch',
);
const customerBranch = defineModel<{
id: string;
address: string;
@ -108,213 +116,14 @@ defineEmits<{
</div>
<div class="col-12 row" style="gap: var(--size-2)">
<q-select
:id="`${prefixId}-select-employer-branch`"
:for="`${prefixId}-select-employer-branch`"
:use-input="!customerBranch"
autocomplete="off"
input-debounce="0"
:hide-dropdown-icon="readonly"
:dense="dense"
outlined
:readonly="readonly"
hide-bottom-space
class="col-12"
<SelectCustomer
v-model:value="customerBranchId"
v-model:value-option="currentCustomerBranch"
:label="$t('customer.form.branchCode')"
v-model="customerBranch"
:option-value="
(v) => ({
id: v.id,
address: v.address,
addressEN: v.addressEN,
provinceId: v.provinceId,
districtId: v.districtId,
subDistrictId: v.subDistrictId,
zipCode: v.zipCode,
})
"
emit-value
map-options
:options="employeeOwnerOption"
@filter="(val, update) => $emit('filterOwnerBranch', val, update)"
:rules="[
(val: string) =>
!!val ||
$t('form.error.selectField', {
field: $t('customerEmployee.branch'),
}),
]"
>
<template v-slot:option="scope">
<q-item
v-if="scope.opt"
v-bind="scope.itemProps"
class="row items-start col-12 no-padding"
>
<div class="q-ma-sm">
<i class="isax isax-frame5" style="color: var(--brand-1)" />
</div>
<div class="q-mt-sm">
<div>
<span v-if="scope.opt.customer.customerType">
<span style="font-weight: 600">
{{
scope.opt.customer.customerType === 'CORP'
? $t('customer.form.registerName')
: $t('customer.form.ownerName')
}}:
</span>
{{
scope.opt.customer.customerType === 'CORP'
? $i18n.locale === 'eng'
? scope.opt.registerNameEN
: scope.opt.registerName
: $i18n.locale === 'eng'
? `${optionStore.mapOption(scope.opt.namePrefix)} ${scope.opt.firstNameEN} ${scope.opt.lastNameEN}` ||
'-'
: `${optionStore.mapOption(scope.opt.namePrefix)} ${scope.opt.firstName} ${scope.opt.lastName}` ||
'-'
}}
({{ scope.opt.code }})
</span>
</div>
<div class="text-caption app-text-muted-2 q-mb-xs">
<span v-if="scope.opt.customer" class="col column">
{{
$t(
`branch.form.title.${scope.opt.code.endsWith('-00') ? 'branchHQLabel' : 'branchLabel'}`,
)
}}
{{
!scope.opt.code.endsWith('-00')
? +scope.opt.code.split('-')[1]
: ''
}}
</span>
<span v-if="scope.opt.province" class="col">
{{ $t('general.address') }}
{{
formatAddress({
address: scope.opt.address,
addressEN: scope.opt.addressEN,
moo: scope.opt.moo,
mooEN: scope.opt.mooEN,
soi: scope.opt.soi,
soiEN: scope.opt.soiEN,
street: scope.opt.street,
streetEN: scope.opt.streetEN,
subDistrict: scope.opt.subDistrict,
district: scope.opt.district,
province: scope.opt.province,
en: $i18n.locale === 'eng',
})
}}
{{ scope.opt.subDistrict?.zipCode || '' }}
</span>
</div>
</div>
</q-item>
<q-separator class="q-mx-sm" />
</template>
<template v-slot:selected-item="scope">
<div
v-if="scope.opt"
class="row items-center no-wrap"
style="width: 1px"
>
<div class="q-mr-sm">
<span style="font-weight: 600">
{{
scope.opt.customer.customerType === 'CORP'
? $t('customer.form.registerName')
: $t('customer.form.ownerName')
}}:
</span>
{{
scope.opt.customer.customerType === 'CORP'
? $i18n.locale === 'eng'
? scope.opt.registerNameEN
: scope.opt.registerName
: $i18n.locale === 'eng'
? `${optionStore.mapOption(scope.opt.namePrefix)} ${scope.opt.firstNameEN} ${scope.opt.lastNameEN}` ||
'-'
: `${optionStore.mapOption(scope.opt.namePrefix)} ${scope.opt.firstName} ${scope.opt.lastName}` ||
'-'
}}
({{ scope.opt.code }})
</div>
<div
class="text-caption app-text-muted-2"
v-if="scope.opt.customer && scope.opt.province"
>
{{
$t(
`branch.form.title.${scope.opt.code.endsWith('-00') ? 'branchHQLabel' : 'branchLabel'}`,
)
}}
{{
!scope.opt.code.endsWith('-00')
? +scope.opt.code.split('-')[1]
: ''
}}
{{ $t('general.address') }}
{{
formatAddress({
address: scope.opt.address,
addressEN: scope.opt.addressEN,
moo: scope.opt.moo,
mooEN: scope.opt.mooEN,
soi: scope.opt.soi,
soiEN: scope.opt.soiEN,
street: scope.opt.street,
streetEN: scope.opt.streetEN,
subDistrict: scope.opt.subDistrict,
district: scope.opt.district,
province: scope.opt.province,
en: $i18n.locale === 'eng',
})
}}
{{ scope.opt.subDistrict?.zipCode || '' }}
<q-tooltip v-if="scope.opt.customer && scope.opt.province">
{{ $t('customerBranch.form.title') }}:
{{ $t('general.address') }}
{{
formatAddress({
address: scope.opt.address,
addressEN: scope.opt.addressEN,
moo: scope.opt.moo,
mooEN: scope.opt.mooEN,
soi: scope.opt.soi,
soiEN: scope.opt.soiEN,
street: scope.opt.street,
streetEN: scope.opt.streetEN,
subDistrict: scope.opt.subDistrict,
district: scope.opt.district,
province: scope.opt.province,
en: $i18n.locale === 'eng',
})
}}
{{ scope.opt.subDistrict?.zipCode || '' }}
</q-tooltip>
</div>
</div>
</template>
<template v-slot:append>
<q-icon
v-if="!readonly && customerBranch"
name="mdi-close-circle"
@click.stop="customerBranch = undefined"
class="cursor-pointer clear-btn"
/>
</template>
</q-select>
class="col-12 field-two"
required
:readonly
/>
<q-input
:for="`${prefixId}-input-code`"

View file

@ -158,7 +158,7 @@ onMounted(async () => {
</template>
<template #option="{ opt, scope }">
<q-item v-bind="scope.itemProps">
<q-item @click="valueOption = opt" v-bind="scope.itemProps">
<SelectCustomerItem :data="opt" :simple :simple-branch-no />
</q-item>

View file

@ -54,7 +54,9 @@ const columns = [
field: (v: Employee) =>
locale.value === Lang.English
? `${v.firstNameEN} ${v.lastNameEN}`
: `${v.firstName} ${v.lastName}`,
: v.firstName
? `${v.firstName} ${v.lastName}`
: `${v.firstNameEN} ${v.lastNameEN}`,
},
{
name: 'birthDate',

View file

@ -102,7 +102,6 @@ const optionStore = useOptionStore();
const ocrStore = useOcrStore();
const refFilter = ref<InstanceType<typeof QSelect>>();
const statusEmployeeCreate = ref<boolean>(false);
const mrz = ref<Awaited<ReturnType<typeof parseResultMRZ>>>();
const {
@ -114,14 +113,22 @@ const {
deleteCustomerBranchById,
} = customerFormStore;
const { employeeFormUndo, employeeConfirmUnsave, deleteEmployeeById } =
employeeFormStore;
const {
state: customerFormState,
currentFormData: customerFormData,
registerAbleBranchOption,
tabFieldRequired,
} = storeToRefs(customerFormStore);
const { state: employeeFormState, currentFromDataEmployee } =
storeToRefs(employeeFormStore);
const {
state: employeeFormState,
currentFromDataEmployee,
onCreateImageList,
statusEmployeeCreate,
refreshImageState,
} = storeToRefs(employeeFormStore);
async function init() {
navigatorStore.current.title = 'menu.customer';
@ -208,13 +215,7 @@ const dialogCustomerImageUpload = ref<InstanceType<typeof ImageUploadDialog>>();
const dialogEmployeeImageUpload = ref<InstanceType<typeof ImageUploadDialog>>();
// image
const refreshImageState = ref(false);
const imageList = ref<{ selectedImage: string; list: string[] }>();
const onCreateImageList = ref<{
selectedImage: string;
list: { url: string; imgFile: File | null; name: string }[];
}>({ selectedImage: '', list: [] });
watch(() => route.name, init);
watch(
[currentTab, currentStatus, inputSearch, customerTypeSelected, pageSize],
@ -425,64 +426,6 @@ async function toggleStatusCustomer(id: string, status: boolean) {
await fetchListCustomer(false, $q.screen.xs);
flowStore.rotate();
}
async function deleteEmployeeById(opts: {
id?: string;
type?: 'passport' | 'visa' | 'healthCheck' | 'work';
index?: number;
}) {
dialog({
color: 'negative',
icon: 'mdi-alert',
title: t('dialog.title.confirmDelete'),
actionText: t('general.delete'),
persistent: true,
message: t('dialog.message.confirmDelete'),
action: async () => {
if (opts.type === 'passport' && opts.index !== undefined) {
await employeeFormStore.deletePassport(opts.index);
}
if (opts.type === 'visa' && opts.index !== undefined) {
await employeeFormStore.deleteVisa(opts.index);
}
if (opts.type === 'healthCheck' && opts.index !== undefined) {
await employeeFormStore.deleteHealthCheck(opts.index);
}
if (opts.type === 'work' && opts.index !== undefined) {
await employeeFormStore.deleteWorkHistory(opts.index);
} else {
if (!!opts.id) {
const result = await employeeStore.deleteById(opts.id);
if (result) {
employeeFormState.value.drawerModal = false;
employeeFormState.value.dialogModal = false;
}
}
}
if (route.name !== 'CustomerBranchManagement') {
await fetchListEmployee(
currentTab.value === 'employer'
? {
page: 1,
pageSize: 999,
customerId: customerFormState.value.currentCustomerId,
}
: { fetchStats: true, mobileFetch: $q.screen.xs },
);
flowStore.rotate();
}
},
cancel: () => {},
});
}
async function openHistory(id: string) {
const res = await employeeStore.getEditHistory(id);
employeeHistory.value = res.reverse();
@ -516,33 +459,6 @@ async function editEmployeeFormPersonal(id: string) {
employeeFormState.value.drawerModal = true;
}
function employeeConfirmUnsave(close = true) {
dialog({
color: 'warning',
icon: 'mdi-alert',
title: t('form.warning.title'),
actionText: t('general.ok'),
persistent: true,
message: t('form.warning.unsave'),
action: () => {
employeeFormStore.resetFormDataEmployee();
onCreateImageList.value = { selectedImage: '', list: [] };
employeeFormState.value.editReadonly = true;
employeeFormState.value.dialogModal = !close;
employeeFormState.value.drawerModal = !close;
},
cancel: () => {},
});
}
function employeeFormUndo(close = true) {
if (employeeFormStore.isFormDataDifferent()) {
return employeeConfirmUnsave(close);
}
employeeFormStore.resetFormDataEmployee();
employeeFormState.value.editReadonly = true;
}
async function createCustomerForm(customerType: 'CORP' | 'PERS') {
customerFormState.value.dialogModal = true;
customerFormState.value.dialogType = 'create';
@ -577,7 +493,7 @@ async function fetchImageList(
// TODO: When in employee form, if select address same as customer then auto fill
watch(
() => employeeFormState.value.formDataEmployeeOwner,
() => employeeFormState.value.currentCustomerBranch,
(e) => {
if (!e) return;
if (employeeFormState.value.formDataEmployeeSameAddr) {
@ -594,21 +510,21 @@ watch(
watch(
() => employeeFormState.value.formDataEmployeeSameAddr,
(isSame) => {
if (!employeeFormState.value.formDataEmployeeOwner) return;
if (!employeeFormState.value.currentCustomerBranch) return;
if (isSame) {
currentFromDataEmployee.value.address =
employeeFormState.value.formDataEmployeeOwner.address;
employeeFormState.value.currentCustomerBranch.address;
currentFromDataEmployee.value.addressEN =
employeeFormState.value.formDataEmployeeOwner.addressEN;
employeeFormState.value.currentCustomerBranch.addressEN;
currentFromDataEmployee.value.provinceId =
employeeFormState.value.formDataEmployeeOwner.provinceId;
employeeFormState.value.currentCustomerBranch.provinceId;
currentFromDataEmployee.value.districtId =
employeeFormState.value.formDataEmployeeOwner.districtId;
employeeFormState.value.currentCustomerBranch.districtId;
currentFromDataEmployee.value.subDistrictId =
employeeFormState.value.formDataEmployeeOwner.subDistrictId;
employeeFormState.value.currentCustomerBranch.subDistrictId;
}
currentFromDataEmployee.value.customerBranchId =
employeeFormState.value.formDataEmployeeOwner.id;
employeeFormState.value.currentCustomerBranch.id;
},
);
@ -1485,7 +1401,23 @@ const emptyCreateDialog = ref(false);
"
@delete="
(item: any) => {
deleteEmployeeById({ id: item.id });
deleteEmployeeById({
id: item.id,
fetch: async () =>
await fetchListEmployee(
currentTab === 'employer'
? {
page: 1,
pageSize: 999,
customerId:
customerFormState.currentCustomerId,
}
: {
fetchStats: true,
mobileFetch: $q.screen.xs,
},
),
});
}
"
@toggle-status="
@ -1804,7 +1736,23 @@ const emptyCreateDialog = ref(false);
@edit="(item: any) => editEmployeeFormPersonal(item.id)"
@delete="
(item: any) => {
deleteEmployeeById({ id: item.id });
deleteEmployeeById({
id: item.id,
fetch: async () =>
await fetchListEmployee(
currentTab === 'employer'
? {
page: 1,
pageSize: 999,
customerId:
customerFormState.currentCustomerId,
}
: {
fetchStats: true,
mobileFetch: $q.screen.xs,
},
),
});
}
"
@toggle-status="
@ -1942,7 +1890,7 @@ const emptyCreateDialog = ref(false);
async (currentBranch) => {
createEmployeeForm();
await nextTick();
employeeFormState.formDataEmployeeOwner = { ...currentBranch };
employeeFormState.currentBranchId = currentBranch.id;
}
"
v-model:branch="branch"
@ -2783,12 +2731,30 @@ const emptyCreateDialog = ref(false);
id="btn-info-basic-delete"
icon-only
@click="
() => deleteEmployeeById({ id: currentFromDataEmployee.id })
() =>
deleteEmployeeById({
id: currentFromDataEmployee.id,
fetch: async () =>
await fetchListEmployee(
currentTab === 'employer'
? {
page: 1,
pageSize: 999,
customerId:
customerFormState.currentCustomerId,
}
: {
fetchStats: true,
mobileFetch: $q.screen.xs,
},
),
})
"
type="button"
/>
</div>
</div>
<BasicInformation
no-action
id="form-information"
@ -2801,11 +2767,13 @@ const emptyCreateDialog = ref(false);
title="form.field.basicInformation"
:readonly="!employeeFormState.isEmployeeEdit"
:employee-owner-option="employeeStore.ownerOption || []"
v-model:customer-branch="employeeFormState.formDataEmployeeOwner"
v-model:customer-branch-id="employeeFormState.currentBranchId"
v-model:current-customer-branch="
employeeFormState.currentCustomerBranch
"
v-model:employee-id="employeeFormState.currentEmployeeCode"
v-model:nrc-no="currentFromDataEmployee.nrcNo"
v-model:code="currentFromDataEmployee.code"
@filter-owner-branch="employeeFormStore.employeeFilterOwnerBranch"
class="q-mb-xl"
/>
<FormPerson
@ -3362,7 +3330,24 @@ const emptyCreateDialog = ref(false);
@click.stop="
() => {
employeeFormState.currentIndexPassport = index;
deleteEmployeeById({ type: 'passport', index });
deleteEmployeeById({
type: 'passport',
index,
fetch: async () =>
await fetchListEmployee(
currentTab === 'employer'
? {
page: 1,
pageSize: 999,
customerId:
customerFormState.currentCustomerId,
}
: {
fetchStats: true,
mobileFetch: $q.screen.xs,
},
),
});
}
"
type="button"
@ -3513,7 +3498,24 @@ const emptyCreateDialog = ref(false);
@click.stop="
() => {
employeeFormState.currentIndexVisa = index;
deleteEmployeeById({ type: 'visa', index });
deleteEmployeeById({
type: 'visa',
index,
fetch: async () =>
await fetchListEmployee(
currentTab === 'employer'
? {
page: 1,
pageSize: 999,
customerId:
customerFormState.currentCustomerId,
}
: {
fetchStats: true,
mobileFetch: $q.screen.xs,
},
),
});
}
"
type="button"
@ -3585,7 +3587,23 @@ const emptyCreateDialog = ref(false);
@delete="
(index) => {
employeeFormState.currentIndexCheckup = index;
deleteEmployeeById({ type: 'healthCheck', index });
deleteEmployeeById({
type: 'healthCheck',
index,
fetch: async () =>
await fetchListEmployee(
currentTab === 'employer'
? {
page: 1,
pageSize: 999,
customerId: customerFormState.currentCustomerId,
}
: {
fetchStats: true,
mobileFetch: $q.screen.xs,
},
),
});
}
"
@save="
@ -3671,7 +3689,23 @@ const emptyCreateDialog = ref(false);
@delete="
(index) => {
employeeFormState.currentIndexWorkHistory = index;
deleteEmployeeById({ type: 'work', index });
deleteEmployeeById({
type: 'work',
index,
fetch: async () =>
await fetchListEmployee(
currentTab === 'employer'
? {
page: 1,
pageSize: 999,
customerId: customerFormState.currentCustomerId,
}
: {
fetchStats: true,
mobileFetch: $q.screen.xs,
},
),
});
}
"
@save="
@ -4738,7 +4772,23 @@ const emptyCreateDialog = ref(false);
icon-only
@click="
() =>
deleteEmployeeById({ id: currentFromDataEmployee.id })
deleteEmployeeById({
id: currentFromDataEmployee.id,
fetch: async () =>
await fetchListEmployee(
currentTab === 'employer'
? {
page: 1,
pageSize: 999,
customerId:
customerFormState.currentCustomerId,
}
: {
fetchStats: true,
mobileFetch: $q.screen.xs,
},
),
})
"
type="button"
/>
@ -4752,16 +4802,13 @@ const emptyCreateDialog = ref(false);
outlined
title="form.field.basicInformation"
:readonly="!employeeFormState.isEmployeeEdit"
:employee-owner-option="employeeStore.ownerOption"
v-model:customer-branch="
employeeFormState.formDataEmployeeOwner
v-model:customer-branch-id="employeeFormState.currentBranchId"
v-model:current-customer-branch="
employeeFormState.currentCustomerBranch
"
v-model:employee-id="employeeFormState.currentEmployeeCode"
v-model:nrc-no="currentFromDataEmployee.nrcNo"
v-model:code="currentFromDataEmployee.code"
@filter-owner-branch="
employeeFormStore.employeeFilterOwnerBranch
"
class="q-mb-xl"
/>
<FormPerson
@ -5368,6 +5415,20 @@ const emptyCreateDialog = ref(false);
deleteEmployeeById({
type: 'passport',
index,
fetch: async () =>
await fetchListEmployee(
currentTab === 'employer'
? {
page: 1,
pageSize: 999,
customerId:
customerFormState.currentCustomerId,
}
: {
fetchStats: true,
mobileFetch: $q.screen.xs,
},
),
});
}
"
@ -5539,7 +5600,24 @@ const emptyCreateDialog = ref(false);
icon-only
@click.stop="
() => {
deleteEmployeeById({ type: 'visa', index });
deleteEmployeeById({
type: 'visa',
index,
fetch: async () =>
await fetchListEmployee(
currentTab === 'employer'
? {
page: 1,
pageSize: 999,
customerId:
customerFormState.currentCustomerId,
}
: {
fetchStats: true,
mobileFetch: $q.screen.xs,
},
),
});
}
"
type="button"
@ -5660,7 +5738,24 @@ const emptyCreateDialog = ref(false);
@delete="
(index) => {
employeeFormState.currentIndexCheckup = index;
deleteEmployeeById({ type: 'healthCheck', index });
deleteEmployeeById({
type: 'healthCheck',
index,
fetch: async () =>
await fetchListEmployee(
currentTab === 'employer'
? {
page: 1,
pageSize: 999,
customerId:
customerFormState.currentCustomerId,
}
: {
fetchStats: true,
mobileFetch: $q.screen.xs,
},
),
});
}
"
/>
@ -5730,7 +5825,24 @@ const emptyCreateDialog = ref(false);
@delete="
(index) => {
employeeFormState.currentIndexWorkHistory = index;
deleteEmployeeById({ type: 'work', index });
deleteEmployeeById({
type: 'work',
index,
fetch: async () =>
await fetchListEmployee(
currentTab === 'employer'
? {
page: 1,
pageSize: 999,
customerId:
customerFormState.currentCustomerId,
}
: {
fetchStats: true,
mobileFetch: $q.screen.xs,
},
),
});
}
"
@save="

View file

@ -2,6 +2,7 @@ import { ref, watch } from 'vue';
import { defineStore } from 'pinia';
import { useI18n } from 'vue-i18n';
import {
CustomerBranch,
CustomerBranchCreate,
CustomerCreate,
CustomerType,
@ -17,6 +18,7 @@ import useMyBranchStore from 'stores/my-branch';
import { baseUrl } from 'src/stores/utils';
import { getRole, getUserId } from 'src/services/keycloak';
import { useRoute } from 'vue-router';
export const useCustomerForm = defineStore('form-customer', () => {
const customerStore = useCustomerStore();
@ -723,11 +725,23 @@ export const useCustomerBranchForm = defineStore('form-customer-branch', () => {
});
export const useEmployeeForm = defineStore('form-employee', () => {
const { t } = useI18n();
const customerStore = useCustomerStore();
const employeeStore = useEmployeeStore();
const flowStore = useFlowStore();
const branchStore = useMyBranch();
const route = useRoute();
const refreshImageState = ref(false);
const onCreateImageList = ref<{
selectedImage: string;
list: { url: string; imgFile: File | null; name: string }[];
}>({ selectedImage: '', list: [] });
const statusEmployeeCreate = ref<boolean>(false);
const state = ref<{
dialogType: 'info' | 'create' | 'edit';
imageDialog: boolean;
@ -736,6 +750,8 @@ export const useEmployeeForm = defineStore('form-employee', () => {
drawerModal: boolean;
isImageEdit: boolean;
currentBranchId: string;
currentCustomerBranch?: CustomerBranch;
currentEmployeeCode: string;
currentEmployee: Employee | null;
currentIndexPassport: number;
@ -769,6 +785,7 @@ export const useEmployeeForm = defineStore('form-employee', () => {
| undefined;
ocr: boolean;
}>({
currentBranchId: '',
isImageEdit: false,
currentIndexPassport: -1,
currentIndexVisa: -1,
@ -1231,6 +1248,8 @@ export const useEmployeeForm = defineStore('form-employee', () => {
selectedImage: string;
list: { url: string; imgFile: File | null; name: string }[];
}) {
let employeeId: string | undefined = undefined;
currentFromDataEmployee.value.firstName =
currentFromDataEmployee.value.firstName.trim();
currentFromDataEmployee.value.middleName =
@ -1249,7 +1268,7 @@ export const useEmployeeForm = defineStore('form-employee', () => {
const res = await employeeStore.create(
{
...currentFromDataEmployee.value,
customerBranchId: state.value.formDataEmployeeOwner?.id || '',
customerBranchId: state.value.currentBranchId || '',
employeeWork: [],
employeeCheckup: [],
@ -1259,6 +1278,7 @@ export const useEmployeeForm = defineStore('form-employee', () => {
);
if (res) {
employeeId = res.id;
await assignFormDataEmployee(res.id);
currentFromDataEmployee.value.id = res.id;
state.value.statusSavePersonal = true;
@ -1280,10 +1300,12 @@ export const useEmployeeForm = defineStore('form-employee', () => {
},
);
if (res) {
employeeId = res.id;
await assignFormDataEmployee(res.id);
state.value.statusSavePersonal = true;
}
}
return employeeId;
}
async function assignFormDataEmployee(id?: string) {
@ -1424,6 +1446,8 @@ export const useEmployeeForm = defineStore('form-employee', () => {
state.value.currentIndexVisa = -1;
}
state.value.currentBranchId = payload.customerBranchId;
const foundBranch = await customerStore.fetchListCustomerBranchById(
payload.customerBranchId,
);
@ -1550,7 +1574,88 @@ export const useEmployeeForm = defineStore('form-employee', () => {
(currentFromDataEmployee.value.employeeWork?.length || 0) - 1;
}
function employeeFormUndo(close = true) {
if (isFormDataDifferent()) {
return employeeConfirmUnsave(close);
}
resetFormDataEmployee();
state.value.editReadonly = true;
}
function employeeConfirmUnsave(close = true) {
dialog({
color: 'warning',
icon: 'mdi-alert',
title: t('form.warning.title'),
actionText: t('general.ok'),
persistent: true,
message: t('form.warning.unsave'),
action: () => {
resetFormDataEmployee();
onCreateImageList.value = { selectedImage: '', list: [] };
state.value.editReadonly = true;
state.value.dialogModal = !close;
state.value.drawerModal = !close;
},
cancel: () => {},
});
}
async function deleteEmployeeById(opts: {
id?: string;
type?: 'passport' | 'visa' | 'healthCheck' | 'work';
index?: number;
fetch?: (...args: unknown[]) => unknown;
removeArray?: (...args: unknown[]) => unknown;
}) {
dialog({
color: 'negative',
icon: 'mdi-alert',
title: t('dialog.title.confirmDelete'),
actionText: t('general.delete'),
persistent: true,
message: t('dialog.message.confirmDelete'),
action: async () => {
if (opts.type === 'passport' && opts.index !== undefined) {
await deletePassport(opts.index);
}
if (opts.type === 'visa' && opts.index !== undefined) {
await deleteVisa(opts.index);
}
if (opts.type === 'healthCheck' && opts.index !== undefined) {
await deleteHealthCheck(opts.index);
}
if (opts.type === 'work' && opts.index !== undefined) {
await deleteWorkHistory(opts.index);
} else {
if (!!opts.id) {
const result = await employeeStore.deleteById(opts.id);
if (result) {
state.value.drawerModal = false;
state.value.dialogModal = false;
}
}
}
if (route.name !== 'CustomerBranchManagement') {
await opts.fetch?.();
flowStore.rotate();
}
opts.removeArray?.();
},
cancel: () => {},
});
}
return {
refreshImageState,
statusEmployeeCreate,
onCreateImageList,
state,
currentFromDataEmployee,
resetEmployeeData,
@ -1577,5 +1682,9 @@ export const useEmployeeForm = defineStore('form-employee', () => {
employeeFilterOwnerBranch,
isFormDataDifferent,
employeeFormUndo,
employeeConfirmUnsave,
deleteEmployeeById,
};
});

View file

@ -590,8 +590,9 @@ async function convertDataToFormSubmit() {
}
}),
...newWorkerList.value.map((v) => {
const { attachment, ...payload } = v;
return payload;
{
return v.id;
}
}),
]),
);

File diff suppressed because it is too large Load diff

View file

@ -221,6 +221,7 @@ export const useQuotationForm = defineStore('form-quotation', () => {
newWorkerList.value.push({
//passportNo: obj.data.passportNo,
//documentExpireDate: obj.data.documentExpireDate,
id: obj.data.id,
lastNameEN: obj.data.lastNameEN,
lastName: obj.data.lastName,
middleNameEN: obj.data.middleNameEN,