ea04f33ad1
- 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
177 lines
6.1 KiB
Vue
177 lines
6.1 KiB
Vue
<script setup lang="ts">
|
|
import type { Person } from '~/models/person'
|
|
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,
|
|
personContactTypes,
|
|
relationshipCodes,
|
|
religionCodes,
|
|
} from '~/lib/constants'
|
|
import { mapToComboboxOptList } from '~/lib/utils'
|
|
|
|
// #region Props & Emits
|
|
const props = defineProps<{
|
|
person: Person
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'click', type: string): void
|
|
}>()
|
|
|
|
// #endregion
|
|
|
|
// #region State & Computed
|
|
const genderOptions = mapToComboboxOptList(genderCodes)
|
|
const religionOptions = mapToComboboxOptList(religionCodes)
|
|
const educationOptions = mapToComboboxOptList(educationCodes)
|
|
const occupationOptions = mapToComboboxOptList(occupationCodes)
|
|
const relationshipOptions = mapToComboboxOptList(relationshipCodes)
|
|
const personContactTypeOptions = mapToComboboxOptList(personContactTypes)
|
|
|
|
// Computed addresses from nested data
|
|
const domicileAddress = computed(() => {
|
|
const addresses = props.person.addresses
|
|
const resident = addresses?.find((addr) => addr.locationType === 'domicile')
|
|
return formatAddress(resident)
|
|
})
|
|
|
|
const identityAddress = computed(() => {
|
|
const addresses = props.person.addresses
|
|
const primary = addresses?.find((addr) => addr.locationType === 'identity')
|
|
return formatAddress(primary)
|
|
})
|
|
|
|
const patientAge = computed(() => {
|
|
if (!props.person.birthDate) {
|
|
return '-'
|
|
}
|
|
const birthDate = new Date(props.person.birthDate)
|
|
const today = new Date()
|
|
let age = today.getFullYear() - birthDate.getFullYear()
|
|
const monthDiff = today.getMonth() - birthDate.getMonth()
|
|
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
|
|
age--
|
|
}
|
|
return age
|
|
})
|
|
// #endregion
|
|
|
|
// #region Lifecycle Hooks
|
|
// #endregion
|
|
|
|
// #region Functions
|
|
|
|
// #endregion region
|
|
|
|
// #region Utilities & event handlers
|
|
function onClick(type: string) {
|
|
emit('click', type)
|
|
}
|
|
// #endregion
|
|
|
|
// #region Watchers
|
|
// #endregion
|
|
</script>
|
|
|
|
<template>
|
|
<DetailSection title="Data Pasien">
|
|
<DetailRow label="Nomor ID">{{ person.id || '-' }}</DetailRow>
|
|
<DetailRow label="Nama Lengkap">{{ person.name || '-' }}</DetailRow>
|
|
<DetailRow label="Tempat, tanggal lahir">
|
|
{{ person.birthRegency?.name || '-' }},
|
|
{{ person.birthDate ? new Date(person.birthDate).toLocaleDateString() : '-' }}
|
|
</DetailRow>
|
|
<DetailRow label="Usia">{{ patientAge || '-' }}</DetailRow>
|
|
<DetailRow label="Tanggal Daftar">
|
|
{{ person.createdAt ? new Date(person.createdAt).toLocaleDateString() : '-' }}
|
|
</DetailRow>
|
|
<DetailRow label="Jenis Kelamin">
|
|
{{ genderOptions.find((item) => item.code === person.gender_code)?.label || '-' }}
|
|
</DetailRow>
|
|
|
|
<DetailRow label="NIK">{{ person.residentIdentityNumber || '-' }}</DetailRow>
|
|
<DetailRow label="No. SIM">{{ person.drivingLicenseNumber || '-' }}</DetailRow>
|
|
<DetailRow label="No. Paspor">{{ person.passportNumber || '-' }}</DetailRow>
|
|
|
|
<DetailRow label="Agama">
|
|
{{ religionOptions.find((item) => item.code === person.religion_code)?.label || '-' }}
|
|
</DetailRow>
|
|
<DetailRow label="Suku">{{ person.ethnic_code || '-' }}</DetailRow>
|
|
<DetailRow label="Bahasa">{{ person.language_code || '-' }}</DetailRow>
|
|
<DetailRow label="Pendidikan">
|
|
{{ 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 || '-'
|
|
}}
|
|
</DetailRow>
|
|
</DetailSection>
|
|
|
|
<DetailSection title="Alamat">
|
|
<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">
|
|
<template
|
|
v-for="contactType in personContactTypeOptions"
|
|
:key="contactType.code"
|
|
>
|
|
<DetailRow :label="contactType.label">
|
|
{{ person.contacts.find((item) => item.type_code === contactType.code)?.value || '-' }}
|
|
</DetailRow>
|
|
</template>
|
|
</template>
|
|
<template v-else>
|
|
<DetailRow label="Kontak">-</DetailRow>
|
|
</template>
|
|
</DetailSection>
|
|
<DetailSection title="Penanggung Jawab">
|
|
<template v-if="person.relatives && person.relatives.filter((rel) => rel.responsible).length > 0">
|
|
<template
|
|
v-for="(relative, index) in person.relatives.filter((rel) => rel.responsible)"
|
|
:key="relative.id"
|
|
>
|
|
<div
|
|
v-if="index > 0"
|
|
class="mt-3 border-t border-gray-200 pt-3"
|
|
></div>
|
|
<DetailRow label="Nama">{{ relative.name || '-' }}</DetailRow>
|
|
<DetailRow label="Hubungan">
|
|
{{ relationshipOptions.find((item) => item.code === relative.relationship_code)?.label || '-' }}
|
|
</DetailRow>
|
|
<DetailRow label="Jenis Kelamin">
|
|
{{ genderOptions.find((item) => item.code === relative.gender_code)?.label || '-' }}
|
|
</DetailRow>
|
|
<DetailRow label="Pendidikan">
|
|
{{ 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 ||
|
|
'-'
|
|
}}
|
|
</DetailRow>
|
|
<DetailRow label="Alamat">{{ relative.address || '-' }}</DetailRow>
|
|
<DetailRow label="Nomor HP">{{ relative.phoneNumber || '-' }}</DetailRow>
|
|
</template>
|
|
</template>
|
|
<template v-else>
|
|
<DetailRow label="Penanggung Jawab">-</DetailRow>
|
|
</template>
|
|
</DetailSection>
|
|
<div class="border-t-1 my-2 flex justify-end border-t-slate-300 py-2">
|
|
<PubMyUiNavFooterBaEd @click="onClick" />
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped></style>
|