refactor(encounter): improve form field synchronization and enhance loading state management

This commit is contained in:
riefive
2025-11-10 13:23:03 +07:00
parent b52f438b23
commit 6c542e5a54
2 changed files with 151 additions and 70 deletions
+32 -25
View File
@@ -58,7 +58,7 @@ const [nationalIdentity, nationalIdentityAttrs] = defineField('nationalIdentity'
const [medicalRecordNumber, medicalRecordNumberAttrs] = defineField('medicalRecordNumber')
const patientId = ref('')
const mode = props.isLoading !== undefined ? props.isLoading : false
const isLoading = props.isLoading !== undefined ? props.isLoading : false
const isReadonly = props.isReadonly !== undefined ? props.isReadonly : false
const doctorOpts = computed(() => {
@@ -87,31 +87,38 @@ watch(subSpecialistId, async (newValue) => {
})
// Sync props to form fields
watch(props, (value) => {
const patient = value.patient || ({} as PatientEntity)
const objects = value.objects || ({} as any)
watch(
() => props.objects,
(objects) => {
if (objects && Object.keys(objects).length > 0) {
patientName.value = objects?.patientName || ''
nationalIdentity.value = objects?.nationalIdentity || ''
medicalRecordNumber.value = objects?.medicalRecordNumber || ''
doctorId.value = objects?.doctorId || ''
subSpecialistId.value = objects?.subSpecialistId || ''
registerDate.value = objects?.registerDate || ''
paymentType.value = objects?.paymentType || ''
patientCategory.value = objects?.patientCategory || ''
cardNumber.value = objects?.cardNumber || ''
sepType.value = objects?.sepType || ''
sepNumber.value = objects?.sepNumber || ''
}
},
{ deep: true, immediate: true },
)
if (Object.keys(objects).length > 0) {
patientName.value = objects?.patientName || ''
nationalIdentity.value = objects?.nationalIdentity || ''
medicalRecordNumber.value = objects?.medicalRecordNumber || ''
doctorId.value = objects?.doctorId || ''
subSpecialistId.value = objects?.subSpecialistId || ''
registerDate.value = objects?.registerDate || ''
paymentType.value = objects?.paymentType || ''
patientCategory.value = objects?.patientCategory || ''
cardNumber.value = objects?.cardNumber || ''
sepType.value = objects?.sepType || ''
sepNumber.value = objects?.sepNumber || ''
}
if (Object.keys(patient).length > 0) {
patientId.value = patient?.id ? String(patient.id) : ''
patientName.value = patient?.person?.name || ''
nationalIdentity.value = patient?.person?.residentIdentityNumber || ''
medicalRecordNumber.value = patient?.number || ''
}
})
watch(
() => props.patient,
(patient) => {
if (patient && Object.keys(patient).length > 0) {
patientId.value = patient?.id ? String(patient.id) : ''
patientName.value = patient?.person?.name || ''
nationalIdentity.value = patient?.person?.residentIdentityNumber || ''
medicalRecordNumber.value = patient?.number || ''
}
},
{ deep: true, immediate: true },
)
function onAddSep() {
const formValues = {
+119 -45
View File
@@ -246,7 +246,7 @@ async function handleEvent(menu: string, value?: any) {
} else if (menu === 'save') {
await handleSaveEncounter(value)
} else if (menu === 'cancel') {
console.log('Cancel')
navigateTo(getListPath())
}
}
@@ -286,6 +286,62 @@ function isSubspecialist(value: string, items: TreeItem[]): boolean {
return false
}
/**
* Helper function to get specialist/subspecialist code from ID
* Returns code string or null if not found
*/
function getSpecialistCodeFromId(id: number | null | undefined): string | null {
if (!id) return null
// First check if encounter has specialist object with code
if (encounterData.value?.specialist?.id === id) {
return encounterData.value.specialist.code || null
}
// Search in specialistsData
for (const specialist of specialistsData.value) {
if (specialist.id === id) {
return specialist.code || null
}
// Check subspecialists
if (specialist.subspecialists && Array.isArray(specialist.subspecialists)) {
for (const subspecialist of specialist.subspecialists) {
if (subspecialist.id === id) {
return subspecialist.code || null
}
}
}
}
return null
}
/**
* Helper function to get subspecialist code from ID
* Returns code string or null if not found
*/
function getSubspecialistCodeFromId(id: number | null | undefined): string | null {
if (!id) return null
// First check if encounter has subspecialist object with code
if (encounterData.value?.subspecialist?.id === id) {
return encounterData.value.subspecialist.code || null
}
// Search in specialistsData
for (const specialist of specialistsData.value) {
if (specialist.subspecialists && Array.isArray(specialist.subspecialists)) {
for (const subspecialist of specialist.subspecialists) {
if (subspecialist.id === id) {
return subspecialist.code || null
}
}
}
}
return null
}
/**
* Helper function to find specialist_id and subspecialist_id from TreeSelect value (code)
* Returns { specialist_id: number | null, subspecialist_id: number | null }
@@ -364,6 +420,7 @@ function handleFetch(value?: any) {
}
async function handleInit() {
selectedPatientObject.value = null
paymentsList.value = Object.keys(paymentTypes).map((item) => ({
value: item.toString(),
label: paymentTypes[item],
@@ -391,13 +448,15 @@ async function loadEncounterDetail() {
try {
isLoadingDetail.value = true
// Include patient, person, specialist, and subspecialist in the response
const result = await getEncounterDetail(props.id, {
includes: 'patient,patient-person,specialist,subspecialist,appointment_doctor,responsible_doctor,encounter_payments',
includes: 'patient,patient-person,specialist,subspecialist',
})
if (result.success && result.body?.data) {
encounterData.value = result.body.data
await mapEncounterToForm(encounterData.value)
// Set loading to false after mapping is complete
isLoadingDetail.value = false
} else {
toast({
title: 'Gagal',
@@ -427,28 +486,30 @@ async function loadEncounterDetail() {
async function mapEncounterToForm(encounter: any) {
if (!encounter) return
// Set patient data and wait for it to load
// Set patient data - use data from response if available
if (encounter.patient) {
selectedPatient.value = String(encounter.patient.id)
selectedPatientObject.value = encounter.patient
// Fetch full patient data to ensure we have all fields
await getPatientCurrent(selectedPatient.value)
// Only fetch patient if person data is missing
if (!encounter.patient.person) {
await getPatientCurrent(selectedPatient.value)
}
}
// Map form fields
const formData: any = {}
// Patient data (readonly, populated from selected patient)
// Use selectedPatientObject which now has full patient data
if (selectedPatientObject.value?.person) {
formData.patientName = selectedPatientObject.value.person.name || ''
formData.nationalIdentity = selectedPatientObject.value.person.residentIdentityNumber || ''
formData.medicalRecordNumber = selectedPatientObject.value.number || ''
} else if (encounter.patient?.person) {
// Fallback to encounter patient data if selectedPatientObject is not yet loaded
// Use encounter.patient.person which is already in the response
if (encounter.patient?.person) {
formData.patientName = encounter.patient.person.name || ''
formData.nationalIdentity = encounter.patient.person.residentIdentityNumber || ''
formData.medicalRecordNumber = encounter.patient.number || ''
} else if (selectedPatientObject.value?.person) {
// Fallback to selectedPatientObject if encounter.patient.person is not available
formData.patientName = selectedPatientObject.value.person.name || ''
formData.nationalIdentity = selectedPatientObject.value.person.residentIdentityNumber || ''
formData.medicalRecordNumber = selectedPatientObject.value.number || ''
}
// Doctor ID
@@ -457,11 +518,27 @@ async function mapEncounterToForm(encounter: any) {
formData.doctorId = String(doctorId)
}
// Specialist/Subspecialist
if (encounter.subspecialist?.code) {
formData.subSpecialistId = encounter.subspecialist.code
} else if (encounter.specialist?.code) {
formData.subSpecialistId = encounter.specialist.code
// Specialist/Subspecialist - use helper function to get code from ID
// Priority: subspecialist_id > specialist_id
if (encounter.subspecialist_id) {
const subspecialistCode = getSubspecialistCodeFromId(encounter.subspecialist_id)
if (subspecialistCode) {
formData.subSpecialistId = subspecialistCode
}
} else if (encounter.specialist_id) {
const specialistCode = getSpecialistCodeFromId(encounter.specialist_id)
if (specialistCode) {
formData.subSpecialistId = specialistCode
}
}
// Fallback: if encounter has specialist/subspecialist object with code
if (!formData.subSpecialistId) {
if (encounter.subspecialist?.code) {
formData.subSpecialistId = encounter.subspecialist.code
} else if (encounter.specialist?.code) {
formData.subSpecialistId = encounter.specialist.code
}
}
// Register date
@@ -474,38 +551,35 @@ async function mapEncounterToForm(encounter: any) {
formData.registerDate = date.toISOString().split('T')[0]
}
// Payment data
// Check if encounter has payment data
if (encounter.encounter_payments && Array.isArray(encounter.encounter_payments) && encounter.encounter_payments.length > 0) {
const payment = encounter.encounter_payments[0]
// Determine payment type from paymentMethod_code
if (payment.paymentMethod_code === 'insurance') {
// Check if it's JKN or JKMM based on member_number or other indicators
// For now, default to 'jkn' - this might need adjustment based on actual data structure
formData.paymentType = 'jkn'
formData.cardNumber = payment.member_number || ''
formData.sepNumber = payment.ref_number || ''
// Note: patientCategory and sepType might need to be extracted from other sources
// as they might not be directly in the payment object
// Payment data - use fields directly from encounter
// Map paymentMethod_code to paymentType
if (encounter.paymentMethod_code) {
// Map paymentMethod_code to paymentType
// 'insurance' typically means JKN/JKMM
if (encounter.paymentMethod_code === 'insurance') {
formData.paymentType = 'jkn' // Default to JKN for insurance
} else {
// For non-insurance payments, try to determine from encounter data
// This might need adjustment based on actual API response
formData.paymentType = 'spm' // default to SPM
// For other payment methods, use the code directly if it matches
// Otherwise default to 'spm'
const validPaymentTypes = ['jkn', 'jkmm', 'spm', 'pks']
if (validPaymentTypes.includes(encounter.paymentMethod_code)) {
formData.paymentType = encounter.paymentMethod_code
} else {
formData.paymentType = 'spm' // Default to SPM
}
}
} else {
// Fallback: try to get payment type from encounter.paymentType if available
if (encounter.paymentType) {
formData.paymentType = encounter.paymentType
}
if (encounter.cardNumber) {
formData.cardNumber = encounter.cardNumber
}
if (encounter.ref_number || encounter.sepNumber) {
formData.sepNumber = encounter.ref_number || encounter.sepNumber
}
// If paymentMethod_code is empty or null, default to 'spm'
formData.paymentType = 'spm'
}
// Map payment fields directly from encounter
formData.cardNumber = encounter.member_number || ''
formData.sepNumber = encounter.ref_number || ''
// Note: patientCategory and sepType might not be available in the response
// These fields might need to be set manually or fetched from other sources
// Set form objects for the form component
formObjects.value = formData