fix: customer & employee image list
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 5s

This commit is contained in:
puriphatt 2025-09-17 17:20:47 +07:00
parent ff0f0bdde6
commit 9b0b57ac3f
7 changed files with 1816 additions and 1656 deletions

File diff suppressed because it is too large Load diff

View file

@ -22,6 +22,7 @@ import FormEmployeePassport from './FormEmployeePassport.vue';
import FormEmployeeVisa from './FormEmployeeVisa.vue';
import FormEmployeeWorkHistory from './FormEmployeeWorkHistory.vue';
import ExpirationDate from 'components/03_customer-management/ExpirationDate.vue';
import ImageUploadDialog from '../ImageUploadDialog.vue';
import useOcrStore from 'stores/ocr';
import useOptionStore from 'src/stores/options';
@ -58,6 +59,7 @@ const {
state: employeeFormState,
currentFromDataEmployee,
refreshImageState,
onCreateImageList,
} = storeToRefs(employeeFormStore);
const { state: customerFormState, currentFormData: customerFormData } =
storeToRefs(customerFormStore);
@ -71,7 +73,13 @@ const props = defineProps<{
customerId?: string;
mobileFetch?: boolean;
}) => Promise<void>;
fetchImageList: (
id: string,
selectedName: string,
type: 'customer' | 'employee',
) => Promise<void>;
}>();
const mrz = defineModel<Awaited<ReturnType<typeof parseResultMRZ>>>('mrz');
defineEmits<{
@ -1668,4 +1676,95 @@ defineEmits<{
</div>
</div>
</DrawerInfo>
<ImageUploadDialog
ref="dialogEmployeeImageUpload"
v-model:dialog-state="employeeFormState.imageDialog"
v-model:file="currentFromDataEmployee.image"
v-model:image-url="employeeFormState.profileUrl"
v-model:data-list="employeeFormState.imageList"
v-model:on-create-data-list="onCreateImageList"
:on-create="employeeFormState.dialogModal && !currentFromDataEmployee.id"
:hidden-footer="!employeeFormState.isImageEdit"
@add-image="
async (v) => {
if (!v) return;
if (!currentFromDataEmployee.id) return;
await employeeStore.addImageList(
v,
currentFromDataEmployee.id,
Date.now().toString(),
);
await fetchImageList(
currentFromDataEmployee.id,
currentFromDataEmployee.selectedImage || '',
'employee',
);
}
"
@remove-image="
async (v) => {
if (!v) return;
if (!currentFromDataEmployee.id) return;
const name = v.split('/').pop() || '';
await employeeStore.deleteImageByName(currentFromDataEmployee.id, name);
await fetchImageList(
currentFromDataEmployee.id,
currentFromDataEmployee.selectedImage || '',
'employee',
);
}
"
@submit="
async (v) => {
if (employeeFormState.dialogModal && !currentFromDataEmployee.id) {
employeeFormState.profileUrl = v;
employeeFormState.imageDialog = false;
} else {
refreshImageState = true;
employeeFormState.dialogType = 'edit';
currentFromDataEmployee.selectedImage = v;
employeeFormState.imageList
? (employeeFormState.imageList.selectedImage = v)
: '';
employeeFormState.profileUrl = `${baseUrl}/employee/${currentFromDataEmployee.id && currentFromDataEmployee.id}/image/${v}`;
employeeFormStore.resetFormDataEmployee();
await employeeFormStore.submitPersonal(onCreateImageList);
employeeFormState.imageDialog = false;
refreshImageState = false;
employeeFormState.isEmployeeEdit = false;
employeeFormState.dialogType = 'info';
await fetchListEmployee();
}
}
"
>
<template #title>
<span
v-if="!employeeFormState.dialogModal || currentFromDataEmployee.id"
class="justify-center flex text-bold"
>
{{ $t('general.image') }}
{{
$i18n.locale === 'eng'
? `${currentFromDataEmployee.firstNameEN || currentFromDataEmployee.firstName} ${currentFromDataEmployee.lastNameEN || currentFromDataEmployee.lastName}`
: `${currentFromDataEmployee.firstName} ${currentFromDataEmployee.lastName}`
}}
</span>
</template>
<template #error>
<div class="full-height full-width" style="background: white">
<div
class="full-height full-width flex justify-center items-center"
style="background: #ee4367"
>
<q-img
:src="`/images/employee-avatar-${currentFromDataEmployee.gender === 'male' ? 'male' : 'female'}.png`"
fit="contain"
style="height: 100%"
/>
</div>
</div>
</template>
</ImageUploadDialog>
</template>

View file

@ -18,6 +18,8 @@ import { CustomerBranch, CustomerType } from 'stores/customer/types';
import { columnsEmployee } from './constant';
import { useCustomerBranchForm, useEmployeeForm } from './form';
import DialogEmployee from 'src/components/03_customer-management/DialogEmployee.vue';
import DrawerEmployee from 'src/components/03_customer-management/DrawerEmployee.vue';
import EmployerFormAuthorized from './components/employer/EmployerFormAuthorized.vue';
import FloatingActionButton from 'components/FloatingActionButton.vue';
import SideMenu from 'components/SideMenu.vue';
@ -89,6 +91,11 @@ const prop = withDefaults(
currentCitizenId?: string;
gender: string;
selectedImage: string;
fetchImageList: (
id: string,
selectedName: string,
type: 'customer' | 'employee',
) => Promise<void>;
}>(),
{
color: 'green',
@ -96,7 +103,6 @@ const prop = withDefaults(
);
const currentBranchEmployee = ref<string>('');
const listEmployee = ref<Employee[]>([]);
const customerId = defineModel<string>('customerId', { required: true });
defineEmits<{
@ -106,16 +112,6 @@ defineEmits<{
(e: 'dialog'): void;
}>();
onMounted(async () => {
customerBranchFormState.value.currentCustomerId = route.params
.customerId as string;
await fetchList();
branch.value?.forEach((v) => {
currentBtnOpen.value.push(false);
});
});
const columns = [
{
name: 'branchName',
@ -257,10 +253,6 @@ async function fetchEmployee(opts: { branchId: string; pageSize?: number }) {
}
}
onMounted(async () => {
await fetchList();
});
watch([customerId, inputSearch, currentStatus, pageSizeBranch], async () => {
await fetchList();
});
@ -280,6 +272,16 @@ watch(
}
},
);
onMounted(async () => {
customerBranchFormState.value.currentCustomerId = route.params
.customerId as string;
await fetchList();
branch.value?.forEach((v) => {
currentBtnOpen.value.push(false);
});
});
</script>
<template>
@ -641,10 +643,15 @@ watch(
"
@history="(item) => {}"
@view="
(item) => {
async (item) => {
employeeFormState.drawerModal = true;
//employeeFormState.isEmployeeEdit = true;
employeeFormStore.assignFormDataEmployee(item.id);
await fetchImageList(
item.id,
item.selectedImage || '',
'employee',
);
}
"
/>
@ -1004,6 +1011,18 @@ watch(
/>
</template>
</DialogFormContainer>
<DialogEmployee
:fetch-list-employee="fetchEmployee"
:fetch-image-list="fetchImageList"
current-tab="employer"
/>
<DrawerEmployee
:fetch-list-employee="fetchEmployee"
:fetch-image-list="fetchImageList"
current-tab="employer"
/>
</template>
<style scoped>

View file

@ -20,6 +20,7 @@ import {
CustomerType,
} from 'stores/customer/types';
import DialogEmployee from 'src/components/03_customer-management/DialogEmployee.vue';
import { SaveButton } from 'components/button';
import TabCustomer from './TabCustomer.vue';
import FloatingActionButton from 'components/FloatingActionButton.vue';
@ -176,6 +177,7 @@ async function createCustomerForm(customerType: 'CORP' | 'PERS') {
function createEmployeeForm() {
employeeFormStore.resetFormDataEmployee(true);
employeeFormState.value.currentEmployee = null;
employeeFormState.value.dialogType = 'create';
employeeFormState.value.dialogModal = true;
employeeFormState.value.isEmployeeEdit = true;
@ -190,11 +192,16 @@ async function fetchImageList(
type === 'customer'
? await customerStore.fetchImageListById(id)
: await employeeStore.fetchImageListById(id);
imageList.value = {
const imageList = {
selectedImage: selectedName,
list: res.map((n: string) => `${type}/${id}/image/${n}`),
};
type === 'customer'
? (customerFormState.value.imageList = imageList)
: (employeeFormState.value.imageList = imageList);
return res;
}
@ -752,7 +759,6 @@ onMounted(async () => await init());
ref="refTabCustomer"
v-model:customer-type-selected="customerTypeSelected"
v-model:stats-customer-type="statsCustomerType"
v-model:img-list="imageList"
:filter-address="filterAddress"
:filter-business-type="filterBusinessType"
:gridView
@ -769,7 +775,6 @@ onMounted(async () => await init());
v-if="currentTab === 'employee'"
ref="refTabEmployee"
v-model:employee-stats="employeeStats"
v-model:img-list="imageList"
:gridView
:searchDate
:currentTab
@ -792,6 +797,7 @@ onMounted(async () => await init());
v-model:status-employee-create="statusEmployeeCreate"
v-model:status-employee-edit="employeeFormState.drawerModal"
v-if="currentCustomer"
:fetch-image-list="fetchImageList"
:customer-type="currentCustomer.customerType"
:current-customer-name="
currentCustomer.customerType === 'PERS'

View file

@ -93,9 +93,6 @@ const {
refreshImageState,
} = storeToRefs(employeeFormStore);
const imageList = defineModel<{ selectedImage: string; list: string[] }>(
'imgList',
);
const statsCustomerType = defineModel<CustomerStats>('statsCustomerType', {
default: {
CORP: 0,
@ -1855,7 +1852,7 @@ onMounted(async () => {
v-model:dialog-state="customerFormState.imageDialog"
v-model:file="customerFormData.image"
v-model:image-url="customerFormState.customerImageUrl"
v-model:data-list="imageList"
v-model:data-list="customerFormState.imageList"
v-model:on-create-data-list="onCreateImageList"
:on-create="
customerFormState.dialogModal && !customerFormState.editCustomerId
@ -1905,7 +1902,9 @@ onMounted(async () => {
} else {
refreshImageState = true;
customerFormData.selectedImage = v;
imageList ? (imageList.selectedImage = v) : '';
customerFormState.imageList
? (customerFormState.imageList.selectedImage = v)
: '';
customerFormState.customerImageUrl = `${baseUrl}/customer/${customerFormState.editCustomerId && customerFormState.editCustomerId}/image/${v}`;
customerFormStore.resetForm();
await customerFormStore.submitFormCustomer();
@ -1970,6 +1969,7 @@ onMounted(async () => {
<DrawerEmployee
:fetch-list-employee="fetchListEmployee"
:fetch-image-list="fetchImageList"
:current-tab="currentTab"
/>
</template>

File diff suppressed because it is too large Load diff

View file

@ -88,6 +88,7 @@ export const useCustomerForm = defineStore('form-customer', () => {
formDataOcr: Record<string, any>;
isImageEdit: boolean;
currentCustomerId?: string;
imageList: { list: string[]; selectedImage: string };
}>({
dialogType: 'info',
dialogOpen: false,
@ -104,6 +105,7 @@ export const useCustomerForm = defineStore('form-customer', () => {
treeFile: [],
formDataOcr: {},
isImageEdit: false,
imageList: { list: [], selectedImage: '' },
});
watch(
@ -788,6 +790,7 @@ export const useEmployeeForm = defineStore('form-employee', () => {
}
| undefined;
ocr: boolean;
imageList: { list: string[]; selectedImage: string };
}>({
currentBranchId: '',
isImageEdit: false,
@ -812,6 +815,7 @@ export const useEmployeeForm = defineStore('form-employee', () => {
infoEmployeePersonCard: [],
formDataEmployeeOwner: undefined,
ocr: false,
imageList: { list: [], selectedImage: '' },
});
const defaultFormData: EmployeeCreate & { image?: File } = {
@ -964,6 +968,7 @@ export const useEmployeeForm = defineStore('form-employee', () => {
state.value.currentIndexVisa = -1;
state.value.currentIndexCheckup = -1;
state.value.currentIndexWorkHistory = -1;
state.value.imageList = { list: [], selectedImage: '' };
// state.value.currentTab = 'personalInfo';
if (clean) {
state.value.formDataEmployeeOwner = undefined;