refactor(patient): restructure patient data handling to use nested properties

Move address, contact and relative data into nested properties of Person model
Update preview component to access data through person object
Remove separate props for addresses, contacts and relatives
This commit is contained in:
Khafid Prayoga
2025-10-10 10:30:00 +07:00
parent bd4a269fad
commit a5d5e8acd1
3 changed files with 40 additions and 17 deletions
+32 -12
View File
@@ -7,15 +7,19 @@ 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 { educationCodes, genderCodes, occupationCodes, personContactTypes, relationshipCodes, religionCodes } from '~/lib/constants'
import {
educationCodes,
genderCodes,
occupationCodes,
personContactTypes,
relationshipCodes,
religionCodes,
} from '~/lib/constants'
import { mapToComboboxOptList } from '~/lib/utils'
// #region Props & Emits
const props = defineProps<{
person: Person
personAddresses: PersonAddress[]
personContacts: PersonContact[]
personRelatives: PersonRelative[]
}>()
const emit = defineEmits<{
@@ -32,8 +36,18 @@ const occupationOptions = mapToComboboxOptList(occupationCodes)
const relationshipOptions = mapToComboboxOptList(relationshipCodes)
const personContactTypeOptions = mapToComboboxOptList(personContactTypes)
const residentAddress = 'Jl. Puncak Borobudur Blok M No. 321, Lowokwaru, Kota Malang, Jawa Timur'
const primaryAddress = 'Perumahan Araya Cluster B, No 22, Blimbing, Kota Malang, Jawa Timur'
// Computed addresses from nested data
const residentAddress = 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 primaryAddress = 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 patientAge = computed(() => {
if (!props.person.birthDate) {
@@ -96,7 +110,9 @@ function onClick(type: string) {
{{ educationOptions.find((item) => item.code === person.education_code)?.label || '-' }}
</DetailRow>
<DetailRow label="Pekerjaan">
{{ occupationOptions.find((item) => item.code === person.occupation_code)?.label || person.occupation_name || '-' }}
{{
occupationOptions.find((item) => item.code === person.occupation_code)?.label || person.occupation_name || '-'
}}
</DetailRow>
</DetailSection>
@@ -105,13 +121,13 @@ function onClick(type: string) {
<DetailRow label="Alamat KTP">{{ primaryAddress || '-' }}</DetailRow>
</DetailSection>
<DetailSection title="Kontak">
<template v-if="personContacts && personContacts.length > 0">
<template v-if="person.contacts && person.contacts.length > 0">
<template
v-for="contactType in personContactTypeOptions"
:key="contactType.code"
>
<DetailRow :label="contactType.label">
{{ personContacts.find((item) => item.type_code === contactType.code)?.value || '-' }}
{{ person.contacts.find((item) => item.type_code === contactType.code)?.value || '-' }}
</DetailRow>
</template>
</template>
@@ -120,9 +136,9 @@ function onClick(type: string) {
</template>
</DetailSection>
<DetailSection title="Penanggung Jawab">
<template v-if="personRelatives && personRelatives.filter((rel) => rel.responsible).length > 0">
<template v-if="person.relatives && person.relatives.filter((rel) => rel.responsible).length > 0">
<template
v-for="(relative, index) in personRelatives.filter((rel) => rel.responsible)"
v-for="(relative, index) in person.relatives.filter((rel) => rel.responsible)"
:key="relative.id"
>
<div
@@ -140,7 +156,11 @@ function onClick(type: string) {
{{ educationOptions.find((item) => item.code === relative.education_code)?.label || '-' }}
</DetailRow>
<DetailRow label="Pekerjaan">
{{ occupationOptions.find((item) => item.code === relative.occupation_code)?.label || relative.occupation_name || '-' }}
{{
occupationOptions.find((item) => item.code === relative.occupation_code)?.label ||
relative.occupation_name ||
'-'
}}
</DetailRow>
<DetailRow label="Alamat">{{ relative.address || '-' }}</DetailRow>
<DetailRow label="Nomor HP">{{ relative.phoneNumber || '-' }}</DetailRow>
@@ -75,9 +75,6 @@ function handleAction(type: string) {
/>
<AppPatientPreview
:person="patient.person"
:person-addresses="patient.personAddresses"
:person-contacts="patient.personContacts"
:person-relatives="patient.personRelatives"
@click="handleAction"
/>
</template>
+8 -2
View File
@@ -1,8 +1,9 @@
import { type Base, genBase } from './_base'
import type { PersonAddress } from './person-address'
import type { PersonContact } from './person-contact'
import type { PersonRelative } from './person-relative'
export interface Person extends Base {
// todo: awaiting approve from stake holder: buat field sapaan
// todo: adjust field ketika person Balita
name: string
// alias?: string
frontTitle?: string
@@ -26,6 +27,11 @@ export interface Person extends Base {
passportFileUrl?: string
drivingLicenseFileUrl?: string
familyIdentityFileUrl?: string
// preload data for detail patient
addresses?: PersonAddress[] | null
contacts?: PersonContact[] | null
relatives?: PersonRelative[] | null
}
export function genPerson(): Person {