jws-frontend/src/pages/03_customer-management/MainPage.vue

686 lines
20 KiB
Vue
Raw Normal View History

2024-04-22 13:42:02 +07:00
<script setup lang="ts">
import { computed, ref } from 'vue';
2024-06-06 17:10:58 +07:00
import { storeToRefs } from 'pinia';
2024-04-23 11:15:25 +00:00
import UsersDetailCardComponent from 'src/components/UsersDetailCardComponent.vue';
2024-04-22 13:42:02 +07:00
import SelectorList from 'components/SelectorList.vue';
import StatCardComponent from 'components/StatCardComponent.vue';
import TooltipComponent from 'components/TooltipComponent.vue';
import AddButton from 'components/AddButton.vue';
import AppBox from 'components/app/AppBox.vue';
import ItemCard from 'src/components/ItemCard.vue';
import FormDialog from 'src/components/FormDialog.vue';
import ProfileUpload from 'src/components/ProfileUpload.vue';
2024-04-22 17:00:30 +07:00
import BasicInformation from 'src/components/03_customer-management/BasicInformation.vue';
2024-04-23 11:37:27 +07:00
import TabComponent from 'src/components/TabComponent.vue';
import FormAddress from 'src/components/02_personnel-management/FormAddress.vue';
2024-04-23 13:51:32 +07:00
import AboutComponent from 'src/components/03_customer-management/AboutComponent.vue';
import ContactComponent from 'src/components/03_customer-management/ContactInformation.vue';
import OtherInformation from 'src/components/03_customer-management/OtherInformation.vue';
import FormBusiness from 'src/components/03_customer-management/FormBusiness.vue';
2024-04-23 11:15:25 +00:00
import DrawerInfo from 'src/components/DrawerInfo.vue';
import InfoForm from 'src/components/02_personnel-management/InfoForm.vue';
2024-04-22 13:42:02 +07:00
import { CustomerCreate } from 'stores/customer/types';
2024-06-06 17:10:58 +07:00
import useCustomerStore from 'src/stores/customer';
2024-06-06 17:10:58 +07:00
const userCustomer = useCustomerStore();
const { create } = userCustomer;
const formData = ref<CustomerCreate>({
2024-06-06 17:10:58 +07:00
status: 'CREATED',
customerType: 'CORP',
customerName: '',
customerNameEN: '',
2024-06-06 17:10:58 +07:00
taxNo: '',
customerBranch: [
{
address: '',
2024-04-24 10:23:19 +07:00
addressEN: '',
provinceId: '',
districtId: '',
subDistrictId: '',
zipCode: '',
email: '',
telephoneNo: '',
2024-04-24 10:23:19 +07:00
name: '',
2024-06-06 17:10:58 +07:00
status: 'CREATED',
2024-04-24 10:23:19 +07:00
taxNo: '',
nameEN: '',
legalPersonNo: '',
registerName: '',
2024-06-06 17:10:58 +07:00
registerDate: new Date(),
authorizedCapital: '',
2024-04-24 10:23:19 +07:00
employmentOffice: '',
bussinessType: '',
bussinessTypeEN: '',
jobPosition: '',
jobPositionEN: '',
jobDescription: '',
saleEmployee: '',
payDate: '',
wageDate: '',
},
],
image: new File([''], 'dummy.jpg'),
});
const indexTab = ref<number>(0);
const statusToggle = ref<boolean>(false);
const profileSubmit = ref<boolean>(false);
const profileFile = ref<File | undefined>(undefined);
const profileUrl = ref<string | null>('');
2024-04-23 11:15:25 +00:00
const infoDrawer = ref(false);
2024-06-06 10:28:59 +00:00
const infoDrawerEdit = ref(false);
const inputFile = (() => {
const element = document.createElement('input');
element.type = 'file';
element.accept = 'image/*';
const reader = new FileReader();
reader.addEventListener('load', () => {
if (typeof reader.result === 'string') profileUrl.value = reader.result;
});
element.addEventListener('change', () => {
profileFile.value = element.files?.[0];
if (profileFile.value) {
reader.readAsDataURL(profileFile.value);
}
});
return element;
})();
const itemCard = [
{
icon: 'mdi:office-building',
text: 'customerLegalEntity',
color: 'var(--purple-8)',
},
{
icon: 'heroicons:user-solid',
text: 'customerNaturalPerson',
color: 'var(--green-9)',
},
];
const customerStats = [
2024-04-22 13:42:02 +07:00
{
id: 1,
count: 2,
2024-04-24 02:38:54 +00:00
name: 'customerLegalEntity',
2024-04-22 13:42:02 +07:00
},
{
id: 2,
count: 3,
2024-04-24 10:27:59 +07:00
name: 'customerNaturalPerson',
2024-04-22 13:42:02 +07:00
},
];
const dialogCustomerType = ref<boolean>(false);
const dialogInputForm = ref<boolean>(false);
2024-04-22 13:42:02 +07:00
const selectorLabel = ref<string>('');
const selectorList = computed(() => [
{ label: 'EMPLOYER', count: 0 },
{ label: 'WORKER', count: 0 },
]);
2024-06-06 17:10:58 +07:00
const customerType = ref<
'customerLegalEntity' | 'customerNaturalPerson' | undefined
>('customerLegalEntity');
function triggerCreate(type: 'customerLegalEntity' | 'customerNaturalPerson') {
customerType.value = type;
openDialogInputForm();
dialogCustomerType.value = false;
}
function openDialogCustomerType() {
dialogCustomerType.value = true;
}
2024-04-23 11:15:25 +00:00
function openDialogInputForm(action: 'FORM' | 'INFO' = 'FORM', id?: string) {
if (action === 'INFO') {
if (!id) return;
infoDrawer.value = true;
} else {
dialogInputForm.value = true;
}
}
function onClose() {
infoDrawer.value = false;
dialogInputForm.value = false;
}
2024-06-06 17:10:58 +07:00
function clearForm() {
customerType.value = undefined;
dialogInputForm.value = false;
formData.value = {
status: 'CREATED',
customerType: 'CORP',
customerName: '',
customerNameEN: '',
taxNo: '',
customerBranch: [
{
address: '',
addressEN: '',
provinceId: '',
districtId: '',
subDistrictId: '',
zipCode: '',
email: '',
telephoneNo: '',
name: '',
status: 'CREATED',
taxNo: '',
nameEN: '',
legalPersonNo: '',
registerName: '',
registerDate: null,
authorizedCapital: '',
employmentOffice: '',
bussinessType: '',
bussinessTypeEN: '',
jobPosition: '',
jobPositionEN: '',
jobDescription: '',
saleEmployee: '',
payDate: '',
wageDate: '',
},
],
image: new File([''], 'dummy.jpg'),
};
}
async function onSubmit() {
await create({
...formData.value,
customerType:
customerType.value === 'customerLegalEntity' ? 'CORP' : 'PERS',
image: (profileFile.value ?? new File([''], 'dummy.jpg')) as File,
});
clearForm();
}
2024-06-06 10:28:59 +00:00
function undo() {
infoDrawerEdit.value = false;
}
2024-04-22 13:42:02 +07:00
</script>
<template>
<div class="column q-pb-lg">
<div class="text-h6 text-weight-bold q-mb-md">
{{ $t('customerManagement') }}
2024-04-22 13:42:02 +07:00
</div>
<div class="row full-width q-mb-md no-wrap">
<SelectorList
:list="selectorList"
v-model:selector="selectorLabel"
class="q-mr-md col-4"
/>
<!-- stat -->
<AppBox bordered class="column full-width">
<div class="row q-pb-sm justify-between items-center">
2024-04-24 10:23:19 +07:00
<div class="text-weight-bold text-subtitle1">
{{ $t('customerStatTitle') }}
</div>
{{ selectorLabel }}
<q-btn
id="btn-add-customer"
dense
unelevated
:label="'+ ' + $t('customerAdd')"
padding="4px 16px"
@click="openDialogCustomerType()"
style="background-color: var(--cyan-6); color: white"
/>
2024-04-22 13:42:02 +07:00
</div>
<div class="row full-width q-py-md" style="overflow-x: auto">
<StatCardComponent
v-if="customerStats"
2024-04-23 11:15:25 +00:00
labelI18n
2024-04-22 13:42:02 +07:00
:branch="
customerStats.map((v) => ({
2024-04-22 13:42:02 +07:00
count: v.count,
2024-04-24 02:38:54 +00:00
label: v.name,
color: v.name === 'customerLegalEntity' ? 'purple' : 'green',
2024-04-22 13:42:02 +07:00
}))
"
:dark="$q.dark.isActive"
class="no-wrap"
/>
</div>
</AppBox>
</div>
<!-- main -->
<AppBox bordered class="column" style="width: 100%; min-height: 70vh">
2024-04-23 11:15:25 +00:00
<div v-if="false" class="row q-mb-md justify-between">
<div class="col-1 self-end">
<div class="row">
<TooltipComponent
title="customerTooltipTitle"
caption="customerTooltipCaption"
imgSrc="personnel-table-"
/>
</div>
</div>
<div
class="col self-center"
style="display: flex; flex-grow: 1; align-items: center"
>
<AddButton
:label="'customerAdd'"
:cyanOn="true"
@trigger="openDialogCustomerType()"
2024-04-22 13:42:02 +07:00
/>
</div>
</div>
<div
2024-04-23 11:15:25 +00:00
class="row full-width customer-row"
:style="`grid-template-columns: repeat(${$q.screen.lt.sm ? '1' : '4'}, 1fr)`"
2024-04-22 13:42:02 +07:00
>
2024-04-23 11:15:25 +00:00
<UsersDetailCardComponent
color="purple"
:metadata="{ id: '1', disabled: false }"
:list="{
id: '1',
type: 'customerLegalEntity',
name: 'เจมส์ บอน',
code: 'HQ007',
detail: [
{
label: 'ชื่อบริษัท/นิติบุคคล ภาษาไทย',
value: 'บริษัทลับ',
},
{
label: 'ชื่อบริษัท/นิติบุคคล ภาษาไทย',
value: 'บริษัทลับ',
},
],
}"
2024-06-07 02:48:48 +00:00
@enter-card="console.log('enter')"
@view-card="openDialogInputForm"
2024-04-23 11:15:25 +00:00
/>
<UsersDetailCardComponent
color="green"
:metadata="{ id: '1', disabled: false }"
:list="{
id: '2',
type: 'customerNaturalPerson',
name: 'ขอบใจ ขอบใจ',
code: 'HQ006',
detail: [
{
label: 'ชื่อบริษัท/นิติบุคคล ภาษาไทย',
value: 'บริษัทเฟรบเป้',
},
{
label: 'ชื่อบริษัท/นิติบุคคล ภาษาไทย',
value: 'บริษัทเฟรบเป้',
},
],
}"
2024-06-07 02:48:48 +00:00
@enter-card="console.log('enter')"
@view-card="openDialogInputForm"
/>
</div>
</AppBox>
</div>
<FormDialog
v-model:modal="dialogCustomerType"
:title="$t('customerCardUserType')"
no-footer
no-app-box
:max-width="80"
>
<template #body>
<div class="row q-gutter-xl q-pa-sm">
<ItemCard
v-for="i in itemCard"
:key="i.text"
:icon="i.icon"
:text="i.text"
:color="i.color"
2024-04-22 13:42:02 +07:00
@trigger="
() => {
triggerCreate(
i.text as 'customerLegalEntity' | 'customerNaturalPerson',
);
2024-04-22 13:42:02 +07:00
}
"
/>
</div>
</template>
</FormDialog>
<FormDialog
v-model:modal="dialogInputForm"
:title="`เพิ่มนายจ้าง`"
:customer-label="customerType"
2024-06-06 17:10:58 +07:00
:submit="
() => {
onSubmit();
}
"
:close="() => {}"
>
<template #prepend>
<ProfileUpload
v-model:url-profile="profileUrl"
v-model:status-toggle="statusToggle"
v-model:profile-submit="profileSubmit"
@input-file="inputFile.click()"
/>
</template>
2024-04-22 17:00:30 +07:00
<template #information>
2024-06-06 17:10:58 +07:00
<BasicInformation
dense
outlined
separator
:type-customer="customerType"
v-model:customer-name="formData.customerName"
v-model:customer-name-en="formData.customerNameEN"
v-model:tax-no="formData.taxNo"
/>
2024-04-22 17:00:30 +07:00
</template>
2024-04-23 11:37:27 +07:00
<template #address>
<!-- <FormCustomerBranch separator dense outlined /> -->
2024-04-24 09:19:05 +07:00
<div class="col-3 app-text-muted">
{{ $t('formDialogCustomerBranch') }}
</div>
2024-06-06 16:03:47 +07:00
<div class="col-12 row bordered q-pt-none rounded">
<TabComponent
v-model:customer-branch="formData.customerBranch"
2024-04-24 09:19:05 +07:00
v-model:tab-index="indexTab"
>
<template #address>
<FormAddress
v-if="
indexTab !== undefined && formData.customerBranch?.[indexTab]
"
v-model:address="formData.customerBranch[indexTab].address"
v-model:address-e-n="formData.customerBranch[indexTab].addressEN"
v-model:province-id="formData.customerBranch[indexTab].provinceId"
v-model:district-id="formData.customerBranch[indexTab].districtId"
v-model:sub-district-id="
formData.customerBranch[indexTab].subDistrictId
"
v-model:zip-code="formData.customerBranch[indexTab].zipCode"
separator
dense
outlined
/>
</template>
<template #businessInformation>
<FormBusiness
v-if="
indexTab !== undefined && formData.customerBranch?.[indexTab]
"
2024-06-06 17:10:58 +07:00
v-model:employment-office="
formData.customerBranch[indexTab].employmentOffice
"
v-model:bussiness-type="
formData.customerBranch[indexTab].bussinessType
"
v-model:bussiness-type-en="
formData.customerBranch[indexTab].bussinessTypeEN
"
v-model:job-position="
formData.customerBranch[indexTab].jobPosition
"
v-model:job-position-en="
formData.customerBranch[indexTab].jobPositionEN
"
v-model:job-description="
formData.customerBranch[indexTab].jobDescription
"
v-model:sale-employee="
formData.customerBranch[indexTab].saleEmployee
"
v-model:pay-date="formData.customerBranch[indexTab].payDate"
v-model:wage-date="formData.customerBranch[indexTab].wageDate"
separator
dense
outlined
/>
</template>
2024-04-23 13:51:32 +07:00
<template #about>
<AboutComponent
v-if="
indexTab !== undefined && formData.customerBranch?.[indexTab]
"
2024-06-06 17:10:58 +07:00
:type-customer="customerType"
v-model:tax-no="formData.customerBranch[indexTab].taxNo"
v-model:customer-name="formData.customerBranch[indexTab].name"
v-model:customer-english-name="
formData.customerBranch[indexTab].nameEN
"
v-model:authorized-capital="
formData.customerBranch[indexTab].authorizedCapital
"
v-model:register-name="
formData.customerBranch[indexTab].registerName
"
v-model:register-date="
formData.customerBranch[indexTab].registerDate
"
dense
outlined
2024-06-06 16:03:47 +07:00
bordered
separator
/>
2024-04-23 13:51:32 +07:00
</template>
<template #contactInformation>
<ContactComponent
v-if="
indexTab !== undefined && formData.customerBranch?.[indexTab]
"
v-model:mail="formData.customerBranch[indexTab].email"
v-model:telephone="formData.customerBranch[indexTab].telephoneNo"
dense
outlined
separator
/>
2024-04-23 13:51:32 +07:00
</template>
<template #otherDocuments>
<OtherInformation
v-if="
indexTab !== undefined && formData.customerBranch?.[indexTab]
"
dense
outlined
/>
2024-04-23 13:51:32 +07:00
</template>
</TabComponent>
</div>
2024-04-23 11:37:27 +07:00
</template>
</FormDialog>
2024-04-23 11:15:25 +00:00
<DrawerInfo
2024-06-06 10:28:59 +00:00
title="บริษัททดสอบ"
2024-04-23 11:15:25 +00:00
v-model:drawer-open="infoDrawer"
badgeLabel="HQ006"
badgeClass="app-bg-pers"
2024-06-06 10:28:59 +00:00
:undo="() => undo()"
:isEdit="infoDrawerEdit"
:close="() => onClose()"
:editData="() => (infoDrawerEdit = true)"
2024-04-23 11:15:25 +00:00
>
<template #info>
2024-06-06 10:28:59 +00:00
<InfoForm>
2024-04-23 11:15:25 +00:00
<template #person-card>
<div class="q-ma-md">
<AppBox class="surface-1" style="padding: 0">
<UsersDetailCardComponent
no-bg
no-detail
no-hover
color="purple"
:metadata="{ id: '1', disabled: false }"
:list="{
id: '2',
type: 'customerNaturalPerson',
name: 'เจมส์ บอน',
code: 'HQ006',
detail: [
{
label: 'ชื่อบริษัท/นิติบุคคล ภาษาไทย',
value: 'บริษัทเฟรบเป้',
},
{
label: 'ชื่อบริษัท/นิติบุคคล ภาษาไทย',
value: 'บริษัทเฟรบเป้',
},
],
}"
@enter-card="openDialogInputForm"
/>
</AppBox>
</div>
</template>
2024-06-06 10:28:59 +00:00
<template #information>
<BasicInformation
dense
outlined
separator
:readonly="!infoDrawerEdit"
/>
</template>
<template #address>
<!-- <FormCustomerBranch separator dense outlined /> -->
<div class="col-3 app-text-muted">
{{ $t('formDialogCustomerBranch') }}
</div>
<div class="col-12 row bordered q-pt-none rounded">
<TabComponent
:readonly="!infoDrawerEdit"
v-model:customer-branch="formData.customerBranch"
v-model:tab-index="indexTab"
>
<template #address>
<FormAddress
v-if="
indexTab !== undefined &&
formData.customerBranch?.[indexTab]
"
v-model:address="formData.customerBranch[indexTab].address"
v-model:address-e-n="
formData.customerBranch[indexTab].addressEN
"
v-model:province-id="
formData.customerBranch[indexTab].provinceId
"
v-model:district-id="
formData.customerBranch[indexTab].districtId
"
v-model:sub-district-id="
formData.customerBranch[indexTab].subDistrictId
"
v-model:zip-code="formData.customerBranch[indexTab].zipCode"
separator
dense
outlined
:readonly="!infoDrawerEdit"
/>
</template>
<template #businessInformation>
<FormBusiness
v-if="
indexTab !== undefined &&
formData.customerBranch?.[indexTab]
"
separator
dense
outlined
:readonly="!infoDrawerEdit"
/>
</template>
<template #about>
<AboutComponent
v-if="
indexTab !== undefined &&
formData.customerBranch?.[indexTab]
"
v-model:customer-name="formData.customerBranch[indexTab].name"
v-model:customer-english-name="
formData.customerBranch[indexTab].nameEN
"
v-model:authorized-capital="
formData.customerBranch[indexTab].authorizedCapital
"
v-model:register-name="
formData.customerBranch[indexTab].registerName
"
v-model:register-date="
formData.customerBranch[indexTab].registerDate
"
dense
outlined
bordered
separator
:readonly="!infoDrawerEdit"
/>
</template>
<template #contactInformation>
<ContactComponent
v-if="
indexTab !== undefined &&
formData.customerBranch?.[indexTab]
"
v-model:mail="formData.customerBranch[indexTab].email"
v-model:telephone="
formData.customerBranch[indexTab].telephoneNo
"
dense
outlined
separator
:readonly="!infoDrawerEdit"
/>
</template>
<template #otherDocuments>
<OtherInformation
v-if="
indexTab !== undefined &&
formData.customerBranch?.[indexTab]
"
dense
outlined
:readonly="!infoDrawerEdit"
/>
</template>
</TabComponent>
</div>
</template>
2024-04-23 11:15:25 +00:00
</InfoForm>
</template>
</DrawerInfo>
2024-04-22 13:42:02 +07:00
</template>
2024-04-23 11:15:25 +00:00
<style scoped>
.customer-row {
display: grid;
gap: var(--size-6);
}
</style>