refactor(address): update address models and forms to use standardized fields
- Add preload relationships to address-related models - Rename postalCode to postalCode_code for consistency - Simplify location type handling with hidden fields - Update validation schemas and form components - Improve address display in patient preview
This commit is contained in:
@@ -1,13 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import type { Person } from '~/models/person'
|
||||
import type { PersonAddress } from '~/models/person-address'
|
||||
import type { PersonContact } from '~/models/person-contact'
|
||||
import type { PersonRelative } from '~/models/person-relative'
|
||||
|
||||
import DetailRow from '~/components/pub/my-ui/form/view/detail-row.vue'
|
||||
import DetailSection from '~/components/pub/my-ui/form/view/detail-section.vue'
|
||||
import { type PersonAddress, formatAddress } from '~/models/person-address'
|
||||
|
||||
import {
|
||||
addressLocationTypeCode,
|
||||
educationCodes,
|
||||
genderCodes,
|
||||
occupationCodes,
|
||||
@@ -37,16 +35,16 @@ const relationshipOptions = mapToComboboxOptList(relationshipCodes)
|
||||
const personContactTypeOptions = mapToComboboxOptList(personContactTypes)
|
||||
|
||||
// Computed addresses from nested data
|
||||
const residentAddress = computed(() => {
|
||||
const domicileAddress = computed(() => {
|
||||
const addresses = props.person.addresses
|
||||
const resident = addresses?.find((addr) => addr.locationType === 'resident')
|
||||
return resident?.address || 'Jl. Puncak Borobudur Blok M No. 321, Lowokwaru, Kota Malang, Jawa Timur'
|
||||
const resident = addresses?.find((addr) => addr.locationType === 'domicile')
|
||||
return formatAddress(resident)
|
||||
})
|
||||
|
||||
const primaryAddress = computed(() => {
|
||||
const identityAddress = computed(() => {
|
||||
const addresses = props.person.addresses
|
||||
const primary = addresses?.find((addr) => addr.locationType === 'primary')
|
||||
return primary?.address || 'Perumahan Araya Cluster B, No 22, Blimbing, Kota Malang, Jawa Timur'
|
||||
const primary = addresses?.find((addr) => addr.locationType === 'identity')
|
||||
return formatAddress(primary)
|
||||
})
|
||||
|
||||
const patientAge = computed(() => {
|
||||
@@ -68,6 +66,7 @@ const patientAge = computed(() => {
|
||||
// #endregion
|
||||
|
||||
// #region Functions
|
||||
|
||||
// #endregion region
|
||||
|
||||
// #region Utilities & event handlers
|
||||
@@ -83,10 +82,9 @@ function onClick(type: string) {
|
||||
<template>
|
||||
<DetailSection title="Data Pasien">
|
||||
<DetailRow label="Nomor ID">{{ person.id || '-' }}</DetailRow>
|
||||
<DetailRow label="Sapaan">{{ '-' }}</DetailRow>
|
||||
<DetailRow label="Nama Lengkap">{{ person.name || '-' }}</DetailRow>
|
||||
<DetailRow label="Tempat, tanggal lahir">
|
||||
{{ person.birthRegency_code || '-' }},
|
||||
{{ person.birthRegency?.name || '-' }},
|
||||
{{ person.birthDate ? new Date(person.birthDate).toLocaleDateString() : '-' }}
|
||||
</DetailRow>
|
||||
<DetailRow label="Usia">{{ patientAge || '-' }}</DetailRow>
|
||||
@@ -117,8 +115,8 @@ function onClick(type: string) {
|
||||
</DetailSection>
|
||||
|
||||
<DetailSection title="Alamat">
|
||||
<DetailRow label="Alamat Domisili">{{ residentAddress || '-' }}</DetailRow>
|
||||
<DetailRow label="Alamat KTP">{{ primaryAddress || '-' }}</DetailRow>
|
||||
<DetailRow :label="addressLocationTypeCode.domicile || 'Alamat Domisili'">{{ domicileAddress || '-' }}</DetailRow>
|
||||
<DetailRow :label="addressLocationTypeCode.identity || 'Alamat KTP'">{{ identityAddress || '-' }}</DetailRow>
|
||||
</DetailSection>
|
||||
<DetailSection title="Kontak">
|
||||
<template v-if="person.contacts && person.contacts.length > 0">
|
||||
|
||||
@@ -18,14 +18,7 @@ const props = defineProps<{
|
||||
isRequired?: boolean
|
||||
}>()
|
||||
|
||||
const {
|
||||
fieldName = 'zipCode',
|
||||
placeholder = 'Kode Pos',
|
||||
errors,
|
||||
class: containerClass,
|
||||
selectClass,
|
||||
fieldGroupClass,
|
||||
} = props
|
||||
const { fieldName = 'zipCode', placeholder = 'Kode Pos', errors, class: containerClass, fieldGroupClass } = props
|
||||
|
||||
const villageCodeRef = toRef(props, 'villageCode')
|
||||
const { postalCodeOptions, isLoading, error } = usePostalCodes(villageCodeRef)
|
||||
|
||||
@@ -43,7 +43,7 @@ const fieldStates: Record<string, { dependsOn?: string; placeholder: string }> =
|
||||
regency_code: { dependsOn: 'province_code', placeholder: 'Pilih provinsi dahulu' },
|
||||
district_code: { dependsOn: 'regency_code', placeholder: 'Pilih kabupaten/kota dahulu' },
|
||||
village_code: { dependsOn: 'district_code', placeholder: 'Pilih kecamatan dahulu' },
|
||||
postalCode: { dependsOn: 'village_code', placeholder: 'Pilih kelurahan dahulu' },
|
||||
postalCode_code: { dependsOn: 'village_code', placeholder: 'Pilih kelurahan dahulu' },
|
||||
address: { placeholder: 'Masukkan alamat' },
|
||||
rt: { placeholder: '001' },
|
||||
rw: { placeholder: '002' },
|
||||
@@ -73,7 +73,7 @@ function getFieldState(field: string) {
|
||||
const isDisabledByDependency = !dependencyValue
|
||||
|
||||
// Jika isSame, semua field location disabled
|
||||
if (isSame && ['regency_code', 'district_code', 'village_code', 'postalCode'].includes(field)) {
|
||||
if (isSame && ['regency_code', 'district_code', 'village_code', 'postalCode_code'].includes(field)) {
|
||||
return { placeholder: '-', disabled: true }
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ function getFieldState(field: string) {
|
||||
}
|
||||
|
||||
// Jika isSame dan field location, disabled
|
||||
if (isSame && ['regency_code', 'district_code', 'village_code', 'postalCode'].includes(field)) {
|
||||
if (isSame && ['regency_code', 'district_code', 'village_code', 'postalCode_code'].includes(field)) {
|
||||
return { placeholder: '-', disabled: true }
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ watch(
|
||||
regency_code: undefined,
|
||||
district_code: undefined,
|
||||
village_code: undefined,
|
||||
postalCode: undefined,
|
||||
postalCode_code: undefined,
|
||||
},
|
||||
false,
|
||||
)
|
||||
@@ -133,7 +133,7 @@ watch(
|
||||
{
|
||||
district_code: undefined,
|
||||
village_code: undefined,
|
||||
postalCode: undefined,
|
||||
postalCode_code: undefined,
|
||||
},
|
||||
false,
|
||||
)
|
||||
@@ -157,7 +157,7 @@ watch(
|
||||
formRef.value.setValues(
|
||||
{
|
||||
village_code: undefined,
|
||||
postalCode: undefined,
|
||||
postalCode_code: undefined,
|
||||
},
|
||||
false,
|
||||
)
|
||||
@@ -180,7 +180,7 @@ watch(
|
||||
|
||||
formRef.value.setValues(
|
||||
{
|
||||
postalCode: undefined,
|
||||
postalCode_code: undefined,
|
||||
},
|
||||
false,
|
||||
)
|
||||
@@ -214,7 +214,7 @@ watch(
|
||||
if (updatedValues.regency_code === '') updatedValues.regency_code = undefined
|
||||
if (updatedValues.district_code === '') updatedValues.district_code = undefined
|
||||
if (updatedValues.village_code === '') updatedValues.village_code = undefined
|
||||
if (updatedValues.postalCode === '') updatedValues.postalCode = undefined
|
||||
if (updatedValues.postalCode_code === '') updatedValues.postalCode_code = undefined
|
||||
if (updatedValues.address === '') updatedValues.address = undefined
|
||||
|
||||
// Update values dan trigger validasi
|
||||
@@ -235,7 +235,7 @@ watch(
|
||||
formRef.value?.setFieldError('regency_code', undefined)
|
||||
formRef.value?.setFieldError('district_code', undefined)
|
||||
formRef.value?.setFieldError('village_code', undefined)
|
||||
formRef.value?.setFieldError('postalCode', undefined)
|
||||
formRef.value?.setFieldError('postalCode_code', undefined)
|
||||
formRef.value?.setFieldError('address', undefined)
|
||||
formRef.value?.setFieldError('rt', undefined)
|
||||
formRef.value?.setFieldError('rw', undefined)
|
||||
@@ -255,7 +255,7 @@ watch(
|
||||
:validation-schema="formSchema"
|
||||
:validate-on-mount="false"
|
||||
validation-mode="onSubmit"
|
||||
:initial-values="initialValues ?? { isSameAddress: '1' }"
|
||||
:initial-values="initialValues ?? { isSameAddress: '1', locationType: 'identity' }"
|
||||
>
|
||||
<div>
|
||||
<p
|
||||
@@ -267,34 +267,17 @@ watch(
|
||||
</div>
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-2">
|
||||
<!-- LocationType -->
|
||||
<FieldGroup v-if="conf?.withAddressName">
|
||||
<Label label-for="locationType">Jenis Alamat</Label>
|
||||
<Field
|
||||
id="locationType"
|
||||
:errors="errors"
|
||||
>
|
||||
<FormField
|
||||
v-slot="{ componentField }"
|
||||
name="locationType"
|
||||
>
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Select
|
||||
id="locationType"
|
||||
v-bind="componentField"
|
||||
:items="[
|
||||
{ label: 'Rumah', value: 'rumah' },
|
||||
{ label: 'Kantor', value: 'kantor' },
|
||||
{ label: 'Lainnya', value: 'lainnya' },
|
||||
]"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<!-- LocationType - Hidden field with default value 'identity' -->
|
||||
<FormField
|
||||
v-slot="{ componentField }"
|
||||
name="locationType"
|
||||
>
|
||||
<input
|
||||
type="hidden"
|
||||
v-bind="componentField"
|
||||
value="primary"
|
||||
/>
|
||||
</FormField>
|
||||
<FieldGroup class="radio-group-field">
|
||||
<Label
|
||||
size="fit"
|
||||
@@ -420,10 +403,10 @@ watch(
|
||||
|
||||
<div class="min-w-0 flex-[2]">
|
||||
<SelectPostal
|
||||
field-name="postalCode"
|
||||
field-name="postalCode_code"
|
||||
:village-code="values.village_code"
|
||||
:placeholder="getFieldState('postalCode').placeholder"
|
||||
:is-disabled="getFieldState('postalCode').disabled || !values.village_code"
|
||||
:placeholder="getFieldState('postalCode_code').placeholder"
|
||||
:is-disabled="getFieldState('postalCode_code').disabled || !values.village_code"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -160,7 +160,7 @@ watch(
|
||||
:validation-schema="formSchema"
|
||||
:validate-on-mount="false"
|
||||
validation-mode="onSubmit"
|
||||
:initial-values="initialValues ? initialValues : {}"
|
||||
:initial-values="initialValues ? { locationType: 'domicile', ...initialValues } : { locationType: 'domicile' }"
|
||||
>
|
||||
<div>
|
||||
<p
|
||||
@@ -172,34 +172,17 @@ watch(
|
||||
</div>
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-2">
|
||||
<!-- LocationType -->
|
||||
<FieldGroup v-if="conf?.withAddressName">
|
||||
<Label label-for="locationType">Jenis Alamat</Label>
|
||||
<Field
|
||||
id="locationType"
|
||||
:errors="errors"
|
||||
>
|
||||
<FormField
|
||||
v-slot="{ componentField }"
|
||||
name="locationType"
|
||||
>
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Select
|
||||
id="locationType"
|
||||
v-bind="componentField"
|
||||
:items="[
|
||||
{ label: 'Rumah', value: 'rumah' },
|
||||
{ label: 'Kantor', value: 'kantor' },
|
||||
{ label: 'Lainnya', value: 'lainnya' },
|
||||
]"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<!-- LocationType - Hidden field with default value 'domicile' -->
|
||||
<FormField
|
||||
v-slot="{ componentField }"
|
||||
name="locationType"
|
||||
>
|
||||
<input
|
||||
type="hidden"
|
||||
v-bind="componentField"
|
||||
value="resident"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<div class="flex-row gap-2 md:flex">
|
||||
<div class="min-w-0 flex-1">
|
||||
@@ -268,7 +251,7 @@ watch(
|
||||
|
||||
<div class="min-w-0 flex-[2]">
|
||||
<SelectPostal
|
||||
field-name="postalCode"
|
||||
field-name="postalCode_code"
|
||||
placeholder="Pilih kelurahan dahulu"
|
||||
:village-code="values.village_code"
|
||||
:is-disabled="!values.village_code"
|
||||
|
||||
@@ -50,7 +50,7 @@ onMounted(() => {
|
||||
regency_code: currentAddressValues.regency_code || undefined,
|
||||
district_code: currentAddressValues.district_code || undefined,
|
||||
village_code: currentAddressValues.village_code || undefined,
|
||||
postalCode: currentAddressValues.postalCode || undefined,
|
||||
postalCode_code: currentAddressValues.postalCode_code || undefined,
|
||||
address: currentAddressValues.address || undefined,
|
||||
rt: currentAddressValues.rt || undefined,
|
||||
rw: currentAddressValues.rw || undefined,
|
||||
@@ -141,7 +141,7 @@ watch(
|
||||
regency_code: currentAddressValues.regency_code || undefined,
|
||||
district_code: currentAddressValues.district_code || undefined,
|
||||
village_code: currentAddressValues.village_code || undefined,
|
||||
postalCode: currentAddressValues.postalCode || undefined,
|
||||
postalCode_code: currentAddressValues.postalCode_code || undefined,
|
||||
address: currentAddressValues.address || undefined,
|
||||
rt: currentAddressValues.rt || undefined,
|
||||
rw: currentAddressValues.rw || undefined,
|
||||
@@ -172,7 +172,7 @@ watch(
|
||||
regency_code: newAddressValues.regency_code || undefined,
|
||||
district_code: newAddressValues.district_code || undefined,
|
||||
village_code: newAddressValues.village_code || undefined,
|
||||
postalCode: newAddressValues.postalCode || undefined,
|
||||
postalCode_code: newAddressValues.postalCode_code || undefined,
|
||||
address: newAddressValues.address || undefined,
|
||||
rt: newAddressValues.rt || undefined,
|
||||
rw: newAddressValues.rw || undefined,
|
||||
@@ -202,7 +202,7 @@ watch(
|
||||
regency_code: currentAddressValues.regency_code || undefined,
|
||||
district_code: currentAddressValues.district_code || undefined,
|
||||
village_code: currentAddressValues.village_code || undefined,
|
||||
postalCode: currentAddressValues.postalCode || undefined,
|
||||
postalCode_code: currentAddressValues.postalCode_code || undefined,
|
||||
address: currentAddressValues.address || undefined,
|
||||
rt: currentAddressValues.rt || undefined,
|
||||
rw: currentAddressValues.rw || undefined,
|
||||
|
||||
Reference in New Issue
Block a user