refactor: add btn uploand file passport
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 7s

This commit is contained in:
Thanaphon Frappet 2025-07-04 16:24:55 +07:00
parent dd09a8cb23
commit 03adabeabd
4 changed files with 48 additions and 19 deletions

View file

@ -9,6 +9,8 @@ import useOptionStore from 'stores/options';
import DatePicker from '../shared/DatePicker.vue'; import DatePicker from '../shared/DatePicker.vue';
import { dateFormat } from 'src/utils/datetime';
const optionStore = useOptionStore(); const optionStore = useOptionStore();
const { locale } = useI18n(); const { locale } = useI18n();
@ -32,6 +34,8 @@ const firstName = defineModel<string>('firstName');
const namePrefix = defineModel<string>('namePrefix'); const namePrefix = defineModel<string>('namePrefix');
const passportNumber = defineModel<string>('passportNumber'); const passportNumber = defineModel<string>('passportNumber');
const file = defineModel<File>('file');
const passportValidator = /[a-zA-Z]{1}[a-zA-Z0-9]{1}[0-9]{5,7}$/; const passportValidator = /[a-zA-Z]{1}[a-zA-Z0-9]{1}[0-9]{5,7}$/;
const genderOptions = ref<Record<string, unknown>[]>([]); const genderOptions = ref<Record<string, unknown>[]>([]);
@ -177,6 +181,30 @@ watch(
}, },
); );
function browse() {
inputFile?.click();
}
const inputFile = (() => {
const _element = document.createElement('input');
_element.type = 'file';
_element.accept = 'image/jpeg,image/png';
_element.addEventListener('change', change);
return _element;
})();
async function change(e: Event) {
const _element = e.target as HTMLInputElement | null;
const _file = _element?.files?.[0];
if (_file) {
const newFileName = `passport-${dateFormat(new Date().toISOString())}-${_file.name}`;
const renamedFile = new File([_file], newFileName, { type: _file.type });
file.value = renamedFile;
}
}
watch( watch(
() => namePrefix.value, () => namePrefix.value,
(v) => { (v) => {
@ -221,20 +249,14 @@ watch(
</div> </div>
<div class="q-col-gutter-sm" :class="{ row: $q.screen.gt.sm }"> <div class="q-col-gutter-sm" :class="{ row: $q.screen.gt.sm }">
<div <div v-if="!ocr">
class="col row justify-center q-col-gutter-sml" <q-btn
style="max-height: 50%" flat
v-if="!ocr" color="primary"
> icon="mdi-upload-box-outline"
<q-avatar @click="() => browse()"
style="border: 1px dashed; border-color: black" :disable="readonly"
square ></q-btn>
size="100px"
font-size="50px"
color="grey-4"
text-color="grey"
icon="mdi-image-outline"
/>
</div> </div>
<div <div
class="row q-col-gutter-sm" class="row q-col-gutter-sm"

View file

@ -3336,6 +3336,7 @@ const emptyCreateDialog = ref(false);
v-model:first-name="value.firstName" v-model:first-name="value.firstName"
v-model:name-prefix="value.namePrefix" v-model:name-prefix="value.namePrefix"
v-model:passport-number="value.number" v-model:passport-number="value.number"
v-model:file="value.file"
> >
<template v-slot:expiryDate> <template v-slot:expiryDate>
{{ $t('general.expirationDate') }} : {{ $t('general.expirationDate') }} :
@ -5432,6 +5433,7 @@ const emptyCreateDialog = ref(false);
v-model:first-name="value.firstName" v-model:first-name="value.firstName"
v-model:name-prefix="value.namePrefix" v-model:name-prefix="value.namePrefix"
v-model:passport-number="value.number" v-model:passport-number="value.number"
v-model:file="value.file"
> >
<template v-slot:expiryDate> <template v-slot:expiryDate>
{{ $t('general.expirationDate') }} : {{ $t('general.expirationDate') }} :

View file

@ -986,12 +986,16 @@ export const useEmployeeForm = defineStore('form-employee', () => {
state.value.currentIndexPassport state.value.currentIndexPassport
].id === undefined ].id === undefined
) { ) {
const { id, employeeId, updatedAt, createdAt, file, ...payload } =
currentFromDataEmployee.value.employeePassport?.[
state.value.currentIndexPassport
];
const res = await employeeStore.postMeta({ const res = await employeeStore.postMeta({
parentId: currentFromDataEmployee.value.id || '', parentId: currentFromDataEmployee.value.id || '',
group: 'passport', group: 'passport',
meta: currentFromDataEmployee.value.employeePassport?.[ meta: payload,
state.value.currentIndexPassport file: file,
],
}); });
if (res) { if (res) {
@ -1005,7 +1009,7 @@ export const useEmployeeForm = defineStore('form-employee', () => {
state.value.currentIndexPassport state.value.currentIndexPassport
].id !== undefined ].id !== undefined
) { ) {
const { id, employeeId, updatedAt, createdAt, ...payload } = const { id, employeeId, updatedAt, createdAt, file, ...payload } =
currentFromDataEmployee.value.employeePassport?.[ currentFromDataEmployee.value.employeePassport?.[
state.value.currentIndexPassport state.value.currentIndexPassport
]; ];
@ -1018,6 +1022,7 @@ export const useEmployeeForm = defineStore('form-employee', () => {
state.value.currentIndexPassport state.value.currentIndexPassport
].id || '', ].id || '',
meta: payload, meta: payload,
file: file || undefined,
}); });
} }

View file

@ -108,7 +108,7 @@ export type EmployeeCreate = {
employeeWork?: EmployeeWorkCreate[]; employeeWork?: EmployeeWorkCreate[];
employeeInCountryNotice?: EmployeeInCountryNoticePayload[]; employeeInCountryNotice?: EmployeeInCountryNoticePayload[];
employeeVisa?: EmployeeVisaPayload[]; employeeVisa?: EmployeeVisaPayload[];
employeePassport?: EmployeePassportPayload[]; employeePassport?: (EmployeePassportPayload & { file?: File })[];
employeeOtherInfo?: EmployeeOtherCreate; employeeOtherInfo?: EmployeeOtherCreate;