diff --git a/app/components/content/encounter/process-next.vue b/app/components/content/encounter/process-next.vue index e3dffe98..df0219bd 100644 --- a/app/components/content/encounter/process-next.vue +++ b/app/components/content/encounter/process-next.vue @@ -11,26 +11,11 @@ import SubMenu from '~/components/pub/my-ui/menus/submenu.vue' import { getPositionAs } from '~/lib/roles' // Types -import type { EncounterProps } from '~/handlers/encounter-process.handler' - -// Services -import { getDetail } from '~/services/encounter.service' +import type { EncounterProps } from '~/handlers/encounter-init.handler' // Handlers -import { getIndexById, listItems, mapResponseToEncounter } from '~/handlers/encounter-process.handler' - -const StatusAsync = defineAsyncComponent(() => import('~/components/content/encounter/status.vue')) -const AssesmentFunctionListAsync = defineAsyncComponent(() => import('~/components/content/soapi/entry.vue')) -const EarlyMedicalAssesmentListAsync = defineAsyncComponent(() => import('~/components/content/soapi/entry.vue')) -const EarlyMedicalRehabListAsync = defineAsyncComponent(() => import('~/components/content/soapi/entry.vue')) -const PrescriptionAsync = defineAsyncComponent(() => import('~/components/content/prescription/main.vue')) -// const PrescriptionListAsync = defineAsyncComponent(() => import('~/components/content/prescription/list.vue')) -const CpLabOrderAsync = defineAsyncComponent(() => import('~/components/content/cp-lab-order/main.vue')) -const RadiologyAsync = defineAsyncComponent(() => import('~/components/content/radiology-order/main.vue')) -const ConsultationAsync = defineAsyncComponent(() => import('~/components/content/consultation/list.vue')) -const ControlLetterListAsync = defineAsyncComponent(() => import('~/components/content/control-letter/list.vue')) -const ProtocolListAsync = defineAsyncComponent(() => import('~/components/app/chemotherapy/list.protocol.vue')) -const MedicineProtocolListAsync = defineAsyncComponent(() => import('~/components/app/chemotherapy/list.medicine.vue')) +import { getEncounterData } from '~/handlers/encounter-process.handler' +import { getMenuItems } from "~/handlers/encounter-init.handler" const { user, getActiveRole } = useUserStore() const route = useRoute() @@ -88,196 +73,43 @@ const paginationMeta = { hasPrev: false, } -async function getData() { - try { - const dataRes = await getDetail(id, { - includes: - 'patient,patient-person,patient-person-addresses,unit,Appointment_Doctor,Appointment_Doctor-employee,Appointment_Doctor-employee-person,Responsible_Doctor,Responsible_Doctor-employee,Responsible_Doctor-employee-person', - }) - const dataResBody = dataRes.body ?? null - const result = dataResBody?.data ?? null - - if (result) { - const mappedData = mapResponseToEncounter(result) - if (mappedData) { - data.value = mappedData - } else { - data.value = null - } - } else { - data.value = null - } - } catch (error) { - console.error('Error fetching encounter data:', error) - data.value = null - } -} - -function getMenus() { - const normalClassCode = props.classCode === 'ambulatory' ? 'outpatient' : props.classCode - const currentListItems = listItems[`installation|${normalClassCode}`]; - if (!currentListItems) return [] - const unitCode = user?.unit?.code ? `unit|${user.unit.code}` : 'all'; - const currentUnitItems: any = currentListItems[`${unitCode}`]; - if (!currentUnitItems) return [] - let menus = [] - if (currentUnitItems.roles && currentUnitItems.roles?.some((role: string) => role === activePosition.value)) { - menus = [...currentUnitItems.items] - } else { - menus = [...currentUnitItems] - } - const indexStatus = getIndexById('status', menus) - const indexEarlyMedicalAssessment = getIndexById('early-medical-assessment', menus) - const indexRehabMedicalAssessment = getIndexById('rehab-medical-assessment', menus) - const indexFunctionAssessment = getIndexById('function-assessment', menus) - const indexTherapyProtocol = getIndexById('therapy-protocol', menus) - const indexChemotherapyProtocol = getIndexById('chemotherapy-protocol', menus) - const indexChemotherapyMedicine = getIndexById('chemotherapy-medicine', menus) - const indexPrescription = getIndexById('prescription', menus) - const indexDevice = getIndexById('device', menus) - const indexMcuRadiology = getIndexById('mcu-radiology', menus) - const indexMcuLabPc = getIndexById('mcu-lab-pc', menus) - const indexMcuLabMicro = getIndexById('mcu-lab-micro', menus) - const indexMcuLabPa = getIndexById('mcu-lab-pa', menus) - const indexMedicalAction = getIndexById('medical-action', menus) - const indexMcuResult = getIndexById('mcu-result', menus) - const indexConsultation = getIndexById('consultation', menus) - const indexResume = getIndexById('resume', menus) - const indexControlLetter = getIndexById('control', menus) - const indexScreening = getIndexById('screening', menus) - const indexSupportingDocument = getIndexById('supporting-document', menus) - const indexPriceList = getIndexById('price-list', menus) - - if (indexStatus > -1) { - menus.splice(indexStatus, 1, { - ...menus[indexStatus], - component: StatusAsync, - props: { encounter: data }, - }) - } - if (indexEarlyMedicalAssessment > -1) { - menus.splice(indexEarlyMedicalAssessment, 1, { - ...menus[indexEarlyMedicalAssessment], - component: EarlyMedicalAssesmentListAsync, - props: { encounter: data, type: 'early-medic', label: 'Pengkajian Awal Medis' }, - }) - } - if (indexRehabMedicalAssessment > -1) { - menus.splice(indexRehabMedicalAssessment, 1, { - ...menus[indexRehabMedicalAssessment], - component: EarlyMedicalRehabListAsync, - props: { encounter: data, type: 'early-rehab', label: 'Pengkajian Awal Medis Rehabilitasi Medis' }, - }) - } - if (indexFunctionAssessment > -1) { - menus.splice(indexFunctionAssessment, 1, { - ...menus[indexFunctionAssessment], - component: AssesmentFunctionListAsync, - props: { encounter: data, type: 'function', label: 'Asesmen Fungsi' }, - }) - } - if (indexTherapyProtocol > -1) { - menus.splice(indexTherapyProtocol, 1, { - ...menus[indexTherapyProtocol], - component: ProtocolListAsync, - props: { data: protocolRows, paginationMeta }, - }) - } - if (indexChemotherapyProtocol > -1) { - menus.splice(indexChemotherapyProtocol, 1, { - ...menus[indexChemotherapyProtocol], - component: ProtocolListAsync, - props: { data: protocolRows, paginationMeta }, - }) - } - if (indexChemotherapyMedicine > -1) { - menus.splice(indexChemotherapyMedicine, 1, { - ...menus[indexChemotherapyMedicine], - component: MedicineProtocolListAsync, - props: { data: protocolRows, paginationMeta }, - }) - } - if (indexPrescription > -1) { - menus.splice(indexPrescription, 1, { - ...menus[indexPrescription], - component: PrescriptionAsync, - props: { encounter_id: id } - }) - } - if (indexDevice > -1) { - menus.splice(indexDevice, 1, { ...menus[indexDevice], component: null }) - } - if (indexMcuRadiology > -1) { - menus.splice(indexMcuRadiology, 1, { - ...menus[indexMcuRadiology], - component: RadiologyAsync, - props: { encounter_id: id } - }) - } - if (indexMcuLabPc > -1) { - menus.splice(indexMcuLabPc, 1, { - ...menus[indexMcuLabPc], - component: CpLabOrderAsync, - props: { encounter_id: id } - }) - } - if (indexMcuLabMicro > -1) { - menus.splice(indexMcuLabMicro, 1, { ...menus[indexMcuLabMicro], component: null }) - } - if (indexMcuLabPa > -1) { - menus.splice(indexMcuLabPa, 1, { ...menus[indexMcuLabPa], component: null }) - } - if (indexMedicalAction > -1) { - menus.splice(indexMcuLabPa, 1, { ...menus[indexMcuLabPa], component: null }) - } - if (indexConsultation > -1) { - menus.splice(indexConsultation, 1, { - ...menus[indexConsultation], - component: ConsultationAsync, - props: { encounter: data } - }) - } - if (indexMcuResult > -1) { - menus.splice(indexMcuResult, 1, { ...menus[indexMcuResult], component: null }) - } - if (indexResume > -1) { - menus.splice(indexResume, 1, { ...menus[indexResume], component: null }) - } - if (indexControlLetter > -1) { - menus.splice(indexControlLetter, 1, { - ...menus[indexControlLetter], - component: ControlLetterListAsync, - props: { encounter: data } - }) - } - if (indexScreening > -1) { - menus.splice(indexScreening, 1, { ...menus[indexScreening], component: null }) - } - if (indexSupportingDocument > -1) { - menus.splice(indexSupportingDocument, 1, { ...menus[indexSupportingDocument], component: null }) - } - if (indexPriceList > -1) { - menus.splice(indexPriceList, 1, { ...menus[indexPriceList], component: null }) - } - - return menus -} - function handleClick(type: string) { if (type === 'draft') { router.back() } } +function initMenus() { + menus.value = getMenuItems(id, props, user, activePosition.value, { + status: data.value, + medicalAssessment: data.value, + medicalAssessmentRehab: data.value, + functionAssessment: data.value, + protocolTheraphy: data.value, + protocolChemotherapy: data.value, + medicineProtocolChemotherapy: data.value, + consultation: data.value, + letterOfControl: data.value, + }, { + protocolTheraphy: paginationMeta, + protocolChemotherapy: paginationMeta, + medicineProtocolChemotherapy: paginationMeta, + }) +} + +async function getData() { + data.value = await getEncounterData(id) +} + watch(getActiveRole, () => { const activeRole = getActiveRole() activePosition.value = getPositionAs(activeRole) - menus.value = getMenus() + initMenus() }) onMounted(async () => { await getData() - menus.value = getMenus() + initMenus() }) diff --git a/app/handlers/encounter-init.handler.ts b/app/handlers/encounter-init.handler.ts index e69de29b..c6b263df 100644 --- a/app/handlers/encounter-init.handler.ts +++ b/app/handlers/encounter-init.handler.ts @@ -0,0 +1,484 @@ +import { isValidDate } from '~/lib/date' +import { medicalPositions } from '~/lib/roles' + +export interface EncounterItem { + id: string + title: string + classCode?: string[] + unit?: string + afterId?: string + component?: any + props?: Record +} + +export interface EncounterProps { + classCode: 'ambulatory' | 'emergency' | 'inpatient' | 'outpatient' + subClassCode: 'reg' | 'rehab' | 'chemo' | 'emg' | 'eon' | 'op' | 'icu' | 'hcu' | 'vk' +} + +export interface EncounterListData { + status?: any + medicalAssessment?: any + medicalAssessmentRehab: any + functionAssessment?: any + protocolTheraphy?: any + protocolChemotherapy?: any + medicineProtocolChemotherapy?: any + consultation?: any + letterOfControl?: any +} + +const StatusAsync = defineAsyncComponent(() => import('~/components/content/encounter/status.vue')) +const AssesmentFunctionListAsync = defineAsyncComponent(() => import('~/components/content/soapi/entry.vue')) +const EarlyMedicalAssesmentListAsync = defineAsyncComponent(() => import('~/components/content/soapi/entry.vue')) +const EarlyMedicalRehabListAsync = defineAsyncComponent(() => import('~/components/content/soapi/entry.vue')) +const PrescriptionAsync = defineAsyncComponent(() => import('~/components/content/prescription/main.vue')) +// const PrescriptionListAsync = defineAsyncComponent(() => import('~/components/content/prescription/list.vue')) +const CpLabOrderAsync = defineAsyncComponent(() => import('~/components/content/cp-lab-order/main.vue')) +const RadiologyAsync = defineAsyncComponent(() => import('~/components/content/radiology-order/main.vue')) +const ConsultationAsync = defineAsyncComponent(() => import('~/components/content/consultation/list.vue')) +const ControlLetterListAsync = defineAsyncComponent(() => import('~/components/content/control-letter/list.vue')) +const ProtocolListAsync = defineAsyncComponent(() => import('~/components/app/chemotherapy/list.protocol.vue')) +const MedicineProtocolListAsync = defineAsyncComponent(() => import('~/components/app/chemotherapy/list.medicine.vue')) + +const defaultKeys: Record = { + status: { + id: 'status', + title: 'Status Masuk/Keluar', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'all', + }, + earlyMedicalAssessment: { + id: 'early-medical-assessment', + title: 'Pengkajian Awal Medis', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'all', + }, + rehabMedicalAssessment: { + id: 'rehab-medical-assessment', + title: 'Pengkajian Awal Medis Rehabilitasi Medis', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'rehab', + afterId: 'early-medical-assessment', + }, + functionAssessment: { + id: 'function-assessment', + title: 'Asesmen Fungsi', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'rehab', + afterId: 'rehab-medical-assessment', + }, + therapyProtocol: { + id: 'therapy-protocol', + classCode: ['ambulatory'], + title: 'Protokol Terapi', + unit: 'rehab', + afterId: 'function-assessment', + }, + chemotherapyProtocol: { + id: 'chemotherapy-protocol', + title: 'Protokol Kemoterapi', + classCode: ['ambulatory'], + unit: 'chemo', + afterId: 'early-medical-assessment', + }, + chemotherapyMedicine: { + id: 'chemotherapy-medicine', + title: 'Protokol Obat Kemoterapi', + classCode: ['ambulatory'], + unit: 'chemo', + afterId: 'chemotherapy-protocol', + }, + report: { + id: 'report', + title: 'Laporan Tindakan', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'all', + }, + patientNote: { + id: 'patient-note', + title: 'CPRJ', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'all', + }, + educationAssessment: { + id: 'education-assessment', + title: 'Asesmen Kebutuhan Edukasi', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'all', + }, + consent: { + id: 'consent', + title: 'General Consent', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'all', + }, + prescription: { + id: 'prescription', + title: 'Order Obat', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'all', + }, + device: { + id: 'device', + title: 'Order Alkes', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'all', + }, + mcuRadiology: { + id: 'mcu-radiology', + title: 'Order Radiologi', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'all', + }, + mcuLabPc: { + id: 'mcu-lab-pc', + title: 'Order Lab PK', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'all', + }, + mcuLabMicro: { + id: 'mcu-lab-micro', + title: 'Order Lab Mikro', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'all', + }, + mcuLabPa: { + id: 'mcu-lab-pa', + title: 'Order Lab PA', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'all', + }, + medicalAction: { + id: 'medical-action', + title: 'Order Ruang Tindakan', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'all', + }, + mcuResult: { + id: 'mcu-result', + title: 'Hasil Penunjang', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'all', + }, + consultation: { + id: 'consultation', + title: 'Konsultasi', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'all', + }, + resume: { + id: 'resume', + title: 'Resume', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'all', + }, + control: { + id: 'control', + title: 'Surat Kontrol', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'all', + }, + screening: { + id: 'screening', + title: 'Skrinning MPP', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'all', + }, + supportingDocument: { + id: 'supporting-document', + title: 'Upload Dokumen Pendukung', + classCode: ['ambulatory'], + unit: 'rehab', + }, + priceList: { + id: 'price-list', + title: 'Tarif Tindakan', + classCode: ['ambulatory', 'emergency', 'inpatient'], + unit: 'all', + }, +} + +export function getItemsByClassCode(classCode: string, items: EncounterItem[]) { + return items.filter((item) => item.classCode?.includes(classCode)) +} + +export function getItemsByUnit(unit: string, items: EncounterItem[]) { + return items.filter((item) => item.unit === unit) +} + +export function getItemsByIds(ids: string[], items: EncounterItem[]) { + return items.filter((item) => ids.includes(item.id)) +} + +export function getIndexById(id: string, items: EncounterItem[]) { + return items.findIndex((item) => item.id === id) +} + +export const getItemsAll = (classCode: string, unit: string, items: EncounterItem[]) => { + const prevItems = [...items] + let updateItems = getItemsByClassCode(classCode, prevItems) + updateItems = getItemsByUnit(unit, updateItems) + return updateItems +} + +export function insertItemByAfterId(id: string, items: EncounterItem[], newItem: EncounterItem) { + const index = getIndexById(id, items) + if (index > -1) { + items.splice(index + 1, 0, newItem) + } +} + +export function injectComponents(id: string | number, data: EncounterListData, meta: EncounterListData) { + const currentKeys = { ...defaultKeys } + if (currentKeys?.status) { + currentKeys.status['component'] = StatusAsync + currentKeys.status['props'] = { encounter: data?.status } + } + if (currentKeys?.earlyMedicalAssessment) { + currentKeys.earlyMedicalAssessment['component'] = EarlyMedicalAssesmentListAsync + currentKeys.earlyMedicalAssessment['props'] = { + encounter: data?.medicalAssessment, + type: 'early-medic', + label: currentKeys.earlyMedicalAssessment['title'], + } + } + if (currentKeys?.rehabMedicalAssessment) { + currentKeys.rehabMedicalAssessment['component'] = EarlyMedicalRehabListAsync + currentKeys.rehabMedicalAssessment['props'] = { + encounter: data?.medicalAssessmentRehab, + type: 'early-rehab', + label: currentKeys.rehabMedicalAssessment['title'], + } + } + if (currentKeys?.functionAssessment) { + currentKeys.functionAssessment['component'] = AssesmentFunctionListAsync + currentKeys.functionAssessment['props'] = { + encounter: data?.functionAssessment, + type: 'function', + label: currentKeys.functionAssessment['title'], + } + } + if (currentKeys?.therapyProtocol) { + currentKeys.therapyProtocol['component'] = ProtocolListAsync + currentKeys.therapyProtocol['props'] = { + data: data?.protocolTheraphy, + paginationMeta: meta?.protocolTheraphy, + } + } + if (currentKeys?.chemotherapyProtocol) { + currentKeys.chemotherapyProtocol['component'] = ProtocolListAsync + currentKeys.chemotherapyProtocol['props'] = { + data: data?.protocolChemotherapy, + paginationMeta: meta?.protocolChemotherapy, + } + } + if (currentKeys?.chemotherapyMedicine) { + currentKeys.chemotherapyMedicine['component'] = MedicineProtocolListAsync + currentKeys.chemotherapyMedicine['props'] = { + data: data?.medicineProtocolChemotherapy, + paginationMeta: meta?.medicineProtocolChemotherapy, + } + } + if (currentKeys?.prescription) { + currentKeys.prescription['component'] = PrescriptionAsync + currentKeys.prescription['props'] = { encounter_id: id } + } + if (currentKeys?.device) { + currentKeys.device['component'] = null + currentKeys.device['props'] = { encounter_id: id } + } + if (currentKeys?.mcuRadiology) { + currentKeys.mcuRadiology['component'] = RadiologyAsync + currentKeys.mcuRadiology['props'] = { encounter_id: id } + } + if (currentKeys?.mcuLabPc) { + currentKeys.mcuLabPc['component'] = CpLabOrderAsync + currentKeys.mcuLabPc['props'] = { encounter_id: id } + } + if (currentKeys?.mcuLabMicro) { + currentKeys.mcuLabMicro['component'] = null + currentKeys.mcuLabMicro['props'] = { encounter_id: id } + } + if (currentKeys?.mcuLabPa) { + currentKeys.mcuLabPa['component'] = null + currentKeys.mcuLabPa['props'] = { encounter_id: id } + } + if (currentKeys?.medicalAction) { + currentKeys.medicalAction['component'] = null + currentKeys.medicalAction['props'] = { encounter_id: id } + } + if (currentKeys?.mcuResult) { + currentKeys.mcuResult['component'] = null + currentKeys.mcuResult['props'] = { encounter_id: id } + } + if (currentKeys?.consultation) { + currentKeys.consultation['component'] = ConsultationAsync + currentKeys.consultation['props'] = { encounter: data?.consultation } + } + if (currentKeys?.resume) { + currentKeys.resume['component'] = null + currentKeys.resume['props'] = { encounter_id: id } + } + if (currentKeys?.control) { + currentKeys.control['component'] = ControlLetterListAsync + currentKeys.control['props'] = { encounter: data?.letterOfControl } + } + if (currentKeys?.screening) { + currentKeys.screening['component'] = null + currentKeys.screening['props'] = { encounter_id: id } + } + if (currentKeys?.supportingDocument) { + currentKeys.supportingDocument['component'] = null + currentKeys.supportingDocument['props'] = { encounter_id: id } + } + if (currentKeys?.priceList) { + currentKeys.priceList['component'] = null + currentKeys.priceList['props'] = { encounter_id: id } + } + if (currentKeys?.patientNote) { + currentKeys.patientNote['component'] = null + currentKeys.patientNote['props'] = { encounter_id: id } + } + if (currentKeys?.educationAssessment) { + currentKeys.educationAssessment['component'] = null + currentKeys.educationAssessment['props'] = { encounter_id: id } + } + if (currentKeys?.consent) { + currentKeys.consent['component'] = null + currentKeys.consent['props'] = { encounter_id: id } + } + if (currentKeys?.report) { + currentKeys.report['component'] = null + currentKeys.report['props'] = { encounter_id: id } + } + + return currentKeys +} + +export function mergeArrayAt(arraysOne: T[], arraysTwo: T[] | T, deleteCount = 0): T[] { + const prevItems = arraysOne.slice() + if (!prevItems) return prevItems + const nextItems = Array.isArray(arraysTwo) ? arraysTwo : [arraysTwo] + if (nextItems.length === 0) return prevItems + // determine insertion position using the first item's `id` if available + const firstId = (nextItems[0] as any)?.afterId || (prevItems[0] as any)?.id + let pos = prevItems.length + if (typeof firstId === 'string') { + const index = prevItems.findIndex((item: any) => item.id === firstId) + pos = index < 0 ? Math.max(prevItems.length + index, 0) : Math.min(index, prevItems.length) + } + prevItems.splice(pos, deleteCount, ...nextItems) + return prevItems +} + +// Function to map API response to Encounter structure +export function mapResponseToEncounter(result: any): any { + if (!result) return null + + // Check if patient and patient.person exist (minimal validation) + if (!result.patient || !result.patient.person) { + return null + } + + const mapped: any = { + id: result.id || 0, + patient_id: result.patient_id || result.patient?.id || 0, + patient: { + id: result.patient?.id || 0, + number: result.patient?.number || '', + person: { + id: result.patient?.person?.id || 0, + name: result.patient?.person?.name || '', + birthDate: result.patient?.person?.birthDate || null, + gender_code: result.patient?.person?.gender_code || '', + residentIdentityNumber: result.patient?.person?.residentIdentityNumber || null, + frontTitle: result.patient?.person?.frontTitle || '', + endTitle: result.patient?.person?.endTitle || '', + addresses: result.patient?.person?.addresses || [], + }, + }, + registeredAt: result.registeredAt || result.patient?.registeredAt || null, + class_code: result.class_code || '', + unit_id: result.unit_id || 0, + unit: result.unit || null, + specialist_id: result.specialist_id || null, + subspecialist_id: result.subspecialist_id || null, + visitDate: isValidDate(result.visitDate) + ? result.visitDate + : result.registeredAt || result.patient?.registeredAt || null, + adm_employee_id: result.adm_employee_id || 0, + appointment_doctor_id: result.appointment_doctor_id || null, + responsible_doctor_id: result.responsible_doctor_id || null, + appointment_doctor: result.appointment_doctor || null, + responsible_doctor: result.responsible_doctor || null, + refSource_name: result.refSource_name || null, + appointment_id: result.appointment_id || null, + earlyEducation: result.earlyEducation || null, + medicalDischargeEducation: result.medicalDischargeEducation || '', + admDischargeEducation: result.admDischargeEducation || null, + discharge_method_code: result.discharge_method_code || null, + discharge_reason: result.dischargeReason || result.discharge_reason || null, + discharge_date: result.discharge_date || null, + status_code: result.status_code || '', + // Payment related fields + paymentMethod_code: + result.paymentMethod_code && result.paymentMethod_code.trim() !== '' ? result.paymentMethod_code : null, + trx_number: result.trx_number || null, + member_number: result.member_number || null, + ref_number: result.ref_number || null, + } + + return mapped +} + +export function getMenuItems( + id: string | number, + props: any, + user: any, + activePosition: any, + data: EncounterListData, + meta: any, +) { + const normalClassCode = props.classCode === 'ambulatory' ? 'outpatient' : props.classCode + const currentKeys = injectComponents(id, data, meta) + const defaultItems: EncounterItem[] = Object.values(currentKeys) + const listItemsForOutpatientRehab = mergeArrayAt( + getItemsAll('ambulatory', 'all', defaultItems), + getItemsAll('ambulatory', 'rehab', defaultItems), + ) + const listItemsForOutpatientChemo = mergeArrayAt( + getItemsAll('ambulatory', 'all', defaultItems), + getItemsAll('ambulatory', 'chemo', defaultItems), + ) + const listItems: Record>> = { + 'installation|outpatient': { + 'unit|rehab': { + items: listItemsForOutpatientRehab, + roles: medicalPositions, + }, + 'unit|chemo': { + items: listItemsForOutpatientChemo, + roles: medicalPositions, + }, + all: getItemsAll('ambulatory', 'all', defaultItems), + }, + 'installation|emergency': { + all: getItemsAll('emergency', 'all', defaultItems), + }, + 'installation|inpatient': { + all: getItemsAll('inpatient', 'all', defaultItems), + }, + } + const currentListItems = listItems[`installation|${normalClassCode}`] + if (!currentListItems) return [] + const unitCode = user?.unit?.code ? `unit|${user.unit.code}` : 'all' + const currentUnitItems: any = currentListItems[`${unitCode}`] + if (!currentUnitItems) return [] + let menus = [] + if (currentUnitItems.roles && currentUnitItems.roles?.some((role: string) => role === activePosition.value)) { + menus = [...currentUnitItems.items] + } else { + menus = [...currentUnitItems] + } +} diff --git a/app/handlers/encounter-process.handler.ts b/app/handlers/encounter-process.handler.ts index 665cae04..4dc91066 100644 --- a/app/handlers/encounter-process.handler.ts +++ b/app/handlers/encounter-process.handler.ts @@ -1,311 +1,31 @@ -import { isValidDate } from '~/lib/date' -import { medicalPositions } from '~/lib/roles' +// Services +import { getDetail } from '~/services/encounter.service' -export interface EncounterItem { - id: string - title: string - classCode?: string[] - unit?: string - afterId?: string - component?: any - props?: Record -} +// Handlers +import { mapResponseToEncounter } from '~/handlers/encounter-init.handler' -export interface EncounterProps { - classCode: 'ambulatory' | 'emergency' | 'inpatient' | 'outpatient' - subClassCode: 'reg' | 'rehab' | 'chemo' | 'emg' | 'eon' | 'op' | 'icu' | 'hcu' | 'vk' -} +export async function getEncounterData(id: string | number) { + let data = null + try { + const dataRes = await getDetail(id, { + includes: + 'patient,patient-person,patient-person-addresses,unit,Appointment_Doctor,Appointment_Doctor-employee,Appointment_Doctor-employee-person,Responsible_Doctor,Responsible_Doctor-employee,Responsible_Doctor-employee-person', + }) + const dataResBody = dataRes.body ?? null + const result = dataResBody?.data ?? null -export const defaultItems: EncounterItem[] = [ - { - id: 'status', - title: 'Status Masuk/Keluar', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'all', - }, - { - id: 'early-medical-assessment', - title: 'Pengkajian Awal Medis', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'all', - }, - { - id: 'rehab-medical-assessment', - title: 'Pengkajian Awal Medis Rehabilitasi Medis', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'rehab', - afterId: 'early-medical-assessment', - }, - { - id: 'function-assessment', - title: 'Asesmen Fungsi', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'rehab', - afterId: 'rehab-medical-assessment', - }, - { - id: 'therapy-protocol', - classCode: ['ambulatory'], - title: 'Protokol Terapi', - unit: 'rehab', - afterId: 'function-assessment', - }, - { - id: 'chemotherapy-protocol', - title: 'Protokol Kemoterapi', - classCode: ['ambulatory'], - unit: 'chemo', - afterId: 'early-medical-assessment', - }, - { - id: 'chemotherapy-medicine', - title: 'Protokol Obat Kemoterapi', - classCode: ['ambulatory'], - unit: 'chemo', - afterId: 'chemotherapy-protocol', - }, - { - id: 'report', - title: 'Laporan Tindakan', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'all', - }, - { - id: 'patient-note', - title: 'CPRJ', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'all', - }, - { - id: 'education-assessment', - title: 'Asesmen Kebutuhan Edukasi', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'all', - }, - { - id: 'consent', - title: 'General Consent', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'all', - }, - { - id: 'prescription', - title: 'Order Obat', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'all', - }, - { - id: 'device', - title: 'Order Alkes', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'all', - }, - { - id: 'mcu-radiology', - title: 'Order Radiologi', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'all', - }, - { - id: 'mcu-lab-pc', - title: 'Order Lab PK', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'all', - }, - { - id: 'mcu-lab-micro', - title: 'Order Lab Mikro', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'all', - }, - { - id: 'mcu-lab-pa', - title: 'Order Lab PA', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'all', - }, - { - id: 'medical-action', - title: 'Order Ruang Tindakan', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'all', - }, - { - id: 'mcu-result', - title: 'Hasil Penunjang', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'all', - }, - { - id: 'consultation', - title: 'Konsultasi', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'all', - }, - { - id: 'resume', - title: 'Resume', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'all', - }, - { - id: 'control', - title: 'Surat Kontrol', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'all', - }, - { - id: 'screening', - title: 'Skrinning MPP', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'all', - }, - { - id: 'supporting-document', - title: 'Upload Dokumen Pendukung', - classCode: ['ambulatory'], - unit: 'rehab', - }, - { - id: 'price-list', - title: 'Tarif Tindakan', - classCode: ['ambulatory', 'emergency', 'inpatient'], - unit: 'all', - }, -] - -const getItemsByClassCode = (classCode: string, items: EncounterItem[]) => { - return items.filter((item) => item.classCode?.includes(classCode)) -} - -const getItemsByUnit = (unit: string, items: EncounterItem[]) => { - return items.filter((item) => item.unit === unit) -} - -export const getItemsByIds = (ids: string[], items: EncounterItem[]) => { - return items.filter((item) => ids.includes(item.id)) -} - -export const getIndexById = (id: string, items: EncounterItem[]) => { - return items.findIndex((item) => item.id === id) -} - -export function insertItemByAfterId(id: string, items: EncounterItem[], newItem: EncounterItem) { - const index = getIndexById(id, items) - if (index > -1) { - items.splice(index + 1, 0, newItem) + if (result) { + const mappedData = mapResponseToEncounter(result) + if (mappedData) { + data = mappedData + } else { + data = null + } + } else { + data = null + } + } catch (error) { + console.error('Error fetching encounter data:', error) + data = null } -} - -export function mergeArrayAt(arraysOne: T[], arraysTwo: T[] | T, deleteCount = 0): T[] { - const prevItems = arraysOne.slice() - if (!prevItems) return prevItems - const nextItems = Array.isArray(arraysTwo) ? arraysTwo : [arraysTwo] - if (nextItems.length === 0) return prevItems - // determine insertion position using the first item's `id` if available - const firstId = (nextItems[0] as any)?.afterId || (prevItems[0] as any)?.id - let pos = prevItems.length - if (typeof firstId === 'string') { - const index = prevItems.findIndex((item: any) => item.id === firstId) - pos = index < 0 ? Math.max(prevItems.length + index, 0) : Math.min(index, prevItems.length) - } - prevItems.splice(pos, deleteCount, ...nextItems) - return prevItems -} - -export const getItemsAll = (classCode: string, unit: string, items: EncounterItem[]) => { - const prevItems = [...items] - let updateItems = getItemsByClassCode(classCode, prevItems) - updateItems = getItemsByUnit(unit, updateItems) - return updateItems -} - -// Function to map API response to Encounter structure -export function mapResponseToEncounter(result: any): any { - if (!result) return null - - // Check if patient and patient.person exist (minimal validation) - if (!result.patient || !result.patient.person) { - return null - } - - const mapped: any = { - id: result.id || 0, - patient_id: result.patient_id || result.patient?.id || 0, - patient: { - id: result.patient?.id || 0, - number: result.patient?.number || '', - person: { - id: result.patient?.person?.id || 0, - name: result.patient?.person?.name || '', - birthDate: result.patient?.person?.birthDate || null, - gender_code: result.patient?.person?.gender_code || '', - residentIdentityNumber: result.patient?.person?.residentIdentityNumber || null, - frontTitle: result.patient?.person?.frontTitle || '', - endTitle: result.patient?.person?.endTitle || '', - addresses: result.patient?.person?.addresses || [], - }, - }, - registeredAt: result.registeredAt || result.patient?.registeredAt || null, - class_code: result.class_code || '', - unit_id: result.unit_id || 0, - unit: result.unit || null, - specialist_id: result.specialist_id || null, - subspecialist_id: result.subspecialist_id || null, - visitDate: isValidDate(result.visitDate) - ? result.visitDate - : result.registeredAt || result.patient?.registeredAt || null, - adm_employee_id: result.adm_employee_id || 0, - appointment_doctor_id: result.appointment_doctor_id || null, - responsible_doctor_id: result.responsible_doctor_id || null, - appointment_doctor: result.appointment_doctor || null, - responsible_doctor: result.responsible_doctor || null, - refSource_name: result.refSource_name || null, - appointment_id: result.appointment_id || null, - earlyEducation: result.earlyEducation || null, - medicalDischargeEducation: result.medicalDischargeEducation || '', - admDischargeEducation: result.admDischargeEducation || null, - discharge_method_code: result.discharge_method_code || null, - discharge_reason: result.dischargeReason || result.discharge_reason || null, - discharge_date: result.discharge_date || null, - status_code: result.status_code || '', - // Payment related fields - paymentMethod_code: - result.paymentMethod_code && result.paymentMethod_code.trim() !== '' ? result.paymentMethod_code : null, - trx_number: result.trx_number || null, - member_number: result.member_number || null, - ref_number: result.ref_number || null, - } - - return mapped -} - -const listItemsForOutpatientRehab = mergeArrayAt( - getItemsAll('ambulatory', 'all', defaultItems), - getItemsAll('ambulatory', 'rehab', defaultItems), -) - -const listItemsForOutpatientChemo = mergeArrayAt( - getItemsAll('ambulatory', 'all', defaultItems), - getItemsAll('ambulatory', 'chemo', defaultItems), -) - -export const listItems: Record>> = { - 'installation|outpatient': { - 'unit|rehab': { - items: listItemsForOutpatientRehab, - roles: medicalPositions, - }, - 'unit|chemo': { - items: listItemsForOutpatientChemo, - roles: medicalPositions, - }, - all: getItemsAll('ambulatory', 'all', defaultItems), - }, - 'installation|emergency': { - all: getItemsAll('emergency', 'all', defaultItems), - }, - 'installation|inpatient': { - all: getItemsAll('inpatient', 'all', defaultItems), - }, -} +} \ No newline at end of file