This commit is contained in:
Viet An
2026-06-09 11:43:27 +07:00
parent 5325168248
commit bb05320d65
19 changed files with 418 additions and 1008 deletions

View File

@@ -1,405 +1,251 @@
<template>
<div
v-if="!selectedCustomerType && isNewCustomer && !props.customerType"
class="p-5"
>
<h3 class="title is-4 mb-5 has-text-centered">
{{ isVietnamese ? "Chọn loại khách hàng" : "Select Customer Type" }}
</h3>
<div v-if="isLoaded && record">
<div class="columns is-multiline">
<div class="column is-4">
<div class="field">
<label class="label"
>{{ isIndividual ? "Họ và tên" : "Tên tổ chức" }}<b class="ml-1 has-text-danger">*</b></label
>
<div class="control">
<input
class="input"
type="text"
v-model="record.fullname"
/>
</div>
<p
class="help is-danger"
v-if="errors.fullname"
>
{{ errors.fullname }}
</p>
</div>
</div>
<div class="column is-4">
<div class="field">
<label class="label"
>{{ dataLang && findFieldName("phone_number")[lang] }}<b class="ml-1 has-text-danger">*</b></label
>
<InputPhone
:record="record"
attr="phone"
@phone="selected('phone', $event)"
/>
<p
class="help is-danger"
v-if="errors.phone"
>
{{ errors.phone }}
<a
class="has-text-primary"
v-if="existedCustomer"
@click="showCustomer()"
>Chi tiết</a
>
</p>
</div>
</div>
<div class="column is-4">
<div class="field">
<label class="label">Email</label>
<InputEmail
:record="record"
attr="email"
@email="selected('email', $event)"
/>
<p
class="help is-danger"
v-if="errors.email"
>
{{ errors.email }}
</p>
</div>
</div>
</div>
<div class="columns is-multiline">
<div class="column is-6">
<button
:disabled="!$getEditRights('edit', { code: 'individual', category: 'submenu' })"
class="button is-large is-fullwidth"
style="height: 120px"
@click="selectCustomerType(1)"
>
<div class="has-text-centered">
<div>
<SvgIcon v-bind="{ name: 'user.svg', type: 'black', size: 40 }"></SvgIcon>
</div>
<div class="title is-5 mb-0">
{{ isVietnamese ? "Cá nhân" : "Individual" }}
</div>
</div>
</button>
</div>
<div class="column is-6">
<button
:disabled="!$getEditRights('edit', { code: 'org', category: 'submenu' })"
class="button is-large is-fullwidth"
style="height: 120px"
@click="selectCustomerType(2)"
>
<div class="has-text-centered">
<div>
<SvgIcon v-bind="{ name: 'building.svg', type: 'black', size: 40 }"></SvgIcon>
</div>
<div class="title is-5 mb-0">
{{ isVietnamese ? "Tổ chức" : "Organization" }}
</div>
</div>
</button>
</div>
</div>
</div>
<template v-else-if="isLoaded">
<div v-if="record && isLoaded">
<div class="columns is-multiline">
<div class="column is-4">
<div class="field">
<label class="label"
>{{ isIndividual ? "Họ và tên" : "Tên tổ chức" }}<b class="ml-1 has-text-danger">*</b></label
>
<div class="control">
<input
class="input"
type="text"
v-model="record.fullname"
/>
</div>
<p
class="help is-danger"
v-if="errors.fullname"
>
{{ errors.fullname }}
</p>
</div>
</div>
<div class="column is-4">
<div class="field">
<label class="label"
>{{ dataLang && findFieldName("phone_number")[lang] }}<b class="ml-1 has-text-danger">*</b></label
>
<InputPhone
v-bind="{ record: record, attr: 'phone' }"
@phone="selected('phone', $event)"
></InputPhone>
<p
class="help is-danger"
v-if="errors.phone"
>
{{ errors.phone }}
<a
class="has-text-primary"
v-if="existedCustomer"
@click="showCustomer()"
>Chi tiết</a
>
</p>
</div>
</div>
<div class="column is-4">
<div class="field">
<label class="label">Email</label>
<InputEmail
v-bind="{ record: record, attr: 'email' }"
@email="selected('email', $event)"
></InputEmail>
<p
class="help is-danger"
v-if="errors.email"
>
{{ errors.email }}
</p>
</div>
</div>
</div>
<div class="columns is-multiline">
<div class="column is-6">
<div class="field">
<label class="label">Địa chỉ liên hệ</label>
<input
class="input"
type="text"
v-model="record.contact_address"
/>
</div>
</div>
<div class="column is-6">
<div class="field">
<label class="label">{{ isIndividual ? "Địa chỉ thường trú" : "Địa chỉ đăng ký" }}</label>
<input
class="input"
type="text"
v-model="record.address"
/>
</div>
</div>
</div>
<div
v-if="isOrganization"
class="columns is-multiline"
>
<div class="column is-6">
<div class="field">
<label class="label">Tài khoản ngân hàng</label>
<input
class="input"
type="text"
v-model="organizationData.bank_account"
/>
</div>
</div>
<div class="column is-6">
<div class="field">
<label class="label">Tên ngân hàng</label>
<input
class="input"
type="text"
v-model="organizationData.bank_name"
/>
</div>
</div>
</div>
<div class="columns is-multiline">
<div class="column is-3">
<div class="field">
<label class="label"
>{{ isIndividual ? "Giấy tờ tùy thân" : "Giấy tờ" }}<b class="ml-1 has-text-danger">*</b></label
>
<SearchBox
v-bind="{
vdata: filteredLegalTypes,
api: 'legaltype',
field: isVietnamese ? 'name' : 'en',
column: ['name', 'en'],
first: true,
optionid: record.legal_type,
}"
@option="selected('legal_type', $event)"
></SearchBox>
</div>
</div>
<div class="column is-3">
<div class="field">
<label class="label"
>{{ dataLang && findFieldName("idnum")[lang] }}<b class="ml-1 has-text-danger">*</b></label
>
<input
class="input"
type="text"
v-model="record.legal_code"
/>
<p
class="help is-danger"
v-if="errors.legal_code"
>
{{ errors.legal_code }}
</p>
</div>
</div>
<div class="column is-3">
<div class="field">
<label class="label"
>{{ dataLang && findFieldName("issued_date")[lang] }}<b class="ml-1 has-text-danger">*</b></label
>
<Datepicker
v-bind="{
record: record,
attr: 'issued_date',
maxdate: new Date(),
}"
@date="selected('issued_date', $event)"
></Datepicker>
<p
class="help is-danger"
v-if="errors.issued_date"
>
{{ errors.issued_date }}
</p>
</div>
</div>
<div class="column is-3">
<div class="field">
<label class="label">{{ dataLang && findFieldName("issued_place")[lang] }}</label>
<SearchBox
v-bind="{
api: 'issuedplace',
field: 'name',
column: ['name'],
first: true,
position: 'is-bottom-right',
optionid: record.issued_place,
filter: { id__in: isIndividual ? [2, 3] : [4, 5] },
}"
@option="selected('issued_place', $event)"
></SearchBox>
</div>
</div>
</div>
<div
class="columns is-multiline"
v-if="isIndividual"
>
<div class="column is-3">
<div class="field">
<label class="label">{{ dataLang && findFieldName("gender")[lang] }}</label>
<SearchBox
v-bind="{
vdata: store.sex,
api: 'sex',
field: isVietnamese ? 'name' : 'en',
column: ['name', 'en'],
first: true,
optionid: individualData.sex,
}"
@option="selectedIndividual('sex', $event)"
></SearchBox>
</div>
</div>
<div class="column is-3">
<div class="field">
<label class="label">{{ dataLang && findFieldName("birth_date")[lang] }}</label>
<Datepicker
v-bind="{
record: individualData,
attr: 'dob',
maxdate: new Date(),
}"
@date="selectedIndividual('dob', $event)"
></Datepicker>
<p
class="help is-danger"
v-if="errors.dob"
>
{{ errors.dob }}
</p>
</div>
</div>
</div>
<div class="columns is-multiline">
<div class="column is-12">
<div class="field">
<label class="label">{{ dataLang && findFieldName("note")[lang] }}</label>
<textarea
class="textarea"
v-model="record.note"
rows="2"
></textarea>
</div>
</div>
</div>
<div class="mt-5 mb-4">
<h4 class="title is-6 has-text-warning">
{{ isIndividual ? "Người liên quan" : "Người đại diện pháp luật" }}
</h4>
</div>
<div
class="columns is-multiline mb-0 is-2"
v-for="(v, i) in localPeople"
:key="i"
>
<div class="column">
<label
class="label"
v-if="i === 0"
>{{ findFieldName("select")[lang] }}</label
>
<SearchBox
v-bind="{
api: 'people',
field: 'label',
column: ['code', 'fullname', 'phone'],
first: true,
optionid: v.people,
position: 'is-top-left',
addon: peopleAddon,
viewaddon: peopleviewAddon,
}"
@option="selectPeople($event, v, i)"
></SearchBox>
</div>
<div class="column is-4">
<label
class="label"
v-if="i === 0"
>{{ isIndividual ? "Quan hệ" : "Chức vụ" }}</label
>
<SearchBox
v-bind="{
api: 'relation',
field: store.lang === 'en' ? 'en' : 'name',
column: ['code', 'name', 'en'],
first: true,
optionid: v.relation,
position: 'is-top-left',
filter: {
id__in: isIndividual ? [1, 2, 3, 4, 5, 6, 7, 8] : [9, 10, 11, 12],
},
}"
@option="selectRelation($event, v, i)"
<div class="field">
<label class="label">Địa chỉ liên hệ</label>
<input
class="input"
type="text"
v-model="record.contact_address"
/>
</div>
<div class="column is-narrow">
<label
class="label"
v-if="i === 0"
>&nbsp;</label
>
<div
class="buttons is-gap-0.5 is-flex-wrap-nowrap are-small"
style="height: 40px"
>
<button
class="button is-dark"
@click="add()"
>
<span class="icon">
<SvgIcon v-bind="{ name: 'add4.svg', type: 'white', size: 20 }"></SvgIcon>
</span>
</button>
<button
class="button is-dark"
@click="remove(v, i)"
>
<span class="icon">
<SvgIcon v-bind="{ name: 'bin1.svg', type: 'white', size: 20 }"></SvgIcon>
</span>
</button>
</div>
</div>
<div class="column is-6">
<div class="field">
<label class="label">{{ isIndividual ? "Địa chỉ thường trú" : "Địa chỉ đăng ký" }}</label>
<input
class="input"
type="text"
v-model="record.address"
/>
</div>
</div>
<div class="mt-5 buttons is-right">
<button
class="button"
@click="emit('close')"
>
{{ isVietnamese ? "Hủy" : "Cancel" }}
</button>
<button
class="button is-primary"
@click="update()"
>
{{ isVietnamese ? "Lưu lại" : "Save" }}
</button>
</div>
<Modal
@close="showmodal = undefined"
v-bind="showmodal"
v-if="showmodal"
></Modal>
</div>
</template>
<div class="columns is-multiline">
<div class="column is-3">
<div class="field">
<label class="label"
>{{ isIndividual ? "Giấy tờ tùy thân" : "Giấy tờ" }}<b class="ml-1 has-text-danger">*</b></label
>
<SearchBox
v-bind="{
vdata: filteredLegalTypes,
api: 'legaltype',
field: isVietnamese ? 'name' : 'en',
column: ['name', 'en'],
first: true,
optionid: record.legal_type,
}"
@option="selected('legal_type', $event)"
></SearchBox>
</div>
</div>
<div class="column is-3">
<div class="field">
<label class="label"
>{{ dataLang && findFieldName("idnum")[lang] }}<b class="ml-1 has-text-danger">*</b></label
>
<input
class="input"
type="text"
v-model="record.legal_code"
/>
<p
class="help is-danger"
v-if="errors.legal_code"
>
{{ errors.legal_code }}
</p>
</div>
</div>
<div class="column is-3">
<div class="field">
<label class="label"
>{{ dataLang && findFieldName("issued_date")[lang] }}<b class="ml-1 has-text-danger">*</b></label
>
<Datepicker
v-bind="{
record: record,
attr: 'issued_date',
maxdate: new Date(),
}"
@date="selected('issued_date', $event)"
></Datepicker>
<p
class="help is-danger"
v-if="errors.issued_date"
>
{{ errors.issued_date }}
</p>
</div>
</div>
<div class="column is-3">
<div class="field">
<label class="label">{{ dataLang && findFieldName("issued_place")[lang] }}</label>
<SearchBox
v-bind="{
api: 'issuedplace',
field: 'name',
column: ['name'],
first: true,
position: 'is-bottom-right',
optionid: record.issued_place,
filter: { id__in: isIndividual ? [2, 3] : [4, 5] },
}"
@option="selected('issued_place', $event)"
></SearchBox>
</div>
</div>
</div>
<div
class="columns is-multiline"
v-if="isIndividual"
>
<div class="column is-3">
<div class="field">
<label class="label">{{ dataLang && findFieldName("gender")[lang] }}</label>
<SearchBox
v-bind="{
vdata: store.sex,
api: 'sex',
field: isVietnamese ? 'name' : 'en',
column: ['name', 'en'],
first: true,
optionid: individualData.sex,
}"
@option="selectedIndividual('sex', $event)"
></SearchBox>
</div>
</div>
<div class="column is-3">
<div class="field">
<label class="label">{{ dataLang && findFieldName("birth_date")[lang] }}</label>
<Datepicker
v-bind="{
record: individualData,
attr: 'dob',
maxdate: new Date(),
}"
@date="selectedIndividual('dob', $event)"
></Datepicker>
<p
class="help is-danger"
v-if="errors.dob"
>
{{ errors.dob }}
</p>
</div>
</div>
</div>
<div class="columns is-multiline">
<div class="column is-12">
<div class="field">
<label class="label">{{ dataLang && findFieldName("note")[lang] }}</label>
<textarea
class="textarea"
v-model="record.note"
rows="2"
></textarea>
</div>
</div>
</div>
<div class="mt-5 buttons is-right">
<button
class="button"
@click="emit('close')"
>
{{ isVietnamese ? "Hủy" : "Cancel" }}
</button>
<button
class="button is-primary"
@click="update()"
>
{{ isVietnamese ? "Lưu lại" : "Save" }}
</button>
</div>
<Modal
v-if="showmodal"
v-bind="showmodal"
@close="showmodal = undefined"
/>
</div>
</template>
<script setup>
import { ref, computed, onMounted, watch } from "vue";
import { useNuxtApp } from "#app";
import { isEqual, pick } from "es-toolkit";
import { useStore } from "~/stores/index";
import InputPhone from "~/components/common/InputPhone";
import InputEmail from "~/components/common/InputEmail";
import SearchBox from "~/components/SearchBox";
import Datepicker from "~/components/datepicker/Datepicker";
import { useStore } from "~/stores/index";
import { isEqual, pick } from "es-toolkit";
const emit = defineEmits(["close", "update", "modalevent"]);
const { $getdata, $patchapi, $insertapi, $deleteapi, $empty, $errPhone, $resetNull, $snackbar, $copy } = useNuxtApp();