diff --git a/app/components/app/encounter/entry-form.vue b/app/components/app/encounter/entry-form.vue index e3c819eb..29a75302 100644 --- a/app/components/app/encounter/entry-form.vue +++ b/app/components/app/encounter/entry-form.vue @@ -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 = { diff --git a/app/components/content/encounter/entry.vue b/app/components/content/encounter/entry.vue index a1919b0b..580031d9 100644 --- a/app/components/content/encounter/entry.vue +++ b/app/components/content/encounter/entry.vue @@ -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