jws-frontend/src/components/02_personnel-management/FormAddress.vue

318 lines
9 KiB
Vue

<script setup lang="ts">
import { onMounted, watch, reactive } from 'vue';
import useAddressStore, {
District,
Province,
SubDistrict,
} from 'src/stores/address';
defineProps<{
title?: string;
addressTitle?: string;
addressTitleEN?: string;
dense?: boolean;
outlined?: boolean;
readonly?: boolean;
separator?: boolean;
employee?: boolean;
}>();
const adrressStore = useAddressStore();
const address = defineModel('address', { default: '' });
const addressEN = defineModel('addressEN', { default: '' });
const provinceId = defineModel<string | null | undefined>('provinceId');
const districtId = defineModel<string | null | undefined>('districtId');
const subDistrictId = defineModel<string | null | undefined>('subDistrictId');
const zipCode = defineModel<string | null | undefined>('zipCode');
const sameWithEmployer = defineModel<boolean>('sameWithEmployer');
const addrOptions = reactive<{
provinceOps: Province[];
districtOps: District[];
subDistrictOps: SubDistrict[];
}>({
provinceOps: [],
districtOps: [],
subDistrictOps: [],
});
async function fetchProvince() {
const result = await adrressStore.fetchProvince();
if (result) addrOptions.provinceOps = result;
}
async function fetchDistrict() {
if (!provinceId.value) return;
const result = await adrressStore.fetchDistrictByProvinceId(provinceId.value);
if (result) addrOptions.districtOps = result;
}
async function fetchSubDistrict() {
if (!districtId.value) return;
const result = await adrressStore.fetchSubDistrictByProvinceId(
districtId.value,
);
if (result) addrOptions.subDistrictOps = result;
}
async function selectSubDistrict(id: string) {
if (!id) return;
zipCode.value =
addrOptions.subDistrictOps
?.filter((x) => x.id === id)
.map((x) => x.zipCode)[0] ?? '';
}
onMounted(async () => {
await fetchProvince();
await fetchDistrict();
await fetchSubDistrict();
});
watch(provinceId, fetchDistrict);
watch(districtId, fetchSubDistrict);
</script>
<template>
<div class="col-12 app-text-muted row items-center">
{{ title || $t('formDialogTitlePersonnelAddress') }}
<div
v-if="employee"
class="q-ml-lg surface-3 q-px-sm q-py-xs row"
style="border-radius: var(--radius-3)"
>
<span
class="q-px-sm q-mr-lg rounded cursor-pointer"
:class="{ dark: $q.dark.isActive, 'active-addr': sameWithEmployer }"
@click="sameWithEmployer = true"
>
เลอกทอยตามนายจาง
</span>
<span
class="q-px-sm rounded cursor-pointer"
:class="{ dark: $q.dark.isActive, 'active-addr': !sameWithEmployer }"
@click="sameWithEmployer = false"
>
กำหนดเอง
</span>
</div>
</div>
<div class="col-12 row q-col-gutter-y-md">
<div class="col-3 q-pl-xl app-text-muted">
{{ addressTitle || $t('formDialogTitleAddressPure') }}
</div>
<div class="col-9 row q-col-gutter-md">
<q-input
for="input-address"
:dense="dense"
:outlined="readonly ? false : outlined"
:readonly="readonly || sameWithEmployer"
:borderless="readonly"
hide-bottom-space
:label="$t('address')"
class="col-12"
v-model="address"
lazy-rules
:rules="[
(val) =>
(val && val.length > 0) || $t('formDialogInputAddressValidate'),
]"
/>
<q-select
id="select-province"
:dense="dense"
:readonly="readonly || sameWithEmployer"
:outlined="readonly ? false : outlined"
:hide-dropdown-icon="readonly || sameWithEmployer"
:borderless="readonly"
hide-bottom-space
emit-value
map-options
v-model="provinceId"
option-value="id"
option-label="name"
:label="$t('province')"
class="col-3"
:options="addrOptions.provinceOps"
lazy-rules
:rules="[
(val) =>
(val && val.length > 0) || $t('formDialogInputProvinceValidate'),
]"
@update:model-value="districtId = subDistrictId = zipCode = null"
/>
<q-select
id="select-district"
:dense="dense"
:readonly="readonly || sameWithEmployer"
:outlined="readonly ? false : outlined"
:hide-dropdown-icon="readonly || sameWithEmployer"
:borderless="readonly"
hide-bottom-space
emit-value
map-options
v-model="districtId"
option-value="id"
option-label="name"
:label="$t('district')"
class="col-3"
:options="addrOptions.districtOps"
lazy-rules
:rules="[
(val) =>
(val && val.length > 0) || $t('formDialogInputDistrictValidate'),
]"
@update:model-value="subDistrictId = zipCode = null"
/>
<q-select
id="select-sub-district"
:dense="dense"
:readonly="readonly || sameWithEmployer"
:outlined="readonly ? false : outlined"
:hide-dropdown-icon="readonly || sameWithEmployer"
:borderless="readonly"
hide-bottom-space
emit-value
map-options
v-model="subDistrictId"
option-value="id"
option-label="name"
:label="$t('subDistrict')"
class="col-3"
:options="addrOptions.subDistrictOps"
lazy-rules
:rules="[
(val) =>
(val && val.length > 0) || $t('formDialogInputSubDistrictValidate'),
]"
@update:model-value="(v: string) => selectSubDistrict(v)"
/>
<q-input
for="input-zip-code"
:dense="dense"
:outlined="readonly ? false : outlined"
:borderless="readonly"
readonly
:label="$t('zipCode')"
class="col-3"
v-model="zipCode"
/>
</div>
<div class="col-3 q-pl-xl app-text-muted">
{{ addressTitleEN || $t('formDialogTitleAddressPure') }}
</div>
<div class="col-9 row q-col-gutter-md">
<q-input
for="input-address-en"
:dense="dense"
:readonly="readonly || sameWithEmployer"
:outlined="readonly ? false : outlined"
:borderless="readonly"
hide-bottom-space
:label="$t('address')"
class="col-12"
v-model="addressEN"
lazy-rules
:rules="[
(val) =>
(val && val.length > 0) || $t('formDialogInputAddressValidate'),
]"
/>
<q-select
id="select-province-en"
:dense="dense"
:readonly="readonly || sameWithEmployer"
:outlined="readonly ? false : outlined"
:borderless="readonly"
:hide-dropdown-icon="readonly || sameWithEmployer"
emit-value
map-options
v-model="provinceId"
option-value="id"
option-label="nameEN"
:label="$t('province')"
class="col-3"
:options="addrOptions.provinceOps"
lazy-rules
:rules="[
(val) =>
(val && val.length > 0) || $t('formDialogInputProvinceValidate'),
]"
@update:model-value="districtId = subDistrictId = zipCode = null"
/>
<q-select
id="select-district-en"
:dense="dense"
:readonly="readonly || sameWithEmployer"
:outlined="readonly ? false : outlined"
:borderless="readonly"
:hide-dropdown-icon="readonly || sameWithEmployer"
emit-value
map-options
v-model="districtId"
option-value="id"
option-label="nameEN"
:label="$t('district')"
class="col-3"
:options="addrOptions.districtOps"
lazy-rules
:rules="[
(val) =>
(val && val.length > 0) || $t('formDialogInputDistrictValidate'),
]"
@update:model-value="subDistrictId = zipCode = null"
/>
<q-select
id="select-sub-district-en"
:dense="dense"
:readonly="readonly || sameWithEmployer"
:outlined="readonly ? false : outlined"
:borderless="readonly"
:hide-dropdown-icon="readonly || sameWithEmployer"
emit-value
map-options
v-model="subDistrictId"
option-value="id"
option-label="nameEN"
:label="$t('subDistrict')"
class="col-3"
:options="addrOptions.subDistrictOps"
lazy-rules
:rules="[
(val) =>
(val && val.length > 0) || $t('formDialogInputSubDistrictValidate'),
]"
@update:model-value="(v: string) => selectSubDistrict(v)"
/>
<q-input
for="input-zip-code"
:dense="dense"
:outlined="readonly ? false : outlined"
:borderless="readonly"
readonly
zip="zip-en"
:label="$t('zipCode')"
class="col-3"
v-model="zipCode"
/>
</div>
</div>
<q-separator
v-if="separator"
class="col-12 q-mb-md"
style="padding-block: 0.5px; margin-top: 32px"
/>
</template>
<style lang="scss" scoped>
.active-addr {
color: hsl(var(--info-bg));
background-color: hsla(var(--info-bg) / 0.1);
&.dark {
background-color: var(--surface-1);
}
}
</style>