refactor: use new select
This commit is contained in:
parent
2ddc101b89
commit
7043c635d5
2 changed files with 811 additions and 618 deletions
|
|
@ -21,20 +21,18 @@ import { useInvoice, useReceipt, usePayment } from 'stores/payment';
|
||||||
import useCustomerStore from 'stores/customer';
|
import useCustomerStore from 'stores/customer';
|
||||||
import useOptionStore from 'stores/options';
|
import useOptionStore from 'stores/options';
|
||||||
import { useQuotationForm } from './form';
|
import { useQuotationForm } from './form';
|
||||||
import useOcrStore from 'stores/ocr';
|
|
||||||
import { deleteItem } from 'stores/utils';
|
import { deleteItem } from 'stores/utils';
|
||||||
import { runOcr, parseResultMRZ } from 'src/utils/ocr';
|
|
||||||
|
|
||||||
// NOTE Import Types
|
// NOTE Import Types
|
||||||
import { RequestData, RequestDataStatus } from 'src/stores/request-list/types';
|
import { RequestData, RequestDataStatus } from 'src/stores/request-list/types';
|
||||||
import { View } from './types.ts';
|
import { View } from './types.ts';
|
||||||
import {
|
import {
|
||||||
|
EmployeeWorker,
|
||||||
PayCondition,
|
PayCondition,
|
||||||
ProductServiceList,
|
ProductServiceList,
|
||||||
QuotationPayload,
|
QuotationPayload,
|
||||||
} from 'src/stores/quotations/types';
|
} from 'src/stores/quotations/types';
|
||||||
import { EmployeeWorker } from 'src/stores/quotations/types';
|
import { Employee, EmployeeWork } from 'src/stores/employee/types';
|
||||||
import { Employee } from 'src/stores/employee/types';
|
|
||||||
import { Receipt } from 'src/stores/payment/types';
|
import { Receipt } from 'src/stores/payment/types';
|
||||||
import {
|
import {
|
||||||
ProductGroup,
|
ProductGroup,
|
||||||
|
|
@ -46,24 +44,17 @@ import {
|
||||||
import TableRequest from './TableRequest.vue';
|
import TableRequest from './TableRequest.vue';
|
||||||
import SelectInput from 'components/shared/SelectInput.vue';
|
import SelectInput from 'components/shared/SelectInput.vue';
|
||||||
import SwitchItem from 'components/shared/SwitchItem.vue';
|
import SwitchItem from 'components/shared/SwitchItem.vue';
|
||||||
import FormEmployeePassport from 'components/03_customer-management/FormEmployeePassport.vue';
|
|
||||||
import FormEmployeeVisa from 'components/03_customer-management/FormEmployeeVisa.vue';
|
|
||||||
import FormReferDocument from 'src/components/05_quotation/FormReferDocument.vue';
|
|
||||||
import { UploadFileGroup, NoticeJobEmployment } from 'components/upload-file';
|
|
||||||
import FormPerson from 'components/02_personnel-management/FormPerson.vue';
|
|
||||||
import ProductItem from 'components/05_quotation/ProductItem.vue';
|
import ProductItem from 'components/05_quotation/ProductItem.vue';
|
||||||
import WorkerItem from 'components/05_quotation/WorkerItem.vue';
|
import WorkerItem from 'components/05_quotation/WorkerItem.vue';
|
||||||
import ToggleButton from 'components/button/ToggleButton.vue';
|
import ToggleButton from 'components/button/ToggleButton.vue';
|
||||||
import FormAbout from 'components/05_quotation/FormAbout.vue';
|
import FormAbout from 'components/05_quotation/FormAbout.vue';
|
||||||
import SelectZone from 'components/shared/SelectZone.vue';
|
import SelectZone from 'components/shared/SelectZone.vue';
|
||||||
import PersonCard from 'components/shared/PersonCard.vue';
|
|
||||||
import ImportWorker from './ImportWorker.vue';
|
import ImportWorker from './ImportWorker.vue';
|
||||||
import {
|
import {
|
||||||
AddButton,
|
AddButton,
|
||||||
SaveButton,
|
SaveButton,
|
||||||
EditButton,
|
EditButton,
|
||||||
UndoButton,
|
UndoButton,
|
||||||
DeleteButton,
|
|
||||||
CloseButton,
|
CloseButton,
|
||||||
MainButton,
|
MainButton,
|
||||||
} from 'components/button';
|
} from 'components/button';
|
||||||
|
|
@ -72,12 +63,6 @@ import QuotationFormProductSelect from './QuotationFormProductSelect.vue';
|
||||||
import QuotationFormInfo from './QuotationFormInfo.vue';
|
import QuotationFormInfo from './QuotationFormInfo.vue';
|
||||||
import QuotationFormWorkerSelect from './QuotationFormWorkerSelect.vue';
|
import QuotationFormWorkerSelect from './QuotationFormWorkerSelect.vue';
|
||||||
import QuotationFormWorkerAddDialog from './QuotationFormWorkerAddDialog.vue';
|
import QuotationFormWorkerAddDialog from './QuotationFormWorkerAddDialog.vue';
|
||||||
import ProfileBanner from 'components/ProfileBanner.vue';
|
|
||||||
import DialogForm from 'components/DialogForm.vue';
|
|
||||||
import {
|
|
||||||
uploadFileListEmployee,
|
|
||||||
columnsAttachment,
|
|
||||||
} from 'src/pages/03_customer-management/constant';
|
|
||||||
import UploadFileSection from 'src/components/upload-file/UploadFileSection.vue';
|
import UploadFileSection from 'src/components/upload-file/UploadFileSection.vue';
|
||||||
|
|
||||||
import { columnPaySplit } from './constants';
|
import { columnPaySplit } from './constants';
|
||||||
|
|
@ -111,7 +96,6 @@ const route = useRoute();
|
||||||
const useReceiptStore = useReceipt();
|
const useReceiptStore = useReceipt();
|
||||||
const configStore = useConfigStore();
|
const configStore = useConfigStore();
|
||||||
const productServiceStore = useProductServiceStore();
|
const productServiceStore = useProductServiceStore();
|
||||||
const employeeFormStore = useEmployeeForm();
|
|
||||||
const customerStore = useCustomerStore();
|
const customerStore = useCustomerStore();
|
||||||
const quotationForm = useQuotationForm();
|
const quotationForm = useQuotationForm();
|
||||||
const quotationStore = useQuotationStore();
|
const quotationStore = useQuotationStore();
|
||||||
|
|
@ -120,7 +104,6 @@ const paymentStore = usePayment();
|
||||||
const optionStore = useOptionStore();
|
const optionStore = useOptionStore();
|
||||||
const requestStore = useRequestList();
|
const requestStore = useRequestList();
|
||||||
const { t, locale } = useI18n();
|
const { t, locale } = useI18n();
|
||||||
const ocrStore = useOcrStore();
|
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
const openQuotation = ref<boolean>(false);
|
const openQuotation = ref<boolean>(false);
|
||||||
const formMetadata = ref();
|
const formMetadata = ref();
|
||||||
|
|
@ -145,8 +128,6 @@ const receiptList = ref<Receipt[]>([]);
|
||||||
const templateForm = ref<string>('');
|
const templateForm = ref<string>('');
|
||||||
const templateFormOption = ref<{ label: string; value: string }[]>([]);
|
const templateFormOption = ref<{ label: string; value: string }[]>([]);
|
||||||
|
|
||||||
const refSelectZoneEmployee = ref<InstanceType<typeof SelectZone>>();
|
|
||||||
const mrz = ref<Awaited<ReturnType<typeof parseResultMRZ>>>();
|
|
||||||
const toggleWorker = ref(true);
|
const toggleWorker = ref(true);
|
||||||
const tempTableProduct = ref<ProductServiceList[]>([]);
|
const tempTableProduct = ref<ProductServiceList[]>([]);
|
||||||
const tempPaySplitCount = ref(0);
|
const tempPaySplitCount = ref(0);
|
||||||
|
|
@ -155,14 +136,12 @@ const tempPaySplit = ref<
|
||||||
>([]);
|
>([]);
|
||||||
const currentQuotationId = ref<string | undefined>(undefined);
|
const currentQuotationId = ref<string | undefined>(undefined);
|
||||||
const date = ref();
|
const date = ref();
|
||||||
const preSelectedWorker = ref<Employee[]>([]);
|
|
||||||
const readonly = computed(() => {
|
const readonly = computed(() => {
|
||||||
return !(
|
return !(
|
||||||
quotationFormState.value.mode === 'create' ||
|
quotationFormState.value.mode === 'create' ||
|
||||||
quotationFormState.value.mode === 'edit'
|
quotationFormState.value.mode === 'edit'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
const test = ref<boolean>(false);
|
|
||||||
|
|
||||||
const selectedWorker = ref<
|
const selectedWorker = ref<
|
||||||
(Employee & {
|
(Employee & {
|
||||||
|
|
@ -175,30 +154,47 @@ const selectedWorker = ref<
|
||||||
}[];
|
}[];
|
||||||
})[]
|
})[]
|
||||||
>([]);
|
>([]);
|
||||||
const selectedWorkerItem = computed(() =>
|
const selectedWorkerItem = computed(() => {
|
||||||
selectedWorker.value.map((e) => ({
|
return [
|
||||||
foreignRefNo: e.employeePassport
|
...selectedWorker.value.map((e) => ({
|
||||||
? e.employeePassport[0]?.number || '-'
|
foreignRefNo: e.employeePassport
|
||||||
: '-',
|
? e.employeePassport[0]?.number || '-'
|
||||||
employeeName:
|
|
||||||
locale.value === Lang.English
|
|
||||||
? `${e.firstNameEN} ${e.lastNameEN}`
|
|
||||||
: `${e.firstName} ${e.lastName}`,
|
|
||||||
birthDate: dateFormatJS({ date: e.dateOfBirth }),
|
|
||||||
gender: e.gender,
|
|
||||||
age: calculateAge(e.dateOfBirth),
|
|
||||||
nationality: optionStore.mapOption(e.nationality),
|
|
||||||
documentExpireDate:
|
|
||||||
e.employeePassport !== undefined &&
|
|
||||||
e.employeePassport[0]?.expireDate !== undefined
|
|
||||||
? dateFormatJS({ date: e.employeePassport[0]?.expireDate })
|
|
||||||
: '-',
|
: '-',
|
||||||
imgUrl: e.selectedImage
|
employeeName:
|
||||||
? `${API_BASE_URL}/employee/${e.id}/image/${e.selectedImage}`
|
locale.value === Lang.English
|
||||||
: '',
|
? `${e.firstNameEN} ${e.lastNameEN}`
|
||||||
status: e.status,
|
: `${e.firstName} ${e.lastName}`,
|
||||||
})),
|
birthDate: dateFormatJS({ date: e.dateOfBirth }),
|
||||||
);
|
gender: e.gender,
|
||||||
|
age: calculateAge(e.dateOfBirth),
|
||||||
|
nationality: optionStore.mapOption(e.nationality),
|
||||||
|
documentExpireDate:
|
||||||
|
e.employeePassport !== undefined &&
|
||||||
|
e.employeePassport[0]?.expireDate !== undefined
|
||||||
|
? dateFormatJS({ date: e.employeePassport[0]?.expireDate })
|
||||||
|
: '-',
|
||||||
|
imgUrl: e.selectedImage
|
||||||
|
? `${API_BASE_URL}/employee/${e.id}/image/${e.selectedImage}`
|
||||||
|
: '',
|
||||||
|
status: e.status,
|
||||||
|
})),
|
||||||
|
|
||||||
|
...newWorkerList.value.map((v: any) => ({
|
||||||
|
foreignRefNo: v.passportNo,
|
||||||
|
employeeName:
|
||||||
|
locale.value === Lang.English
|
||||||
|
? `${v.firstNameEN} ${v.lastNameEN}`
|
||||||
|
: `${v.firstName} ${v.lastName}`,
|
||||||
|
birthDate: dateFormatJS({ date: v.dateOfBirth }),
|
||||||
|
gender: v.gender,
|
||||||
|
age: calculateAge(v.dateOfBirth),
|
||||||
|
nationality: optionStore.mapOption(v.nationality),
|
||||||
|
documentExpireDate: '-',
|
||||||
|
imgUrl: '',
|
||||||
|
status: 'CREATED',
|
||||||
|
})),
|
||||||
|
];
|
||||||
|
});
|
||||||
const workerList = ref<Employee[]>([]);
|
const workerList = ref<Employee[]>([]);
|
||||||
|
|
||||||
const selectedProductGroup = ref('');
|
const selectedProductGroup = ref('');
|
||||||
|
|
@ -300,36 +296,7 @@ const pageState = reactive({
|
||||||
const productList = ref<Partial<Record<ProductGroupId, Product[]>>>({});
|
const productList = ref<Partial<Record<ProductGroupId, Product[]>>>({});
|
||||||
const serviceList = ref<Partial<Record<ProductGroupId, Service[]>>>({});
|
const serviceList = ref<Partial<Record<ProductGroupId, Service[]>>>({});
|
||||||
const productGroup = ref<ProductGroup[]>([]);
|
const productGroup = ref<ProductGroup[]>([]);
|
||||||
|
|
||||||
const { state: employeeFormState, currentFromDataEmployee } =
|
|
||||||
storeToRefs(employeeFormStore);
|
|
||||||
|
|
||||||
const selectedGroupSub = ref<'product' | 'service' | null>(null);
|
const selectedGroupSub = ref<'product' | 'service' | null>(null);
|
||||||
const formDataEmployee = ref<
|
|
||||||
EmployeeWorker & {
|
|
||||||
attachment?: {
|
|
||||||
name?: string;
|
|
||||||
group?: string;
|
|
||||||
url?: string;
|
|
||||||
file?: File;
|
|
||||||
_meta?: Record<string, any>;
|
|
||||||
}[];
|
|
||||||
}
|
|
||||||
>({
|
|
||||||
passportNo: '',
|
|
||||||
documentExpireDate: new Date(),
|
|
||||||
lastNameEN: '',
|
|
||||||
lastName: '',
|
|
||||||
middleNameEN: '',
|
|
||||||
middleName: '',
|
|
||||||
firstNameEN: '',
|
|
||||||
firstName: '',
|
|
||||||
namePrefix: '',
|
|
||||||
nationality: '',
|
|
||||||
gender: '',
|
|
||||||
dateOfBirth: new Date(),
|
|
||||||
attachment: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
const productServiceList = ref<
|
const productServiceList = ref<
|
||||||
Required<QuotationPayload['productServiceList'][number]>[]
|
Required<QuotationPayload['productServiceList'][number]>[]
|
||||||
|
|
@ -599,16 +566,17 @@ async function convertDataToFormSubmit() {
|
||||||
});
|
});
|
||||||
|
|
||||||
quotationFormData.value.worker = JSON.parse(
|
quotationFormData.value.worker = JSON.parse(
|
||||||
JSON.stringify(
|
JSON.stringify([
|
||||||
selectedWorker.value.map((v) => {
|
...selectedWorker.value.map((v) => {
|
||||||
if (v.id === undefined) {
|
{
|
||||||
const { attachment, ...payload } = v;
|
|
||||||
return payload;
|
|
||||||
} else {
|
|
||||||
return v.id;
|
return v.id;
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
),
|
...newWorkerList.value.map((v) => {
|
||||||
|
const { attachment, ...payload } = v;
|
||||||
|
return payload;
|
||||||
|
}),
|
||||||
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
quotationFormData.value.paySplit = JSON.parse(
|
quotationFormData.value.paySplit = JSON.parse(
|
||||||
|
|
@ -639,6 +607,7 @@ async function convertDataToFormSubmit() {
|
||||||
remark: quotationFormData.value.remark || '',
|
remark: quotationFormData.value.remark || '',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
newWorkerList.value = [];
|
||||||
const res = await quotationForm.submitQuotation();
|
const res = await quotationForm.submitQuotation();
|
||||||
|
|
||||||
if (res === true) {
|
if (res === true) {
|
||||||
|
|
@ -673,26 +642,6 @@ async function getAllProduct(
|
||||||
if (ret) productList.value[groupId] = ret.result;
|
if (ret) productList.value[groupId] = ret.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDefaultFormEmployee() {
|
|
||||||
formDataEmployee.value = {
|
|
||||||
passportNo: '',
|
|
||||||
documentExpireDate: new Date(),
|
|
||||||
lastNameEN: '',
|
|
||||||
lastName: '',
|
|
||||||
middleNameEN: '',
|
|
||||||
middleName: '',
|
|
||||||
firstNameEN: '',
|
|
||||||
firstName: '',
|
|
||||||
namePrefix: '',
|
|
||||||
nationality: '',
|
|
||||||
gender: '',
|
|
||||||
dateOfBirth: new Date(),
|
|
||||||
attachment: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
employeeFormState.value.dialogModal = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getAllService(
|
async function getAllService(
|
||||||
groupId: string,
|
groupId: string,
|
||||||
opts?: { force?: boolean; page?: number; pageSize?: number; query?: string },
|
opts?: { force?: boolean; page?: number; pageSize?: number; query?: string },
|
||||||
|
|
@ -712,14 +661,6 @@ async function getAllService(
|
||||||
if (ret) serviceList.value[groupId] = ret.result;
|
if (ret) serviceList.value[groupId] = ret.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function triggerCreateEmployee() {
|
|
||||||
employeeFormStore.resetFormDataEmployee(true);
|
|
||||||
setDefaultFormEmployee();
|
|
||||||
employeeFormState.value.dialogType = 'create';
|
|
||||||
employeeFormState.value.dialogModal = true;
|
|
||||||
employeeFormState.value.isEmployeeEdit = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function triggerSelectEmployeeDialog() {
|
async function triggerSelectEmployeeDialog() {
|
||||||
pageState.employeeModal = true;
|
pageState.employeeModal = true;
|
||||||
await nextTick();
|
await nextTick();
|
||||||
|
|
@ -2275,10 +2216,11 @@ watch(
|
||||||
v-model:open="pageState.employeeModal"
|
v-model:open="pageState.employeeModal"
|
||||||
@success="
|
@success="
|
||||||
(v) => {
|
(v) => {
|
||||||
selectedWorker = v;
|
console.log(v.newWorker);
|
||||||
|
selectedWorker = v.worker;
|
||||||
|
newWorkerList = v.newWorker;
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
@trigger-create-employee="() => triggerCreateEmployee()"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- add product service -->
|
<!-- add product service -->
|
||||||
|
|
@ -2311,438 +2253,6 @@ watch(
|
||||||
></QuotationFormProductSelect>
|
></QuotationFormProductSelect>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- NOTE: START - Employee Add Form -->
|
|
||||||
|
|
||||||
<DialogForm
|
|
||||||
hide-footer
|
|
||||||
ref="formDialogRef"
|
|
||||||
v-model:modal="employeeFormState.dialogModal"
|
|
||||||
:title="$t('form.title.create', { name: $t('customer.employee') })"
|
|
||||||
:submit="
|
|
||||||
() => {
|
|
||||||
quotationForm.injectNewEmployee({ data: formDataEmployee }, () =>
|
|
||||||
setDefaultFormEmployee(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
"
|
|
||||||
:close="
|
|
||||||
() => {
|
|
||||||
employeeFormState.dialogModal = false;
|
|
||||||
}
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
:class="{
|
|
||||||
'q-mx-lg q-my-md': $q.screen.gt.sm,
|
|
||||||
'q-mx-md q-my-sm': !$q.screen.gt.sm,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<ProfileBanner
|
|
||||||
prefix="dialog"
|
|
||||||
active
|
|
||||||
useToggle
|
|
||||||
color="white"
|
|
||||||
icon="mdi-account-plus-outline"
|
|
||||||
:bg-color="
|
|
||||||
employeeFormState.profileUrl
|
|
||||||
? 'white'
|
|
||||||
: 'linear-gradient(135deg, rgba(43,137,223,1) 0%, rgba(230,51,81,1) 100%)'
|
|
||||||
"
|
|
||||||
v-model:current-tab="employeeFormState.currentTab"
|
|
||||||
v-model:toggle-status="currentFromDataEmployee.status"
|
|
||||||
fallbackCover="/images/employee-banner.png"
|
|
||||||
:img="employeeFormState.profileUrl || `/images/employee-avatar.png`"
|
|
||||||
:toggleTitle="$t('status.title')"
|
|
||||||
hideFade
|
|
||||||
@view="
|
|
||||||
() => {
|
|
||||||
employeeFormState.imageDialog = true;
|
|
||||||
employeeFormState.isImageEdit = false;
|
|
||||||
}
|
|
||||||
"
|
|
||||||
@edit="
|
|
||||||
employeeFormState.imageDialog = employeeFormState.isImageEdit = true
|
|
||||||
"
|
|
||||||
@update:toggle-status="
|
|
||||||
() => {
|
|
||||||
currentFromDataEmployee.status =
|
|
||||||
currentFromDataEmployee.status === 'CREATED'
|
|
||||||
? 'INACTIVE'
|
|
||||||
: 'CREATED';
|
|
||||||
}
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="col"
|
|
||||||
:class="{
|
|
||||||
'q-px-lg q-pb-lg': $q.screen.gt.sm,
|
|
||||||
'q-px-md q-pb-sm': !$q.screen.gt.sm,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style="overflow-y: auto"
|
|
||||||
class="row full-width full-height surface-1 rounded bordered relative-position"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
:class="{
|
|
||||||
'q-py-md q-px-lg': $q.screen.gt.sm,
|
|
||||||
'q-py-sm q-px-lg': !$q.screen.gt.sm,
|
|
||||||
}"
|
|
||||||
style="position: absolute; z-index: 99999; top: 0; right: 0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
v-if="currentFromDataEmployee.status !== 'INACTIVE'"
|
|
||||||
class="surface-1 row rounded"
|
|
||||||
>
|
|
||||||
<UndoButton
|
|
||||||
v-if="
|
|
||||||
employeeFormState.isEmployeeEdit &&
|
|
||||||
employeeFormState.dialogType !== 'create'
|
|
||||||
"
|
|
||||||
id="btn-info-basic-undo"
|
|
||||||
icon-only
|
|
||||||
@click="
|
|
||||||
() => {
|
|
||||||
employeeFormStore.resetFormDataEmployee();
|
|
||||||
employeeFormState.isEmployeeEdit = false;
|
|
||||||
employeeFormState.dialogType = 'info';
|
|
||||||
}
|
|
||||||
"
|
|
||||||
type="button"
|
|
||||||
/>
|
|
||||||
<SaveButton
|
|
||||||
v-if="employeeFormState.isEmployeeEdit"
|
|
||||||
id="btn-info-basic-save"
|
|
||||||
icon-only
|
|
||||||
type="submit"
|
|
||||||
/>
|
|
||||||
<EditButton
|
|
||||||
v-if="!employeeFormState.isEmployeeEdit"
|
|
||||||
id="btn-info-basic-edit"
|
|
||||||
icon-only
|
|
||||||
@click="
|
|
||||||
() => {
|
|
||||||
employeeFormState.isEmployeeEdit = true;
|
|
||||||
employeeFormState.dialogType = 'edit';
|
|
||||||
}
|
|
||||||
"
|
|
||||||
type="button"
|
|
||||||
/>
|
|
||||||
<DeleteButton
|
|
||||||
v-if="!employeeFormState.isEmployeeEdit"
|
|
||||||
id="btn-info-basic-delete"
|
|
||||||
icon-only
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="col-12 full-height q-col-gutter-sm q-py-md q-pl-md q-pr-sm"
|
|
||||||
:class="{
|
|
||||||
'q-py-md q-pr-md ': $q.screen.gt.sm,
|
|
||||||
'q-py-md q-px-lg': !$q.screen.gt.sm,
|
|
||||||
}"
|
|
||||||
id="branch-form"
|
|
||||||
style="overflow-y: auto"
|
|
||||||
>
|
|
||||||
<FormReferDocument
|
|
||||||
title="form.field.basicInformation"
|
|
||||||
prefixId="dialog"
|
|
||||||
dense
|
|
||||||
v-model:passport-no="formDataEmployee.passportNo"
|
|
||||||
v-model:document-expire-date="formDataEmployee.documentExpireDate"
|
|
||||||
class="q-mb-md"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormPerson
|
|
||||||
id="form-personal"
|
|
||||||
prefix-id="form-employee"
|
|
||||||
dense
|
|
||||||
outlined
|
|
||||||
employee
|
|
||||||
separator
|
|
||||||
hideNameEn
|
|
||||||
title="personnel.form.personalInformation"
|
|
||||||
class="q-mb-md"
|
|
||||||
v-model:prefix-name="formDataEmployee.namePrefix"
|
|
||||||
v-model:first-name="formDataEmployee.firstName"
|
|
||||||
v-model:mid-name="formDataEmployee.middleName"
|
|
||||||
v-model:last-name="formDataEmployee.lastName"
|
|
||||||
v-model:birth-date="formDataEmployee.dateOfBirth"
|
|
||||||
v-model:gender="formDataEmployee.gender"
|
|
||||||
v-model:nationality="formDataEmployee.nationality"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<UploadFileGroup
|
|
||||||
show-title
|
|
||||||
v-model="formDataEmployee.attachment"
|
|
||||||
hide-action
|
|
||||||
@submit="
|
|
||||||
async (group, allMeta) => {
|
|
||||||
if (allMeta === undefined) return;
|
|
||||||
|
|
||||||
if (group === 'passport') {
|
|
||||||
const fullName = allMeta['full_name'].split(' ');
|
|
||||||
let tempValue: {
|
|
||||||
oldData: { nameField: string; value: string }[];
|
|
||||||
newData: { nameField: string; value: string }[];
|
|
||||||
} = { oldData: [], newData: [] };
|
|
||||||
|
|
||||||
if (
|
|
||||||
formDataEmployee.gender !== '' &&
|
|
||||||
formDataEmployee.gender !== allMeta['sex']
|
|
||||||
) {
|
|
||||||
tempValue.oldData.push({
|
|
||||||
nameField: $t('form.gender'),
|
|
||||||
value: $t(`general.${formDataEmployee.gender}`),
|
|
||||||
});
|
|
||||||
tempValue.newData.push({
|
|
||||||
nameField: $t('form.gender'),
|
|
||||||
value: $t(`general.${allMeta['sex']}`),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (formDataEmployee.firstName !== '') {
|
|
||||||
tempValue.oldData.push({
|
|
||||||
nameField: $t('personnel.form.firstName'),
|
|
||||||
value: formDataEmployee.firstName,
|
|
||||||
});
|
|
||||||
tempValue.newData.push({
|
|
||||||
nameField: $t('personnel.form.firstName'),
|
|
||||||
value: fullName[0],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (formDataEmployee.lastName !== '') {
|
|
||||||
tempValue.oldData.push({
|
|
||||||
nameField: $t('personnel.form.lastName'),
|
|
||||||
value: formDataEmployee.lastName,
|
|
||||||
});
|
|
||||||
tempValue.newData.push({
|
|
||||||
nameField: $t('personnel.form.lastName'),
|
|
||||||
value: fullName[1],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (formDataEmployee.passportNo !== '') {
|
|
||||||
tempValue.oldData.push({
|
|
||||||
nameField: $t('customerEmployee.form.passportNo'),
|
|
||||||
value: formDataEmployee.passportNo || '',
|
|
||||||
});
|
|
||||||
tempValue.newData.push({
|
|
||||||
nameField: $t('customerEmployee.form.passportNo'),
|
|
||||||
value: allMeta['doc_number'],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (formDataEmployee.nationality !== '') {
|
|
||||||
tempValue.oldData.push({
|
|
||||||
nameField: $t('general.nationality'),
|
|
||||||
value: formDataEmployee.nationality || '',
|
|
||||||
});
|
|
||||||
tempValue.newData.push({
|
|
||||||
nameField: $t('general.nationality'),
|
|
||||||
value: allMeta['nationality'],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
dialogCheckData({
|
|
||||||
action: async () => {
|
|
||||||
formDataEmployee.gender = allMeta['sex'];
|
|
||||||
formDataEmployee.firstName = fullName[0];
|
|
||||||
formDataEmployee.lastName = fullName[1];
|
|
||||||
formDataEmployee.passportNo = allMeta['doc_number'];
|
|
||||||
formDataEmployee.nationality = allMeta['nationality'];
|
|
||||||
},
|
|
||||||
checkData: () => {
|
|
||||||
return tempValue;
|
|
||||||
},
|
|
||||||
cancel: () => {
|
|
||||||
if (!formDataEmployee.gender) {
|
|
||||||
formDataEmployee.gender = allMeta['gender'];
|
|
||||||
}
|
|
||||||
if (!formDataEmployee.firstName) {
|
|
||||||
formDataEmployee.firstName = fullName[0];
|
|
||||||
}
|
|
||||||
if (!formDataEmployee.firstName) {
|
|
||||||
formDataEmployee.firstName = fullName[0];
|
|
||||||
}
|
|
||||||
if (!formDataEmployee.lastName) {
|
|
||||||
formDataEmployee.lastName = fullName[1];
|
|
||||||
}
|
|
||||||
if (!formDataEmployee.passportNo) {
|
|
||||||
formDataEmployee.passportNo = allMeta['doc_number'];
|
|
||||||
}
|
|
||||||
if (!formDataEmployee.nationality) {
|
|
||||||
formDataEmployee.nationality = allMeta['nationality'];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"
|
|
||||||
:menu="uploadFileListEmployee"
|
|
||||||
:columns="columnsAttachment"
|
|
||||||
:ocr="
|
|
||||||
async (group, file) => {
|
|
||||||
if (group === 'passport') {
|
|
||||||
mrz = await runOcr(file, parseResultMRZ);
|
|
||||||
|
|
||||||
if (mrz !== null) {
|
|
||||||
const mapMrz = Object.entries(mrz.result || {}).map(
|
|
||||||
([key, value]) => ({
|
|
||||||
name: key,
|
|
||||||
value: value,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
const tempValue = {
|
|
||||||
status: true,
|
|
||||||
group,
|
|
||||||
meta: mapMrz,
|
|
||||||
};
|
|
||||||
|
|
||||||
return tempValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (group === 'visa') {
|
|
||||||
const res = await ocrStore.sendOcr({
|
|
||||||
file: file,
|
|
||||||
category: group,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (res) {
|
|
||||||
const tempValue = {
|
|
||||||
status: true,
|
|
||||||
group,
|
|
||||||
meta: res.fields,
|
|
||||||
};
|
|
||||||
|
|
||||||
return tempValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return { status: true, group, meta: [] };
|
|
||||||
}
|
|
||||||
"
|
|
||||||
:delete-item="
|
|
||||||
async () => {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
"
|
|
||||||
:get-file-list="
|
|
||||||
async (group: 'passport' | 'visa' | 'attachment') => {
|
|
||||||
if (!!currentFromDataEmployee.id && group !== 'attachment') {
|
|
||||||
const resMeta = await employeeStore.getMetaList({
|
|
||||||
parentId: currentFromDataEmployee.id,
|
|
||||||
group,
|
|
||||||
});
|
|
||||||
|
|
||||||
const tempValue = resMeta.map(async (i: any) => {
|
|
||||||
return {
|
|
||||||
_meta: { ...i },
|
|
||||||
name: `${group}-${dateFormat(i.expireDate)}` || '',
|
|
||||||
group: group,
|
|
||||||
url: await employeeStore.getFile({
|
|
||||||
parentId: currentFromDataEmployee.id || '',
|
|
||||||
group,
|
|
||||||
fileId: i.id,
|
|
||||||
}),
|
|
||||||
file: undefined,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return await waitAll(tempValue);
|
|
||||||
} else {
|
|
||||||
const res = await employeeStore.listAttachment({
|
|
||||||
parentId: currentFromDataEmployee.id || '',
|
|
||||||
});
|
|
||||||
|
|
||||||
const tempValue = (res as string[]).map(async (i: any) => {
|
|
||||||
return {
|
|
||||||
_meta: { id: i, name: i },
|
|
||||||
name: i || '',
|
|
||||||
group: group,
|
|
||||||
url: await employeeStore.getAttachment({
|
|
||||||
parentId: currentFromDataEmployee.id || '',
|
|
||||||
name: i,
|
|
||||||
}),
|
|
||||||
file: undefined,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return await waitAll(tempValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<template #form="{ mode, meta, isEdit }">
|
|
||||||
<FormEmployeePassport
|
|
||||||
v-if="mode === 'passport' && meta"
|
|
||||||
prefix-id="drawer-info-employee"
|
|
||||||
id="form-passport"
|
|
||||||
dense
|
|
||||||
outlined
|
|
||||||
separator
|
|
||||||
ocr
|
|
||||||
:title="$t('customerEmployee.form.group.passport')"
|
|
||||||
:readonly="!isEdit"
|
|
||||||
v-model:birth-country="meta.birthCountry"
|
|
||||||
v-model:previous-passportRef="meta.previousPassportRef"
|
|
||||||
v-model:issue-place="meta.issuePlace"
|
|
||||||
v-model:issue-country="meta.issueCountry"
|
|
||||||
v-model:issue-date="meta.issueDate"
|
|
||||||
v-model:type="meta.type"
|
|
||||||
v-model:expire-date="meta.expireDate"
|
|
||||||
v-model:birth-date="meta.birthDate"
|
|
||||||
v-model:worker-status="meta.workerStatus"
|
|
||||||
v-model:nationality="meta.nationality"
|
|
||||||
v-model:gender="meta.gender"
|
|
||||||
v-model:last-name-en="meta.lastNameEN"
|
|
||||||
v-model:last-name="meta.lastName"
|
|
||||||
v-model:middle-name-en="meta.middleNameEN"
|
|
||||||
v-model:middle-name="meta.middleName"
|
|
||||||
v-model:first-name-en="meta.firstNameEN"
|
|
||||||
v-model:first-name="meta.firstName"
|
|
||||||
v-model:name-prefix="meta.namePrefix"
|
|
||||||
v-model:passport-number="meta.number"
|
|
||||||
/>
|
|
||||||
<FormEmployeeVisa
|
|
||||||
v-if="mode === 'visa' && meta"
|
|
||||||
prefix-id="drawer-info-employee"
|
|
||||||
id="form-visa"
|
|
||||||
ocr
|
|
||||||
dense
|
|
||||||
outlined
|
|
||||||
title="customerEmployee.form.group.visa"
|
|
||||||
:readonly="!isEdit"
|
|
||||||
v-model:arrival-at="meta.arrivalAt"
|
|
||||||
v-model:arrival-tm-no="meta.arrivalTMNo"
|
|
||||||
v-model:arrival-tm="meta.arrivalTM"
|
|
||||||
v-model:mrz="meta.mrz"
|
|
||||||
v-model:entry-count="meta.entryCount"
|
|
||||||
v-model:issue-place="meta.issuePlace"
|
|
||||||
v-model:issue-country="meta.issueCountry"
|
|
||||||
v-model:issueDate="meta.issueDate"
|
|
||||||
v-model:type="meta.type"
|
|
||||||
v-model:expire-date="meta.expireDate"
|
|
||||||
v-model:visa-issue-date="meta.issueDate"
|
|
||||||
v-model:visa-expiry-date="meta.expireDate"
|
|
||||||
v-model:remark="meta.remark"
|
|
||||||
v-model:worker-type="meta.workerType"
|
|
||||||
v-model:number="meta.number"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<NoticeJobEmployment v-if="mode === 'noticeJobEmployment'" />
|
|
||||||
</template>
|
|
||||||
</UploadFileGroup>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</DialogForm>
|
|
||||||
|
|
||||||
<!-- NOTE: END - Employee Add Form -->
|
|
||||||
|
|
||||||
<QuotationFormWorkerAddDialog
|
<QuotationFormWorkerAddDialog
|
||||||
v-if="quotationFormState.source"
|
v-if="quotationFormState.source"
|
||||||
:disabled-worker-id="selectedWorker.map((v) => v.id)"
|
:disabled-worker-id="selectedWorker.map((v) => v.id)"
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,116 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { reactive, ref, watch } from 'vue';
|
import { reactive, ref, watch } from 'vue';
|
||||||
import { calculateAge } from 'src/utils/datetime';
|
|
||||||
|
|
||||||
|
// NOTE: Import stores
|
||||||
|
import { dialog } from 'stores/utils';
|
||||||
import useOptionStore from 'src/stores/options';
|
import useOptionStore from 'src/stores/options';
|
||||||
import useEmployeeStore from 'src/stores/employee';
|
import useEmployeeStore from 'src/stores/employee';
|
||||||
import { useQuotationStore } from 'src/stores/quotations';
|
import { useEmployeeForm } from 'src/pages/03_customer-management/form';
|
||||||
import { Employee } from 'src/stores/employee/types';
|
import { waitAll } from 'src/stores/utils';
|
||||||
|
import { calculateAge, dateFormatJS } from 'src/utils/datetime';
|
||||||
|
import { dialogCheckData } from 'stores/utils';
|
||||||
|
import { useQuotationForm } from 'pages/05_quotation/form';
|
||||||
|
|
||||||
import { CancelButton, MainButton } from 'components/button';
|
// NOTE Import Types
|
||||||
|
import { Employee } from 'src/stores/employee/types';
|
||||||
|
import { EmployeeWorker } from 'src/stores/quotations/types';
|
||||||
|
import { runOcr, parseResultMRZ } from 'src/utils/ocr';
|
||||||
|
import useOcrStore from 'stores/ocr';
|
||||||
|
|
||||||
|
// NOTE: Import Components
|
||||||
|
import {
|
||||||
|
SaveButton,
|
||||||
|
EditButton,
|
||||||
|
UndoButton,
|
||||||
|
DeleteButton,
|
||||||
|
MainButton,
|
||||||
|
CancelButton,
|
||||||
|
} from 'components/button';
|
||||||
import DialogContainer from 'components/dialog/DialogContainer.vue';
|
import DialogContainer from 'components/dialog/DialogContainer.vue';
|
||||||
import DialogHeader from 'components/dialog/DialogHeader.vue';
|
import DialogHeader from 'components/dialog/DialogHeader.vue';
|
||||||
import ImportWorker from './ImportWorker.vue';
|
import ImportWorker from './ImportWorker.vue';
|
||||||
import PersonCard from 'src/components/shared/PersonCard.vue';
|
import PersonCard from 'src/components/shared/PersonCard.vue';
|
||||||
import { QuotationFull, EmployeeWorker } from 'src/stores/quotations/types';
|
import NewPersonCard from 'src/components/shared/NewPersonCard.vue';
|
||||||
import { Lang } from 'src/utils/ui';
|
import { Lang } from 'src/utils/ui';
|
||||||
import NoData from 'src/components/NoData.vue';
|
import NoData from 'src/components/NoData.vue';
|
||||||
|
import FormEmployeePassport from 'components/03_customer-management/FormEmployeePassport.vue';
|
||||||
|
import FormEmployeeVisa from 'components/03_customer-management/FormEmployeeVisa.vue';
|
||||||
|
import FormReferDocument from 'src/components/05_quotation/FormReferDocument.vue';
|
||||||
|
import { UploadFileGroup, NoticeJobEmployment } from 'components/upload-file';
|
||||||
|
import FormPerson from 'components/02_personnel-management/FormPerson.vue';
|
||||||
|
import ProfileBanner from 'components/ProfileBanner.vue';
|
||||||
|
import DialogForm from 'components/DialogForm.vue';
|
||||||
|
import {
|
||||||
|
uploadFileListEmployee,
|
||||||
|
columnsAttachment,
|
||||||
|
} from 'src/pages/03_customer-management/constant';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
|
||||||
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
|
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const employeeFormStore = useEmployeeForm();
|
||||||
|
const quotationForm = useQuotationForm();
|
||||||
const { locale } = useI18n();
|
const { locale } = useI18n();
|
||||||
|
const ocrStore = useOcrStore();
|
||||||
|
|
||||||
const props = defineProps<{
|
const { state: employeeFormState, currentFromDataEmployee } =
|
||||||
customerBranchId?: string;
|
storeToRefs(employeeFormStore);
|
||||||
disabledWorkerId?: string[];
|
const { newWorkerList } = storeToRefs(quotationForm);
|
||||||
preselectWorker?: Employee[];
|
|
||||||
}>();
|
const mrz = ref<Awaited<ReturnType<typeof parseResultMRZ>>>();
|
||||||
|
|
||||||
|
const formDataEmployee = ref<
|
||||||
|
EmployeeWorker & {
|
||||||
|
attachment?: {
|
||||||
|
name?: string;
|
||||||
|
group?: string;
|
||||||
|
url?: string;
|
||||||
|
file?: File;
|
||||||
|
_meta?: Record<string, any>;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
>({
|
||||||
|
passportNo: '',
|
||||||
|
documentExpireDate: new Date(),
|
||||||
|
lastNameEN: '',
|
||||||
|
lastName: '',
|
||||||
|
middleNameEN: '',
|
||||||
|
middleName: '',
|
||||||
|
firstNameEN: '',
|
||||||
|
firstName: '',
|
||||||
|
namePrefix: '',
|
||||||
|
nationality: '',
|
||||||
|
gender: '',
|
||||||
|
dateOfBirth: new Date(),
|
||||||
|
attachment: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
customerBranchId?: string;
|
||||||
|
disabledWorkerId?: string[];
|
||||||
|
preselectWorker?: Employee[];
|
||||||
|
}>(),
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
|
||||||
const emits = defineEmits<{
|
const emits = defineEmits<{
|
||||||
(e: 'triggerCreateEmployee'): void;
|
(e: 'triggerCreateEmployee'): void;
|
||||||
(e: 'success', workerSelected: Employee[]): void;
|
(
|
||||||
|
e: 'success',
|
||||||
|
data: {
|
||||||
|
worker: Employee[];
|
||||||
|
newWorker: EmployeeWorker[];
|
||||||
|
},
|
||||||
|
): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const optionStore = useOptionStore();
|
const optionStore = useOptionStore();
|
||||||
const employeeStore = useEmployeeStore();
|
const employeeStore = useEmployeeStore();
|
||||||
|
|
||||||
const open = defineModel<boolean>('open', { default: false });
|
const open = defineModel<boolean>('open', { default: false });
|
||||||
const newWorkerList = defineModel<EmployeeWorker[]>('newWorkerList', {
|
|
||||||
default: [],
|
|
||||||
});
|
|
||||||
const workerSelected = ref<Employee[]>([]);
|
const workerSelected = ref<Employee[]>([]);
|
||||||
const workerList = ref<Employee[]>([]);
|
const workerList = ref<Employee[]>([]);
|
||||||
const importWorkerCriteria = ref<{
|
const importWorkerCriteria = ref<{
|
||||||
|
|
@ -55,6 +127,49 @@ const state = reactive({
|
||||||
search: '',
|
search: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function removeNewWorker(index: number) {
|
||||||
|
dialog({
|
||||||
|
color: 'negative',
|
||||||
|
icon: 'mdi-trash-can-outline',
|
||||||
|
title: t('dialog.title.confirmDelete'),
|
||||||
|
actionText: t('general.delete'),
|
||||||
|
persistent: true,
|
||||||
|
message: t('dialog.message.confirmDelete'),
|
||||||
|
action: async () => {
|
||||||
|
newWorkerList.value.splice(index, 1);
|
||||||
|
},
|
||||||
|
cancel: () => {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function triggerCreateEmployee() {
|
||||||
|
employeeFormStore.resetFormDataEmployee(true);
|
||||||
|
setDefaultFormEmployee();
|
||||||
|
employeeFormState.value.dialogType = 'create';
|
||||||
|
employeeFormState.value.dialogModal = true;
|
||||||
|
employeeFormState.value.isEmployeeEdit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDefaultFormEmployee() {
|
||||||
|
formDataEmployee.value = {
|
||||||
|
passportNo: '',
|
||||||
|
documentExpireDate: new Date(),
|
||||||
|
lastNameEN: '',
|
||||||
|
lastName: '',
|
||||||
|
middleNameEN: '',
|
||||||
|
middleName: '',
|
||||||
|
firstNameEN: '',
|
||||||
|
firstName: '',
|
||||||
|
namePrefix: '',
|
||||||
|
nationality: '',
|
||||||
|
gender: '',
|
||||||
|
dateOfBirth: new Date(),
|
||||||
|
attachment: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
employeeFormState.value.dialogModal = false;
|
||||||
|
}
|
||||||
|
|
||||||
function clean() {
|
function clean() {
|
||||||
workerList.value = [];
|
workerList.value = [];
|
||||||
workerSelected.value = [];
|
workerSelected.value = [];
|
||||||
|
|
@ -163,7 +278,7 @@ watch(() => state.search, getWorkerList);
|
||||||
clickable
|
clickable
|
||||||
class="row items-center"
|
class="row items-center"
|
||||||
style="white-space: nowrap"
|
style="white-space: nowrap"
|
||||||
@click.stop="() => emits('triggerCreateEmployee')"
|
@click.stop="() => triggerCreateEmployee()"
|
||||||
>
|
>
|
||||||
<q-icon
|
<q-icon
|
||||||
size="xs"
|
size="xs"
|
||||||
|
|
@ -215,67 +330,168 @@ watch(() => state.search, getWorkerList);
|
||||||
</q-input>
|
</q-input>
|
||||||
</section>
|
</section>
|
||||||
<!-- wrapper -->
|
<!-- wrapper -->
|
||||||
<div class="col scroll">
|
<div class="col q-gutter-y-md scroll">
|
||||||
<section
|
<q-expansion-item
|
||||||
:class="{ ['items-center']: workerList.length === 0 }"
|
v-if="newWorkerList.length !== 0"
|
||||||
class="row q-col-gutter-md"
|
for="item-up"
|
||||||
|
id="item-up"
|
||||||
|
dense
|
||||||
|
class="overflow-hidden"
|
||||||
|
switch-toggle-side
|
||||||
|
style="border-radius: var(--radius-2)"
|
||||||
|
expand-icon="mdi-chevron-down-circle"
|
||||||
|
default-opened
|
||||||
>
|
>
|
||||||
<div
|
<template v-slot:header>
|
||||||
style="display: inline-block; margin-inline: auto"
|
<section class="row items-center full-width">
|
||||||
v-if="workerList.length === 0"
|
<div class="row items-center q-pr-md q-py-sm">
|
||||||
>
|
<span
|
||||||
<NoData :not-found="!!state.search" />
|
class="text-weight-medium q-mr-md"
|
||||||
</div>
|
style="font-size: 18px"
|
||||||
<div
|
>
|
||||||
:key="emp.id"
|
{{ $t('quotation.newCustomer') }}
|
||||||
v-for="(emp, index) in workerList.map((data) => ({
|
</span>
|
||||||
...data,
|
</div>
|
||||||
_selectedIndex: selectedIndex(data),
|
</section>
|
||||||
}))"
|
</template>
|
||||||
class="col-2"
|
|
||||||
>
|
<div class="full-width q-pt-md">
|
||||||
<button
|
<section
|
||||||
class="selectable-item full-width"
|
:class="{ ['items-center']: workerList.length === 0 }"
|
||||||
:class="{
|
class="row q-col-gutter-md"
|
||||||
['selectable-item__selected']: emp._selectedIndex !== -1,
|
|
||||||
['selectable-item__disabled']: disabledWorkerId?.some(
|
|
||||||
(id) => id === emp.id,
|
|
||||||
),
|
|
||||||
}"
|
|
||||||
@click="toggleSelect(emp)"
|
|
||||||
>
|
>
|
||||||
<span class="selectable-item__pos">
|
<div
|
||||||
{{ emp._selectedIndex + 1 }}
|
style="display: inline-block; margin-inline: auto"
|
||||||
</span>
|
v-if="workerList.length === 0"
|
||||||
<PersonCard
|
>
|
||||||
no-action
|
<NoData :not-found="!!state.search" />
|
||||||
class="full-width"
|
</div>
|
||||||
:prefix-id="'employee-' + index"
|
<div
|
||||||
:data="{
|
:key="emp.id"
|
||||||
name:
|
v-for="(emp, index) in newWorkerList.map((data) => ({
|
||||||
locale === Lang.English
|
...data,
|
||||||
? `${emp.firstNameEN} ${emp.lastNameEN}`
|
}))"
|
||||||
: `${emp.firstName} ${emp.lastName}`,
|
class="col-2"
|
||||||
code: emp.employeePassport?.at(0)?.number || '-',
|
>
|
||||||
female: emp.gender === 'female',
|
<button
|
||||||
male: emp.gender === 'male',
|
class="selectable-item full-width selectable-item__selected"
|
||||||
img: getEmployeeImageUrl(emp),
|
>
|
||||||
fallbackImg: '/images/employee-avatar.png',
|
<NewPersonCard
|
||||||
detail: [
|
@cancel="(i) => removeNewWorker(i)"
|
||||||
{
|
no-action
|
||||||
icon: 'mdi-passport',
|
class="full-width"
|
||||||
value: optionStore.mapOption(emp.nationality),
|
:prefix-id="'employee-' + index"
|
||||||
},
|
:data="{
|
||||||
{
|
name:
|
||||||
icon: 'mdi-clock-outline',
|
locale === Lang.English
|
||||||
value: calculateAge(emp.dateOfBirth),
|
? `${emp.firstNameEN} ${emp.lastNameEN}`
|
||||||
},
|
: `${emp.firstName} ${emp.lastName}`,
|
||||||
],
|
female: emp.gender === 'female',
|
||||||
}"
|
male: emp.gender === 'male',
|
||||||
/>
|
img: '/images/employee-avatar.png',
|
||||||
</button>
|
index: index,
|
||||||
|
detail: [
|
||||||
|
{
|
||||||
|
icon: 'mdi-passport',
|
||||||
|
value: optionStore.mapOption(emp.nationality),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'mdi-clock-outline',
|
||||||
|
value: calculateAge(emp.dateOfBirth),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</q-expansion-item>
|
||||||
|
|
||||||
|
<q-expansion-item
|
||||||
|
for="item-up"
|
||||||
|
id="item-up"
|
||||||
|
dense
|
||||||
|
class="overflow-hidden"
|
||||||
|
switch-toggle-side
|
||||||
|
default-opened
|
||||||
|
style="border-radius: var(--radius-2)"
|
||||||
|
expand-icon="mdi-chevron-down-circle"
|
||||||
|
header-class=""
|
||||||
|
>
|
||||||
|
<template v-slot:header>
|
||||||
|
<section class="row items-center full-width">
|
||||||
|
<div class="row items-center q-pr-md q-py-sm">
|
||||||
|
<span
|
||||||
|
class="text-weight-medium q-mr-md"
|
||||||
|
style="font-size: 18px"
|
||||||
|
>
|
||||||
|
{{ $t('quotation.customer') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div class="full-width q-pt-md">
|
||||||
|
<section
|
||||||
|
:class="{ ['items-center']: workerList.length === 0 }"
|
||||||
|
class="row q-col-gutter-md scroll"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="display: inline-block; margin-inline: auto"
|
||||||
|
v-if="workerList.length === 0"
|
||||||
|
>
|
||||||
|
<NoData :not-found="!!state.search" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:key="emp.id"
|
||||||
|
v-for="(emp, index) in workerList.map((data) => ({
|
||||||
|
...data,
|
||||||
|
_selectedIndex: selectedIndex(data),
|
||||||
|
}))"
|
||||||
|
class="col-2"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="selectable-item full-width"
|
||||||
|
:class="{
|
||||||
|
['selectable-item__selected']: emp._selectedIndex !== -1,
|
||||||
|
['selectable-item__disabled']: disabledWorkerId?.some(
|
||||||
|
(id) => id === emp.id,
|
||||||
|
),
|
||||||
|
}"
|
||||||
|
@click="toggleSelect(emp)"
|
||||||
|
>
|
||||||
|
<PersonCard
|
||||||
|
no-action
|
||||||
|
class="full-width"
|
||||||
|
:prefix-id="'employee-' + index"
|
||||||
|
:data="{
|
||||||
|
name:
|
||||||
|
locale === Lang.English
|
||||||
|
? `${emp.firstNameEN} ${emp.lastNameEN}`
|
||||||
|
: `${emp.firstName} ${emp.lastName}`,
|
||||||
|
code: emp.employeePassport?.at(0)?.number || '-',
|
||||||
|
female: emp.gender === 'female',
|
||||||
|
male: emp.gender === 'male',
|
||||||
|
img: getEmployeeImageUrl(emp),
|
||||||
|
fallbackImg: '/images/employee-avatar.png',
|
||||||
|
detail: [
|
||||||
|
{
|
||||||
|
icon: 'mdi-passport',
|
||||||
|
value: optionStore.mapOption(emp.nationality),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'mdi-clock-outline',
|
||||||
|
value: calculateAge(emp.dateOfBirth),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</q-expansion-item>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
|
@ -285,16 +501,483 @@ watch(() => state.search, getWorkerList);
|
||||||
icon="mdi-check"
|
icon="mdi-check"
|
||||||
color="207 96% 32%"
|
color="207 96% 32%"
|
||||||
solid
|
solid
|
||||||
@click="emits('success', workerSelected), (open = false)"
|
@click="
|
||||||
|
emits('success', {
|
||||||
|
worker: workerSelected,
|
||||||
|
newWorker: newWorkerList,
|
||||||
|
}),
|
||||||
|
(open = false)
|
||||||
|
"
|
||||||
>
|
>
|
||||||
{{ $t('general.select', { msg: $t('quotation.employeeList') }) }}
|
{{ $t('general.select', { msg: $t('quotation.employeeList') }) }}
|
||||||
</MainButton>
|
</MainButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</DialogContainer>
|
</DialogContainer>
|
||||||
|
|
||||||
|
<!-- NOTE: START - Employee Add Form -->
|
||||||
|
|
||||||
|
<DialogForm
|
||||||
|
hide-footer
|
||||||
|
ref="formDialogRef"
|
||||||
|
v-model:modal="employeeFormState.dialogModal"
|
||||||
|
:title="$t('form.title.create', { name: $t('customer.employee') })"
|
||||||
|
:submit="
|
||||||
|
() => {
|
||||||
|
quotationForm.injectNewEmployee({ data: formDataEmployee }, () =>
|
||||||
|
setDefaultFormEmployee(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
:close="
|
||||||
|
() => {
|
||||||
|
employeeFormState.dialogModal = false;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
:class="{
|
||||||
|
'q-mx-lg q-my-md': $q.screen.gt.sm,
|
||||||
|
'q-mx-md q-my-sm': !$q.screen.gt.sm,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<ProfileBanner
|
||||||
|
prefix="dialog"
|
||||||
|
active
|
||||||
|
useToggle
|
||||||
|
color="white"
|
||||||
|
icon="mdi-account-plus-outline"
|
||||||
|
:bg-color="
|
||||||
|
employeeFormState.profileUrl
|
||||||
|
? 'white'
|
||||||
|
: 'linear-gradient(135deg, rgba(43,137,223,1) 0%, rgba(230,51,81,1) 100%)'
|
||||||
|
"
|
||||||
|
v-model:current-tab="employeeFormState.currentTab"
|
||||||
|
v-model:toggle-status="currentFromDataEmployee.status"
|
||||||
|
fallbackCover="/images/employee-banner.png"
|
||||||
|
:img="employeeFormState.profileUrl || `/images/employee-avatar.png`"
|
||||||
|
:toggleTitle="$t('status.title')"
|
||||||
|
hideFade
|
||||||
|
@view="
|
||||||
|
() => {
|
||||||
|
employeeFormState.imageDialog = true;
|
||||||
|
employeeFormState.isImageEdit = false;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@edit="
|
||||||
|
employeeFormState.imageDialog = employeeFormState.isImageEdit = true
|
||||||
|
"
|
||||||
|
@update:toggle-status="
|
||||||
|
() => {
|
||||||
|
currentFromDataEmployee.status =
|
||||||
|
currentFromDataEmployee.status === 'CREATED'
|
||||||
|
? 'INACTIVE'
|
||||||
|
: 'CREATED';
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="col"
|
||||||
|
:class="{
|
||||||
|
'q-px-lg q-pb-lg': $q.screen.gt.sm,
|
||||||
|
'q-px-md q-pb-sm': !$q.screen.gt.sm,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="overflow-y: auto"
|
||||||
|
class="row full-width full-height surface-1 rounded bordered relative-position"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
:class="{
|
||||||
|
'q-py-md q-px-lg': $q.screen.gt.sm,
|
||||||
|
'q-py-sm q-px-lg': !$q.screen.gt.sm,
|
||||||
|
}"
|
||||||
|
style="position: absolute; z-index: 99999; top: 0; right: 0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="currentFromDataEmployee.status !== 'INACTIVE'"
|
||||||
|
class="surface-1 row rounded"
|
||||||
|
>
|
||||||
|
<UndoButton
|
||||||
|
v-if="
|
||||||
|
employeeFormState.isEmployeeEdit &&
|
||||||
|
employeeFormState.dialogType !== 'create'
|
||||||
|
"
|
||||||
|
id="btn-info-basic-undo"
|
||||||
|
icon-only
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
employeeFormStore.resetFormDataEmployee();
|
||||||
|
employeeFormState.isEmployeeEdit = false;
|
||||||
|
employeeFormState.dialogType = 'info';
|
||||||
|
}
|
||||||
|
"
|
||||||
|
type="button"
|
||||||
|
/>
|
||||||
|
<SaveButton
|
||||||
|
v-if="employeeFormState.isEmployeeEdit"
|
||||||
|
id="btn-info-basic-save"
|
||||||
|
icon-only
|
||||||
|
type="submit"
|
||||||
|
/>
|
||||||
|
<EditButton
|
||||||
|
v-if="!employeeFormState.isEmployeeEdit"
|
||||||
|
id="btn-info-basic-edit"
|
||||||
|
icon-only
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
employeeFormState.isEmployeeEdit = true;
|
||||||
|
employeeFormState.dialogType = 'edit';
|
||||||
|
}
|
||||||
|
"
|
||||||
|
type="button"
|
||||||
|
/>
|
||||||
|
<DeleteButton
|
||||||
|
v-if="!employeeFormState.isEmployeeEdit"
|
||||||
|
id="btn-info-basic-delete"
|
||||||
|
icon-only
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="col-12 full-height q-col-gutter-sm q-py-md q-pl-md q-pr-sm"
|
||||||
|
:class="{
|
||||||
|
'q-py-md q-pr-md ': $q.screen.gt.sm,
|
||||||
|
'q-py-md q-px-lg': !$q.screen.gt.sm,
|
||||||
|
}"
|
||||||
|
id="branch-form"
|
||||||
|
style="overflow-y: auto"
|
||||||
|
>
|
||||||
|
<FormReferDocument
|
||||||
|
title="form.field.basicInformation"
|
||||||
|
prefixId="dialog"
|
||||||
|
dense
|
||||||
|
v-model:passport-no="formDataEmployee.passportNo"
|
||||||
|
v-model:document-expire-date="formDataEmployee.documentExpireDate"
|
||||||
|
class="q-mb-md"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormPerson
|
||||||
|
id="form-personal"
|
||||||
|
prefix-id="form-employee"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
employee
|
||||||
|
separator
|
||||||
|
hideNameEn
|
||||||
|
title="personnel.form.personalInformation"
|
||||||
|
class="q-mb-md"
|
||||||
|
v-model:prefix-name="formDataEmployee.namePrefix"
|
||||||
|
v-model:first-name="formDataEmployee.firstName"
|
||||||
|
v-model:mid-name="formDataEmployee.middleName"
|
||||||
|
v-model:last-name="formDataEmployee.lastName"
|
||||||
|
v-model:birth-date="formDataEmployee.dateOfBirth"
|
||||||
|
v-model:gender="formDataEmployee.gender"
|
||||||
|
v-model:nationality="formDataEmployee.nationality"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<UploadFileGroup
|
||||||
|
show-title
|
||||||
|
v-model="formDataEmployee.attachment"
|
||||||
|
hide-action
|
||||||
|
@submit="
|
||||||
|
async (group, allMeta) => {
|
||||||
|
if (allMeta === undefined) return;
|
||||||
|
|
||||||
|
if (group === 'passport') {
|
||||||
|
const fullName = allMeta['full_name'].split(' ');
|
||||||
|
let tempValue: {
|
||||||
|
oldData: { nameField: string; value: string }[];
|
||||||
|
newData: { nameField: string; value: string }[];
|
||||||
|
} = { oldData: [], newData: [] };
|
||||||
|
|
||||||
|
if (
|
||||||
|
formDataEmployee.gender !== '' &&
|
||||||
|
formDataEmployee.gender !== allMeta['sex']
|
||||||
|
) {
|
||||||
|
tempValue.oldData.push({
|
||||||
|
nameField: $t('form.gender'),
|
||||||
|
value: $t(`general.${formDataEmployee.gender}`),
|
||||||
|
});
|
||||||
|
tempValue.newData.push({
|
||||||
|
nameField: $t('form.gender'),
|
||||||
|
value: $t(`general.${allMeta['sex']}`),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formDataEmployee.firstName !== '') {
|
||||||
|
tempValue.oldData.push({
|
||||||
|
nameField: $t('personnel.form.firstName'),
|
||||||
|
value: formDataEmployee.firstName,
|
||||||
|
});
|
||||||
|
tempValue.newData.push({
|
||||||
|
nameField: $t('personnel.form.firstName'),
|
||||||
|
value: fullName[0],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formDataEmployee.lastName !== '') {
|
||||||
|
tempValue.oldData.push({
|
||||||
|
nameField: $t('personnel.form.lastName'),
|
||||||
|
value: formDataEmployee.lastName,
|
||||||
|
});
|
||||||
|
tempValue.newData.push({
|
||||||
|
nameField: $t('personnel.form.lastName'),
|
||||||
|
value: fullName[1],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formDataEmployee.passportNo !== '') {
|
||||||
|
tempValue.oldData.push({
|
||||||
|
nameField: $t('customerEmployee.form.passportNo'),
|
||||||
|
value: formDataEmployee.passportNo || '',
|
||||||
|
});
|
||||||
|
tempValue.newData.push({
|
||||||
|
nameField: $t('customerEmployee.form.passportNo'),
|
||||||
|
value: allMeta['doc_number'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formDataEmployee.nationality !== '') {
|
||||||
|
tempValue.oldData.push({
|
||||||
|
nameField: $t('general.nationality'),
|
||||||
|
value: formDataEmployee.nationality || '',
|
||||||
|
});
|
||||||
|
tempValue.newData.push({
|
||||||
|
nameField: $t('general.nationality'),
|
||||||
|
value: allMeta['nationality'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dialogCheckData({
|
||||||
|
action: async () => {
|
||||||
|
formDataEmployee.gender = allMeta['sex'];
|
||||||
|
formDataEmployee.firstName = fullName[0];
|
||||||
|
formDataEmployee.lastName = fullName[1];
|
||||||
|
formDataEmployee.passportNo = allMeta['doc_number'];
|
||||||
|
formDataEmployee.nationality = allMeta['nationality'];
|
||||||
|
},
|
||||||
|
checkData: () => {
|
||||||
|
return tempValue;
|
||||||
|
},
|
||||||
|
cancel: () => {
|
||||||
|
if (!formDataEmployee.gender) {
|
||||||
|
formDataEmployee.gender = allMeta['gender'];
|
||||||
|
}
|
||||||
|
if (!formDataEmployee.firstName) {
|
||||||
|
formDataEmployee.firstName = fullName[0];
|
||||||
|
}
|
||||||
|
if (!formDataEmployee.firstName) {
|
||||||
|
formDataEmployee.firstName = fullName[0];
|
||||||
|
}
|
||||||
|
if (!formDataEmployee.lastName) {
|
||||||
|
formDataEmployee.lastName = fullName[1];
|
||||||
|
}
|
||||||
|
if (!formDataEmployee.passportNo) {
|
||||||
|
formDataEmployee.passportNo = allMeta['doc_number'];
|
||||||
|
}
|
||||||
|
if (!formDataEmployee.nationality) {
|
||||||
|
formDataEmployee.nationality = allMeta['nationality'];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
:menu="uploadFileListEmployee"
|
||||||
|
:columns="columnsAttachment"
|
||||||
|
:ocr="
|
||||||
|
async (group, file) => {
|
||||||
|
if (group === 'passport') {
|
||||||
|
mrz = await runOcr(file, parseResultMRZ);
|
||||||
|
|
||||||
|
if (mrz !== null) {
|
||||||
|
const mapMrz = Object.entries(mrz.result || {}).map(
|
||||||
|
([key, value]) => ({
|
||||||
|
name: key,
|
||||||
|
value: value,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const tempValue = {
|
||||||
|
status: true,
|
||||||
|
group,
|
||||||
|
meta: mapMrz,
|
||||||
|
};
|
||||||
|
|
||||||
|
return tempValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (group === 'visa') {
|
||||||
|
const res = await ocrStore.sendOcr({
|
||||||
|
file: file,
|
||||||
|
category: group,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
const tempValue = {
|
||||||
|
status: true,
|
||||||
|
group,
|
||||||
|
meta: res.fields,
|
||||||
|
};
|
||||||
|
|
||||||
|
return tempValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { status: true, group, meta: [] };
|
||||||
|
}
|
||||||
|
"
|
||||||
|
:delete-item="
|
||||||
|
async () => {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
:get-file-list="
|
||||||
|
async (group: 'passport' | 'visa' | 'attachment') => {
|
||||||
|
if (!!currentFromDataEmployee.id && group !== 'attachment') {
|
||||||
|
const resMeta = await employeeStore.getMetaList({
|
||||||
|
parentId: currentFromDataEmployee.id,
|
||||||
|
group,
|
||||||
|
});
|
||||||
|
|
||||||
|
const tempValue = resMeta.map(async (i: any) => {
|
||||||
|
return {
|
||||||
|
_meta: { ...i },
|
||||||
|
name: `${group}-${dateFormatJS(i.expireDate)}` || '',
|
||||||
|
group: group,
|
||||||
|
url: await employeeStore.getFile({
|
||||||
|
parentId: currentFromDataEmployee.id || '',
|
||||||
|
group,
|
||||||
|
fileId: i.id,
|
||||||
|
}),
|
||||||
|
file: undefined,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return await waitAll(tempValue);
|
||||||
|
} else {
|
||||||
|
const res = await employeeStore.listAttachment({
|
||||||
|
parentId: currentFromDataEmployee.id || '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const tempValue = (res as string[]).map(async (i: any) => {
|
||||||
|
return {
|
||||||
|
_meta: { id: i, name: i },
|
||||||
|
name: i || '',
|
||||||
|
group: group,
|
||||||
|
url: await employeeStore.getAttachment({
|
||||||
|
parentId: currentFromDataEmployee.id || '',
|
||||||
|
name: i,
|
||||||
|
}),
|
||||||
|
file: undefined,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return await waitAll(tempValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template #form="{ mode, meta, isEdit }">
|
||||||
|
<FormEmployeePassport
|
||||||
|
v-if="mode === 'passport' && meta"
|
||||||
|
prefix-id="drawer-info-employee"
|
||||||
|
id="form-passport"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
separator
|
||||||
|
ocr
|
||||||
|
:title="$t('customerEmployee.form.group.passport')"
|
||||||
|
:readonly="!isEdit"
|
||||||
|
v-model:birth-country="meta.birthCountry"
|
||||||
|
v-model:previous-passportRef="meta.previousPassportRef"
|
||||||
|
v-model:issue-place="meta.issuePlace"
|
||||||
|
v-model:issue-country="meta.issueCountry"
|
||||||
|
v-model:issue-date="meta.issueDate"
|
||||||
|
v-model:type="meta.type"
|
||||||
|
v-model:expire-date="meta.expireDate"
|
||||||
|
v-model:birth-date="meta.birthDate"
|
||||||
|
v-model:worker-status="meta.workerStatus"
|
||||||
|
v-model:nationality="meta.nationality"
|
||||||
|
v-model:gender="meta.gender"
|
||||||
|
v-model:last-name-en="meta.lastNameEN"
|
||||||
|
v-model:last-name="meta.lastName"
|
||||||
|
v-model:middle-name-en="meta.middleNameEN"
|
||||||
|
v-model:middle-name="meta.middleName"
|
||||||
|
v-model:first-name-en="meta.firstNameEN"
|
||||||
|
v-model:first-name="meta.firstName"
|
||||||
|
v-model:name-prefix="meta.namePrefix"
|
||||||
|
v-model:passport-number="meta.number"
|
||||||
|
/>
|
||||||
|
<FormEmployeeVisa
|
||||||
|
v-if="mode === 'visa' && meta"
|
||||||
|
prefix-id="drawer-info-employee"
|
||||||
|
id="form-visa"
|
||||||
|
ocr
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
title="customerEmployee.form.group.visa"
|
||||||
|
:readonly="!isEdit"
|
||||||
|
v-model:arrival-at="meta.arrivalAt"
|
||||||
|
v-model:arrival-tm-no="meta.arrivalTMNo"
|
||||||
|
v-model:arrival-tm="meta.arrivalTM"
|
||||||
|
v-model:mrz="meta.mrz"
|
||||||
|
v-model:entry-count="meta.entryCount"
|
||||||
|
v-model:issue-place="meta.issuePlace"
|
||||||
|
v-model:issue-country="meta.issueCountry"
|
||||||
|
v-model:issueDate="meta.issueDate"
|
||||||
|
v-model:type="meta.type"
|
||||||
|
v-model:expire-date="meta.expireDate"
|
||||||
|
v-model:visa-issue-date="meta.issueDate"
|
||||||
|
v-model:visa-expiry-date="meta.expireDate"
|
||||||
|
v-model:remark="meta.remark"
|
||||||
|
v-model:worker-type="meta.workerType"
|
||||||
|
v-model:number="meta.number"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<NoticeJobEmployment v-if="mode === 'noticeJobEmployment'" />
|
||||||
|
</template>
|
||||||
|
</UploadFileGroup>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</DialogForm>
|
||||||
|
|
||||||
|
<!-- NOTE: END - Employee Add Form -->
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
:deep(i.q-icon.mdi.mdi-chevron-down-circle.q-expansion-item__toggle-icon) {
|
||||||
|
color: hsl(var(--text-mute));
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(
|
||||||
|
i.q-icon.mdi.mdi-chevron-down-circle.q-expansion-item__toggle-icon.q-expansion-item__toggle-icon--rotated
|
||||||
|
) {
|
||||||
|
color: var(--brand-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.q-editor__toolbar-group):nth-child(2) {
|
||||||
|
margin-left: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.q-editor__toolbar.row.no-wrap.scroll-x) {
|
||||||
|
background-color: var(--surface-2) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.q-editor__toolbar) {
|
||||||
|
border-color: var(--surface-3) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(
|
||||||
|
.q-item.q-item-type.row.no-wrap.q-item--dense.q-item--clickable.q-link.cursor-pointer.q-focusable.q-hoverable.surface-1
|
||||||
|
.q-focus-helper
|
||||||
|
) {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.selectable-item {
|
.selectable-item {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue