454 lines
16 KiB
Vue
454 lines
16 KiB
Vue
<script setup lang="ts">
|
|
import { ref, onMounted } from 'vue'
|
|
import { useRoute } from 'vue-router'
|
|
|
|
// Components
|
|
import AppSepEntryForm from '~/components/app/sep/entry-form.vue'
|
|
import AppViewPatient from '~/components/app/patient/view-patient.vue'
|
|
import AppViewHistory from '~/components/app/sep/view-history.vue'
|
|
import AppViewLetter from '~/components/app/sep/view-letter.vue'
|
|
import { toast } from '~/components/pub/ui/toast'
|
|
|
|
// Types
|
|
import type { SepHistoryData } from '~/components/app/sep/list-cfg.history'
|
|
|
|
// Constants
|
|
import {
|
|
serviceTypes,
|
|
serviceAssessments,
|
|
registerMethods,
|
|
trafficAccidents,
|
|
supportCodes,
|
|
procedureTypes,
|
|
purposeOfVisits,
|
|
classLevels,
|
|
classLevelUpgrades,
|
|
classPaySources,
|
|
} from '~/lib/constants.vclaim'
|
|
|
|
// Services
|
|
import { getValueLabelList as getProvinceList } from '~/services/vclaim-region-province.service'
|
|
import { getValueLabelList as getCityList } from '~/services/vclaim-region-city.service'
|
|
import { getValueLabelList as getDistrictList } from '~/services/vclaim-region-district.service'
|
|
import { getValueLabelList as getDoctorLabelList } from '~/services/vclaim-doctor.service'
|
|
import { getValueLabelList as getHealthFacilityLabelList } from '~/services/vclaim-healthcare.service'
|
|
import { getValueLabelList as getDiagnoseLabelList } from '~/services/vclaim-diagnose.service'
|
|
import { getList as getHospitalLetterList } from '~/services/vclaim-reference-hospital-letter.service'
|
|
import { getList as getControlLetterList } from '~/services/vclaim-control-letter.service'
|
|
import { getList as getMonitoringHistoryList } from '~/services/vclaim-monitoring-history.service'
|
|
import { create as createSep, makeSepData } from '~/services/vclaim-sep.service'
|
|
|
|
// Handlers
|
|
import {
|
|
patients,
|
|
selectedPatient,
|
|
selectedPatientObject,
|
|
paginationMeta,
|
|
getPatientsList,
|
|
getPatientCurrent,
|
|
getPatientByIdentifierSearch,
|
|
} from '~/handlers/patient.handler'
|
|
|
|
const route = useRoute()
|
|
const openPatient = ref(false)
|
|
const openLetter = ref(false)
|
|
const openHistory = ref(false)
|
|
const selectedLetter = ref('')
|
|
const selectedObjects = ref<any>({})
|
|
const selectedServiceType = ref<string>('')
|
|
const selectedAdmissionType = ref<string>('')
|
|
const histories = ref<Array<SepHistoryData>>([])
|
|
const letters = ref<Array<any>>([])
|
|
const doctors = ref<Array<{ value: string | number; label: string }>>([])
|
|
const diagnoses = ref<Array<{ value: string | number; label: string }>>([])
|
|
const facilitiesFrom = ref<Array<{ value: string | number; label: string }>>([])
|
|
const facilitiesTo = ref<Array<{ value: string | number; label: string }>>([])
|
|
const supportCodesList = ref<Array<{ value: string; label: string }>>([])
|
|
const serviceTypesList = ref<Array<{ value: string; label: string }>>([])
|
|
const registerMethodsList = ref<Array<{ value: string; label: string }>>([])
|
|
const accidentsList = ref<Array<{ value: string; label: string }>>([])
|
|
const purposeOfVisitsList = ref<Array<{ value: string; label: string }>>([])
|
|
const proceduresList = ref<Array<{ value: string; label: string }>>([])
|
|
const assessmentsList = ref<Array<{ value: string; label: string }>>([])
|
|
const provincesList = ref<Array<{ value: string; label: string }>>([])
|
|
const citiesList = ref<Array<{ value: string; label: string }>>([])
|
|
const districtsList = ref<Array<{ value: string; label: string }>>([])
|
|
const classLevelsList = ref<Array<{ value: string; label: string }>>([])
|
|
const classLevelUpgradesList = ref<Array<{ value: string; label: string }>>([])
|
|
const classPaySourcesList = ref<Array<{ value: string; label: string }>>([])
|
|
const isServiceHidden = ref(false)
|
|
const isSaveLoading = ref(false)
|
|
const resourceType = ref('')
|
|
|
|
async function getMonitoringHistoryMappers() {
|
|
histories.value = []
|
|
const dateFirst = new Date()
|
|
const dateLast = new Date()
|
|
dateLast.setMonth(dateFirst.getMonth() - 3)
|
|
const cardNumber =
|
|
selectedPatientObject.value?.person?.residentIdentityNumber || selectedPatientObject.value?.number || ''
|
|
const result = await getMonitoringHistoryList({
|
|
cardNumber: cardNumber,
|
|
startDate: dateFirst.toISOString().substring(0, 10),
|
|
endDate: dateLast.toISOString().substring(0, 10),
|
|
})
|
|
if (result && result.success && result.body) {
|
|
const historiesRaw = result.body?.response?.histori || []
|
|
if (!historiesRaw) return
|
|
historiesRaw.forEach((result: any) => {
|
|
histories.value.push({
|
|
sepNumber: result.noSep,
|
|
sepDate: result.tglSep,
|
|
referralNumber: result.noRujukan,
|
|
diagnosis:
|
|
result.diagnosa && typeof result.diagnosa === 'string' && result.diagnosa.length > 20
|
|
? result.diagnosa.toString().substring(0, 17) + '...'
|
|
: '-',
|
|
serviceType: !result.jnsPelayanan ? '-' : result.jnsPelayanan === '1' ? 'Rawat Jalan' : 'Rawat Inap',
|
|
careClass: result.kelasRawat,
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
async function getLetterMappers(admissionType: string, search: string) {
|
|
letters.value = []
|
|
let result = null
|
|
if (admissionType !== '3') {
|
|
result = await getHospitalLetterList({
|
|
letterNumber: search,
|
|
})
|
|
} else {
|
|
result = await getControlLetterList({
|
|
letterNumber: search,
|
|
mode: 'by-control',
|
|
})
|
|
if (result && result.success && result.body) {
|
|
const lettersRaw = result.body?.response || null
|
|
if (!lettersRaw) {
|
|
result = await getControlLetterList({
|
|
letterNumber: search,
|
|
mode: 'by-card',
|
|
})
|
|
}
|
|
}
|
|
if (result && result.success && result.body) {
|
|
const lettersRaw = result.body?.response || null
|
|
if (!lettersRaw) {
|
|
result = await getControlLetterList({
|
|
letterNumber: search,
|
|
mode: 'by-sep',
|
|
})
|
|
}
|
|
}
|
|
}
|
|
if (result && result.success && result.body) {
|
|
const lettersRaw = result.body?.response || null
|
|
if (!lettersRaw) return
|
|
if (admissionType === '3') {
|
|
letters.value = [
|
|
{
|
|
letterNumber: lettersRaw.noSuratKontrol || '',
|
|
plannedDate: lettersRaw.tglRencanaKontrol || '',
|
|
sepNumber: lettersRaw.sep.noSep || '',
|
|
patientName: lettersRaw.sep.peserta.nama || '',
|
|
bpjsCardNo: lettersRaw.sep.peserta.noKartu,
|
|
clinic: lettersRaw.sep.poli || '',
|
|
doctor: lettersRaw.sep.namaDokter || '',
|
|
},
|
|
]
|
|
} else {
|
|
letters.value = [
|
|
{
|
|
letterNumber: lettersRaw.rujukan.noKunjungan || '',
|
|
plannedDate: lettersRaw.rujukan.tglKunjungan || '',
|
|
sepNumber: lettersRaw.rujukan?.informasi?.eSEP || '-',
|
|
patientName: lettersRaw.rujukan.peserta.nama || '',
|
|
bpjsCardNo: lettersRaw.rujukan.peserta.noKartu || '',
|
|
clinic: lettersRaw.rujukan.poliRujukan.nama || '',
|
|
doctor: '',
|
|
},
|
|
]
|
|
}
|
|
}
|
|
}
|
|
|
|
function handleSavePatient() {
|
|
selectedPatientObject.value = null
|
|
setTimeout(() => {
|
|
getPatientCurrent(selectedPatient.value)
|
|
}, 150)
|
|
}
|
|
|
|
function handleSaveLetter() {
|
|
// Find the selected letter and get its plannedDate
|
|
const selectedLetterData = letters.value.find((letter) => letter.letterNumber === selectedLetter.value)
|
|
if (selectedLetterData && selectedLetterData.plannedDate) {
|
|
selectedObjects.value['letterDate'] = selectedLetterData.plannedDate
|
|
}
|
|
}
|
|
|
|
async function handleEvent(menu: string, value: any) {
|
|
if (menu === 'admission-type') {
|
|
selectedAdmissionType.value = value
|
|
return
|
|
}
|
|
if (menu === 'service-type') {
|
|
selectedServiceType.value = value
|
|
doctors.value = await getDoctorLabelList({
|
|
serviceType: selectedServiceType.value || 1,
|
|
serviceDate: new Date().toISOString().substring(0, 10),
|
|
specialistCode: 0,
|
|
})
|
|
}
|
|
if (menu === 'search-patient') {
|
|
getPatientsList({ 'page-size': 10, includes: 'person' }).then(() => {
|
|
openPatient.value = true
|
|
})
|
|
return
|
|
}
|
|
if (menu === 'search-letter') {
|
|
getLetterMappers(value.admissionType, value.search).then(() => {
|
|
if (letters.value.length > 0) {
|
|
const copyObjects = { ...selectedObjects.value }
|
|
selectedObjects.value = {}
|
|
selectedLetter.value = letters.value[0].letterNumber
|
|
setTimeout(() => {
|
|
selectedObjects.value = copyObjects
|
|
selectedObjects.value['letterDate'] = letters.value[0].plannedDate
|
|
}, 100)
|
|
}
|
|
})
|
|
return
|
|
}
|
|
if (menu === 'open-letter') {
|
|
openLetter.value = true
|
|
return
|
|
}
|
|
if (menu === 'history-sep') {
|
|
getMonitoringHistoryMappers().then(() => {
|
|
openHistory.value = true
|
|
})
|
|
return
|
|
}
|
|
if (menu === 'back') {
|
|
navigateTo('/integration/bpjs/sep')
|
|
}
|
|
if (menu === 'save-sep') {
|
|
isSaveLoading.value = true
|
|
createSep(makeSepData(value))
|
|
.then((res) => {
|
|
const body = res?.body
|
|
const code = body?.metaData?.code
|
|
const message = body?.metaData?.message
|
|
if (code && code !== '200') {
|
|
toast({ title: 'Gagal', description: message || 'Gagal membuat SEP', variant: 'destructive' })
|
|
return
|
|
}
|
|
toast({ title: 'Berhasil', description: 'SEP berhasil dibuat', variant: 'default' })
|
|
if (resourceType.value === 'encounter') {
|
|
navigateTo('/rehab/encounter/add')
|
|
return
|
|
}
|
|
navigateTo('/integration/bpjs/sep')
|
|
})
|
|
.catch((err) => {
|
|
console.error('Failed to save SEP:', err)
|
|
toast({ title: 'Gagal', description: err?.message || 'Gagal membuat SEP', variant: 'destructive' })
|
|
})
|
|
.finally(() => {
|
|
isSaveLoading.value = false
|
|
})
|
|
}
|
|
}
|
|
|
|
async function handleFetch(params: any) {
|
|
const menu = params.menu || ''
|
|
const value = params.value || ''
|
|
if (menu === 'diagnosis') {
|
|
diagnoses.value = await getDiagnoseLabelList({ diagnosa: value })
|
|
}
|
|
if (menu === 'clinic-from') {
|
|
facilitiesFrom.value = await getHealthFacilityLabelList({
|
|
healthcare: value,
|
|
healthcareType: selectedServiceType.value || 1,
|
|
})
|
|
}
|
|
if (menu === 'clinic-to') {
|
|
facilitiesTo.value = await getHealthFacilityLabelList({
|
|
healthcare: value,
|
|
healthcareType: selectedServiceType.value || 1,
|
|
})
|
|
}
|
|
if (menu === 'province') {
|
|
citiesList.value = await getCityList({ province: value })
|
|
districtsList.value = []
|
|
}
|
|
if (menu === 'city') {
|
|
districtsList.value = await getDistrictList({ city: value })
|
|
}
|
|
}
|
|
|
|
async function handleInit() {
|
|
const facilities = await getHealthFacilityLabelList({
|
|
healthcare: 'Puskesmas',
|
|
healthcareType: selectedLetter.value || 1,
|
|
})
|
|
diagnoses.value = await getDiagnoseLabelList({ diagnosa: 'paru' })
|
|
facilitiesFrom.value = facilities
|
|
facilitiesTo.value = facilities
|
|
doctors.value = await getDoctorLabelList({
|
|
serviceType: selectedServiceType.value || 1,
|
|
serviceDate: new Date().toISOString().substring(0, 10),
|
|
specialistCode: 0,
|
|
})
|
|
provincesList.value = await getProvinceList()
|
|
serviceTypesList.value = Object.keys(serviceTypes).map((item) => ({
|
|
value: item.toString(),
|
|
label: serviceTypes[item],
|
|
})) as any
|
|
registerMethodsList.value = Object.keys(registerMethods)
|
|
.filter((item) => ![''].includes(item))
|
|
.map((item) => ({
|
|
value: item.toString(),
|
|
label: registerMethods[item],
|
|
})) as any
|
|
accidentsList.value = Object.keys(trafficAccidents).map((item) => ({
|
|
value: item.toString(),
|
|
label: trafficAccidents[item],
|
|
})) as any
|
|
purposeOfVisitsList.value = Object.keys(purposeOfVisits).map((item) => ({
|
|
value: item.toString(),
|
|
label: purposeOfVisits[item],
|
|
})) as any
|
|
proceduresList.value = Object.keys(procedureTypes).map((item) => ({
|
|
value: item.toString(),
|
|
label: procedureTypes[item],
|
|
})) as any
|
|
assessmentsList.value = Object.keys(serviceAssessments).map((item) => ({
|
|
value: item.toString(),
|
|
label: `${item.toString()} - ${serviceAssessments[item]}`,
|
|
})) as any
|
|
supportCodesList.value = Object.keys(supportCodes).map((item) => ({
|
|
value: item.toString(),
|
|
label: `${item.toString()} - ${supportCodes[item]}`,
|
|
})) as any
|
|
classLevelsList.value = Object.keys(classLevels).map((item) => ({
|
|
value: item.toString(),
|
|
label: classLevels[item],
|
|
})) as any
|
|
classLevelUpgradesList.value = Object.keys(classLevelUpgrades).map((item) => ({
|
|
value: item.toString(),
|
|
label: classLevelUpgrades[item],
|
|
})) as any
|
|
classPaySourcesList.value = Object.keys(classPaySources).map((item) => ({
|
|
value: item.toString(),
|
|
label: classPaySources[item],
|
|
})) as any
|
|
if (route.query) {
|
|
const queries = route.query as any
|
|
isServiceHidden.value = queries['is-service'] === 'true'
|
|
selectedObjects.value = {}
|
|
if (queries['bpjs-number']) selectedObjects.value['bpjsNumber'] = queries['bpjs-number']
|
|
if (queries['register-date']) selectedObjects.value['registerDate'] = queries['register-date']
|
|
if (queries['sep-type']) selectedObjects.value['sepType'] = queries['sep-type']
|
|
if (queries['sep-number']) selectedObjects.value['sepNumber'] = queries['sep-number']
|
|
if (queries['register-date']) selectedObjects.value['registerDate'] = queries['register-date']
|
|
if (queries['doctor-id']) selectedObjects.value['doctorId'] = queries['doctor-id']
|
|
if (queries['patient-name']) selectedObjects.value['patientName'] = queries['patient-name']
|
|
if (queries['national-identity']) selectedObjects.value['nationalIdentity'] = queries['national-identity']
|
|
if (queries['payment-type']) selectedObjects.value['paymentType'] = queries['payment-type']
|
|
if (queries['medical-record-number'])
|
|
selectedObjects.value['medicalRecordNumber'] = queries['medical-record-number']
|
|
if (queries['resource']) resourceType.value = queries['resource']
|
|
delete selectedObjects.value['is-service']
|
|
// Load patient data if identifier is provided
|
|
if (queries['national-identity'] && queries['medical-record-number']) {
|
|
try {
|
|
await getPatientByIdentifierSearch(queries['national-identity'])
|
|
if (patients.value.length > 0) {
|
|
const foundPatient = patients.value[0]
|
|
if (foundPatient && foundPatient.id) {
|
|
selectedPatient.value = foundPatient.id
|
|
await getPatientCurrent(foundPatient.id)
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.error('Failed to load patient from query params:', err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
onMounted(async () => {
|
|
await handleInit()
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
|
<Icon
|
|
name="i-lucide-panel-bottom"
|
|
class="me-2"
|
|
/>
|
|
<span class="font-semibold">Tambah</span>
|
|
SEP
|
|
</div>
|
|
<AppSepEntryForm
|
|
:doctors="doctors"
|
|
:diagnoses="diagnoses"
|
|
:facilities-from="facilitiesFrom"
|
|
:facilities-to="facilitiesTo"
|
|
:service-types="serviceTypesList"
|
|
:register-methods="registerMethodsList"
|
|
:accidents="accidentsList"
|
|
:purposes="purposeOfVisitsList"
|
|
:procedures="proceduresList"
|
|
:assessments="assessmentsList"
|
|
:support-codes="supportCodesList"
|
|
:provinces="provincesList"
|
|
:cities="citiesList"
|
|
:districts="districtsList"
|
|
:class-levels="classLevelsList"
|
|
:class-level-upgrades="classLevelUpgradesList"
|
|
:class-pay-sources="classPaySourcesList"
|
|
:is-save-loading="isSaveLoading"
|
|
:is-service="isServiceHidden"
|
|
:patient="selectedPatientObject"
|
|
:objects="selectedObjects"
|
|
@fetch="handleFetch"
|
|
@event="handleEvent"
|
|
/>
|
|
<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"
|
|
/>
|
|
<AppViewHistory
|
|
v-model:open="openHistory"
|
|
:histories="histories"
|
|
/>
|
|
<AppViewLetter
|
|
v-model:open="openLetter"
|
|
:letters="letters"
|
|
:menu="selectedAdmissionType !== '3' ? 'control' : 'reference'"
|
|
:selected="selectedLetter"
|
|
:pagination-meta="{ recordCount: 0, page: 1, pageSize: 10, totalPage: 0 } as any"
|
|
@fetch="(value) => getLetterMappers(value.admissionType, value.search)"
|
|
@save="handleSaveLetter"
|
|
/>
|
|
</template>
|