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

No files matched your search

+15 -8
View File
@@ -58,7 +58,7 @@ const [nationalIdentity, nationalIdentityAttrs] = defineField('nationalIdentity'
const [medicalRecordNumber, medicalRecordNumberAttrs] = defineField('medicalRecordNumber') const [medicalRecordNumber, medicalRecordNumberAttrs] = defineField('medicalRecordNumber')
const patientId = ref('') 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 isReadonly = props.isReadonly !== undefined ? props.isReadonly : false
const doctorOpts = computed(() => { const doctorOpts = computed(() => {
@@ -87,11 +87,10 @@ watch(subSpecialistId, async (newValue) => {
}) })
// Sync props to form fields // Sync props to form fields
watch(props, (value) => { watch(
const patient = value.patient || ({} as PatientEntity) () => props.objects,
const objects = value.objects || ({} as any) (objects) => {
if (objects && Object.keys(objects).length > 0) {
if (Object.keys(objects).length > 0) {
patientName.value = objects?.patientName || '' patientName.value = objects?.patientName || ''
nationalIdentity.value = objects?.nationalIdentity || '' nationalIdentity.value = objects?.nationalIdentity || ''
medicalRecordNumber.value = objects?.medicalRecordNumber || '' medicalRecordNumber.value = objects?.medicalRecordNumber || ''
@@ -104,14 +103,22 @@ watch(props, (value) => {
sepType.value = objects?.sepType || '' sepType.value = objects?.sepType || ''
sepNumber.value = objects?.sepNumber || '' sepNumber.value = objects?.sepNumber || ''
} }
},
{ deep: true, immediate: true },
)
if (Object.keys(patient).length > 0) { watch(
() => props.patient,
(patient) => {
if (patient && Object.keys(patient).length > 0) {
patientId.value = patient?.id ? String(patient.id) : '' patientId.value = patient?.id ? String(patient.id) : ''
patientName.value = patient?.person?.name || '' patientName.value = patient?.person?.name || ''
nationalIdentity.value = patient?.person?.residentIdentityNumber || '' nationalIdentity.value = patient?.person?.residentIdentityNumber || ''
medicalRecordNumber.value = patient?.number || '' medicalRecordNumber.value = patient?.number || ''
} }
}) },
{ deep: true, immediate: true },
)
function onAddSep() { function onAddSep() {
const formValues = { const formValues = {
+117 -43
View File
@@ -246,7 +246,7 @@ async function handleEvent(menu: string, value?: any) {
} else if (menu === 'save') { } else if (menu === 'save') {
await handleSaveEncounter(value) await handleSaveEncounter(value)
} else if (menu === 'cancel') { } else if (menu === 'cancel') {
console.log('Cancel') navigateTo(getListPath())
} }
} }
@@ -286,6 +286,62 @@ function isSubspecialist(value: string, items: TreeItem[]): boolean {
return false 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) * Helper function to find specialist_id and subspecialist_id from TreeSelect value (code)
* Returns { specialist_id: number | null, subspecialist_id: number | null } * Returns { specialist_id: number | null, subspecialist_id: number | null }
@@ -364,6 +420,7 @@ function handleFetch(value?: any) {
} }
async function handleInit() { async function handleInit() {
selectedPatientObject.value = null
paymentsList.value = Object.keys(paymentTypes).map((item) => ({ paymentsList.value = Object.keys(paymentTypes).map((item) => ({
value: item.toString(), value: item.toString(),
label: paymentTypes[item], label: paymentTypes[item],
@@ -391,13 +448,15 @@ async function loadEncounterDetail() {
try { try {
isLoadingDetail.value = true isLoadingDetail.value = true
// Include patient, person, specialist, and subspecialist in the response
const result = await getEncounterDetail(props.id, { 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) { if (result.success && result.body?.data) {
encounterData.value = result.body.data encounterData.value = result.body.data
await mapEncounterToForm(encounterData.value) await mapEncounterToForm(encounterData.value)
// Set loading to false after mapping is complete
isLoadingDetail.value = false
} else { } else {
toast({ toast({
title: 'Gagal', title: 'Gagal',
@@ -427,28 +486,30 @@ async function loadEncounterDetail() {
async function mapEncounterToForm(encounter: any) { async function mapEncounterToForm(encounter: any) {
if (!encounter) return if (!encounter) return
// Set patient data and wait for it to load // Set patient data - use data from response if available
if (encounter.patient) { if (encounter.patient) {
selectedPatient.value = String(encounter.patient.id) selectedPatient.value = String(encounter.patient.id)
selectedPatientObject.value = encounter.patient selectedPatientObject.value = encounter.patient
// Fetch full patient data to ensure we have all fields // Only fetch patient if person data is missing
if (!encounter.patient.person) {
await getPatientCurrent(selectedPatient.value) await getPatientCurrent(selectedPatient.value)
} }
}
// Map form fields // Map form fields
const formData: any = {} const formData: any = {}
// Patient data (readonly, populated from selected patient) // Patient data (readonly, populated from selected patient)
// Use selectedPatientObject which now has full patient data // Use encounter.patient.person which is already in the response
if (selectedPatientObject.value?.person) { if (encounter.patient?.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
formData.patientName = encounter.patient.person.name || '' formData.patientName = encounter.patient.person.name || ''
formData.nationalIdentity = encounter.patient.person.residentIdentityNumber || '' formData.nationalIdentity = encounter.patient.person.residentIdentityNumber || ''
formData.medicalRecordNumber = encounter.patient.number || '' 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 // Doctor ID
@@ -457,12 +518,28 @@ async function mapEncounterToForm(encounter: any) {
formData.doctorId = String(doctorId) formData.doctorId = String(doctorId)
} }
// Specialist/Subspecialist // 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) { if (encounter.subspecialist?.code) {
formData.subSpecialistId = encounter.subspecialist.code formData.subSpecialistId = encounter.subspecialist.code
} else if (encounter.specialist?.code) { } else if (encounter.specialist?.code) {
formData.subSpecialistId = encounter.specialist.code formData.subSpecialistId = encounter.specialist.code
} }
}
// Register date // Register date
if (encounter.registeredAt) { if (encounter.registeredAt) {
@@ -474,37 +551,34 @@ async function mapEncounterToForm(encounter: any) {
formData.registerDate = date.toISOString().split('T')[0] formData.registerDate = date.toISOString().split('T')[0]
} }
// Payment data // Payment data - use fields directly from encounter
// Check if encounter has payment data // Map paymentMethod_code to paymentType
if (encounter.encounter_payments && Array.isArray(encounter.encounter_payments) && encounter.encounter_payments.length > 0) { if (encounter.paymentMethod_code) {
const payment = encounter.encounter_payments[0] // 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 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 {
// If paymentMethod_code is empty or null, default to 'spm'
formData.paymentType = 'spm'
}
// Determine payment type from paymentMethod_code // Map payment fields directly from encounter
if (payment.paymentMethod_code === 'insurance') { formData.cardNumber = encounter.member_number || ''
// Check if it's JKN or JKMM based on member_number or other indicators formData.sepNumber = encounter.ref_number || ''
// For now, default to 'jkn' - this might need adjustment based on actual data structure
formData.paymentType = 'jkn' // Note: patientCategory and sepType might not be available in the response
formData.cardNumber = payment.member_number || '' // These fields might need to be set manually or fetched from other sources
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
} 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
}
} 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
}
}
// Set form objects for the form component // Set form objects for the form component
formObjects.value = formData formObjects.value = formData