Files
simrsx-fe/app/components/content/encounter/entry.vue
2025-12-02 10:02:00 +07:00

216 lines
5.3 KiB
Vue

<script setup lang="ts">
// Components
import { Button } from '~/components/pub/ui/button'
import AppEncounterEntryForm from '~/components/app/encounter/entry-form.vue'
import AppViewPatient from '~/components/app/patient/view-patient.vue'
// Helpers
import { refDebounced } from '@vueuse/core'
// Handlers
import { getDetail as getDoctorDetail } from '~/services/doctor.service'
import { useEncounterEntry } from '~/handlers/encounter-entry.handler'
import { genDoctor, type Doctor } from '~/models/doctor'
// Props
const props = defineProps<{
id: number
classCode?: 'ambulatory' | 'emergency' | 'inpatient' | 'outpatient'
subClassCode?: 'reg' | 'rehab' | 'chemo' | 'emg' | 'eon' | 'op' | 'icu' | 'hcu' | 'vk'
formType: string
}>()
const route = useRoute()
const formRef = ref<InstanceType<typeof AppEncounterEntryForm> | null>(null)
const {
paymentsList,
sepNumber,
sepsList,
participantGroupsList,
specialistsTree,
doctorsList,
recSelectId,
isLoadingDetail,
formObjects,
openPatient,
isSepValid,
isCheckingSep,
isSaveDisabled,
isSaving,
isLoading,
patients,
selectedPatient,
selectedPatientObject,
paginationMeta,
toNavigateSep,
getListPath,
handleInit,
loadEncounterDetail,
handleSaveEncounter,
getPatientsList,
getPatientCurrent,
getPatientByIdentifierSearch,
getIsSubspecialist,
getValidateSepNumber,
handleFetchDoctors,
} = useEncounterEntry(props)
const debouncedSepNumber = refDebounced(sepNumber, 500)
const selectedDoctor = ref<Doctor>(genDoctor())
provide('rec_select_id', recSelectId)
provide('table_data_loader', isLoading)
watch(debouncedSepNumber, async (newValue) => {
await getValidateSepNumber(newValue)
})
watch(
() => formObjects.value?.paymentType,
(newValue) => {
isSepValid.value = false
if (newValue !== 'jkn') {
sepNumber.value = ''
}
},
)
onMounted(async () => {
await handleInit()
if (props.id > 0) {
await loadEncounterDetail()
}
})
///// Functions
function handleSavePatient() {
selectedPatientObject.value = null
setTimeout(() => {
getPatientCurrent(selectedPatient.value)
}, 150)
}
function handleSaveClick() {
if (formRef.value && typeof formRef.value.submitForm === 'function') {
formRef.value.submitForm()
}
}
function handleFetch(value?: any) {
if (value?.subSpecialistId) {
handleFetchDoctors(value.subSpecialistId)
}
}
async function handleEvent(menu: string, value?: any) {
if (menu === 'search') {
getPatientsList({ 'page-size': 10, includes: 'person' }).then(() => {
openPatient.value = true
})
} else if (menu === 'add') {
navigateTo('/client/patient/add')
} else if (menu === 'add-sep') {
if (isSepValid.value) {
return
}
toNavigateSep({
isService: 'false',
sourcePath: route.path,
resource: `${props.classCode}-${props.subClassCode}`,
...value,
})
} else if (menu === 'sep-number-changed') {
await getValidateSepNumber(String(value || ''))
} else if (menu === 'save') {
await handleSaveEncounter(value)
} else if (menu === 'cancel') {
navigateTo(getListPath())
}
}
async function getDoctorInfo(value: string) {
const resp = await getDoctorDetail(value, { includes: 'unit,specialist,subspecialist'})
if (resp.success) {
selectedDoctor.value = resp.body.data
// console.log(selectedDoctor.value)
}
}
</script>
<template>
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
<Icon
name="i-lucide-user"
class="me-2"
/>
<span class="font-semibold">{{ props.formType }}</span>
Kunjungan
</div>
<AppEncounterEntryForm
ref="formRef"
:is-loading="isLoadingDetail"
:is-sep-valid="isSepValid"
:is-checking-sep="isCheckingSep"
:payments="paymentsList"
:seps="sepsList"
:participant-groups="participantGroupsList"
:specialists="specialistsTree"
:doctorItems="doctorsList"
:selectedDoctor="selectedDoctor"
:patient="selectedPatientObject"
:objects="formObjects"
@on-select-doctor="getDoctorInfo"
@event="handleEvent"
@fetch="handleFetch"
/>
<AppViewPatient
v-model:open="openPatient"
v-model:selected="selectedPatient"
:patients="patients"
:pagination-meta="paginationMeta"
@fetch="
(value) => {
if (value.search && value.search.length >= 3) {
// Use identifier search for specific searches (NIK, RM, etc.)
getPatientByIdentifierSearch(value.search)
} else {
// Use regular search for general searches
getPatientsList({ ...value, 'page-size': 10, includes: 'person' })
}
}
"
@save="handleSavePatient"
/>
<!-- Footer Actions -->
<div class="mt-6 flex justify-end gap-2 border-t border-t-slate-300 pt-4">
<Button
variant="outline"
type="button"
class="h-[40px] min-w-[120px] rounded-md border-orange-400 text-orange-400 hover:bg-green-50 hover:text-orange-400"
@click="handleEvent('cancel')"
>
<Icon
name="i-lucide-x"
class="h-5 w-5"
/>
Batal
</Button>
<Button
type="button"
class="h-[40px] min-w-[120px] text-white"
:disabled="isSaveDisabled"
@click="handleSaveClick"
>
<Icon
name="i-lucide-save"
class="h-5 w-5"
/>
Simpan
</Button>
</div>
</template>