refactor: worker select & employee nationality

This commit is contained in:
puriphatt 2024-10-03 18:10:40 +07:00
parent 8006314ce4
commit 9d745d8e52
5 changed files with 100 additions and 52 deletions

View file

@ -258,7 +258,7 @@ defineEmits<{
detail: [
{
icon: 'mdi-passport',
value: props.row.nationality,
value: optionStore.mapOption(props.row.nationality),
},
{

View file

@ -9,6 +9,7 @@ defineEmits<{
withDefaults(
defineProps<{
employeeAmount: number;
fallbackImg?: string;
rows: {
foreignRefNo: string;
employeeName: string;
@ -92,7 +93,11 @@ const columns = [
>
<template v-slot:img-column="{ props }">
<q-avatar class="q-mr-sm" size="md">
<q-img :src="props.row.imgUrl"></q-img>
<q-img :src="props.row.imgUrl" class="full-height full-width">
<template #error>
<q-img :src="fallbackImg" :ratio="1" />
</template>
</q-img>
<div
class="absolute-bottom-right"
style="
@ -121,7 +126,7 @@ const columns = [
class="surface-tab bordered rounded flex items-center justify-center q-mx-md"
style="width: 30px; height: 30px"
>
{{ employeeAmount }}
{{ employeeAmount || '0' }}
</div>
</div>
</div>

View file

@ -21,7 +21,7 @@ const props = withDefaults(
},
);
defineExpose({ select });
defineExpose({ select, assignSelect });
function select(item?: unknown, all?: boolean) {
if (all) {
@ -44,6 +44,19 @@ function select(item?: unknown, all?: boolean) {
} else selectedItem.value.push(item);
}
}
function assignSelect(to: unknown[], from: unknown[]) {
const existingItems = new Set(to);
for (let i = to.length - 1; i >= 0; i--) {
if (!from.includes(to[i])) {
to.splice(i, 1);
}
}
const newItems = from.filter((item) => !existingItems.has(item));
to.push(...newItems);
}
</script>
<template>
<section class="full-width column">

View file

@ -2,12 +2,13 @@
import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia';
import { QSelect, useQuasar } from 'quasar';
import { onMounted, reactive, ref } from 'vue';
import { nextTick, onMounted, reactive, ref } from 'vue';
import { setLocale } from 'src/utils/datetime';
import { dateFormat } from 'src/utils/datetime';
import { baseUrl } from 'src/stores/utils';
import { setLocale, dateFormat, calculateAge } from 'src/utils/datetime';
import useOptionStore from 'stores/options';
import useEmployeeStore from 'src/stores/employee';
import { useQuotationForm } from './form';
import { Employee } from 'src/stores/employee/types';
import {
@ -28,6 +29,7 @@ import SelectZone from 'src/components/shared/SelectZone.vue';
import PersonCard from 'src/components/shared/PersonCard.vue';
import { AddButton, SaveButton } from 'components/button';
import useProductServiceStore from 'src/stores/product-service';
import useCustomerStore from 'src/stores/customer';
type Node = {
[key: string]: any;
@ -44,20 +46,26 @@ defineProps<{
}>();
const optionStore = useOptionStore();
const customerStore = useCustomerStore();
const productServiceStore = useProductServiceStore();
const quotationForm = useQuotationForm();
const employeeStore = useEmployeeStore();
const { locale } = useI18n();
const { currentFormData: quotationFormData } = storeToRefs(quotationForm);
const $q = useQuasar();
const refSelectZoneEmployee = ref<InstanceType<typeof SelectZone>>();
const date = ref();
const rows = ref<Node[]>([]);
const selectedEmployee = ref<Employee[]>([]);
const selectedBranchIssuer = ref('');
const selectedCustomer = ref('');
const toggleWorker = ref(true);
const branchId = ref('');
const selectedWorker = ref<Employee[]>([]);
const preSelectedWorker = ref<Employee[]>([]);
const workerList = ref<Employee[]>([]);
const quotationNo = ref('');
const actor = ref('');
const workName = ref('');
@ -130,9 +138,13 @@ async function getAllService(
if (ret) serviceList.value[groupId] = ret.result;
}
function triggerSelectEmployeeDialog() {
async function triggerSelectEmployeeDialog() {
pageState.employeeModal = true;
// TODO: form and state controll
await nextTick();
refSelectZoneEmployee.value?.assignSelect(
preSelectedWorker.value,
selectedWorker.value,
);
}
function triggerProductServiceDialog() {
@ -153,6 +165,14 @@ function convertToTable(nodes: Node[]) {
productServiceList.value = nodes.flatMap(_recursive).map((v) => v.value);
}
function convertEmployeeToTable() {
refSelectZoneEmployee.value?.assignSelect(
selectedWorker.value,
preSelectedWorker.value,
);
pageState.employeeModal = false;
}
function changeMode(mode: string) {
if (mode === 'light') {
localStorage.setItem('currentTheme', 'light');
@ -199,6 +219,11 @@ onMounted(async () => {
if (locale.value === 'eng') optionStore.globalOption = rawOption.eng;
if (locale.value === 'tha') optionStore.globalOption = rawOption.tha;
const retEmp = await customerStore.fetchBranchEmployee(
quotationFormData.value.customerBranchId,
);
if (retEmp) workerList.value = retEmp.data.result;
const getCurLang = localStorage.getItem('currentLanguage');
if (getCurLang === 'English') {
locale.value = 'eng';
@ -307,19 +332,24 @@ onMounted(async () => {
<div class="surface-1 q-pa-md full-width">
<WorkerItem
:rows="[
{
foreignRefNo: '123',
employeeName: '123',
birthDate: '123',
gender: '123',
age: '123',
nationality: '123',
documentExpireDate: '123',
imgUrl: '/images/employee-avatar.png',
status: 'ACTIVE',
},
]"
:employee-amount="selectedWorker.length"
fallback-img="/images/employee-avatar.png"
:rows="
selectedWorker.map((e: Employee) => ({
foreignRefNo: '123456789',
employeeName:
$i18n.locale === 'eng'
? `${e.firstNameEN} ${e.lastNameEN}`
: `${e.firstName} ${e.lastName}`,
birthDate: dateFormat(e.dateOfBirth),
gender: e.gender,
age: calculateAge(e.dateOfBirth),
nationality: optionStore.mapOption(e.nationality),
documentExpireDate: '1234',
imgUrl: `${baseUrl}/customer/${e.id}/image/${e.selectedImage}`,
status: e.status,
}))
"
/>
</div>
</q-expansion-item>
@ -448,33 +478,18 @@ onMounted(async () => {
:submit-label="$t('general.select', { msg: $t('quotation.employee') })"
submit-icon="mdi-check"
height="75vh"
:submit="() => convertEmployeeToTable()"
:close="
() => {
(preSelectedWorker = []), (pageState.employeeModal = false);
}
"
>
<section class="col row scroll">
<SelectZone
v-model:selected-item="selectedEmployee"
:items="[
{
name: 'มิเคล่า สุวรรณดี',
gender: 'female',
telephoneNo: '0621249602',
code: 'CORP000000-1-01-240001',
birthDate: '16 ปี 11 เดือน 5 วัน',
},
{
name: 'มิลิเซนต์ สุวรรณดี',
gender: 'female',
telephoneNo: '0621249666',
code: 'CORP000000-1-01-240002',
birthDate: '19 ปี 2 เดือน 2 วัน',
},
{
name: 'ไรคาร์ด พวงศรี',
gender: 'male',
telephoneNo: '0621249777',
code: 'CORP000000-1-01-240003',
birthDate: '39 ปี 5 เดือน 2 วัน',
},
]"
ref="refSelectZoneEmployee"
v-model:selected-item="preSelectedWorker"
:items="workerList"
>
<template #top>
<AddButton
@ -492,14 +507,24 @@ onMounted(async () => {
prefixId="asda"
class="full-width"
:data="{
name: item.name,
name:
$i18n.locale === 'eng'
? `${item.firstNameEN} ${item.lastNameEN}`
: `${item.firstName} ${item.lastName}`,
code: item.code,
female: item.gender === 'female',
male: item.gender === 'male',
img: '/images/employee-avatar.png',
img: `${baseUrl}/customer/${item.id}/image/${item.selectedImage}`,
fallbackImg: '/images/employee-avatar.png',
detail: [
{ icon: 'mdi-phone-outline', value: item.telephoneNo },
{ icon: 'mdi-clock-outline', value: item.birthDate },
{
icon: 'mdi-passport',
value: optionStore.mapOption(item.nationality),
},
{
icon: 'mdi-clock-outline',
value: calculateAge(item.dateOfBirth),
},
],
}"
></PersonCard>

View file

@ -21,7 +21,7 @@ export function dateFormat(
if (time) return m.format('HH:mm');
if (number) {
let formattedNumberDate = m.format('L');
const formattedNumberDate = m.format('L');
return formattedNumberDate;
}
@ -60,6 +60,11 @@ export function toISOStringWithTimezone(date: Date) {
);
}
export function calculateAge(birthDate: Date | null | string): string;
export function calculateAge(
birthDate: Date | null | string,
only: 'year' | 'months' | 'days',
): number;
export function calculateAge(
birthDate: Date | null | string,
only?: 'year' | 'months' | 'days',