refactor: worker select & employee nationality
This commit is contained in:
parent
8006314ce4
commit
9d745d8e52
5 changed files with 100 additions and 52 deletions
|
|
@ -258,7 +258,7 @@ defineEmits<{
|
|||
detail: [
|
||||
{
|
||||
icon: 'mdi-passport',
|
||||
value: props.row.nationality,
|
||||
value: optionStore.mapOption(props.row.nationality),
|
||||
},
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue