Files
simrsx-fe/app/components/app/patient/preview.vue
T
Khafid Prayoga ea04f33ad1 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
2025-10-10 15:36:54 +07:00

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>