feat: update chemotherapy encounter pages to use 'chemo' subclass code + simplify sep
This commit is contained in:
@@ -1,642 +1,59 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { onMounted } from 'vue'
|
||||
|
||||
// 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'
|
||||
import type { TreeItem } from '~/components/pub/my-ui/select-tree/type'
|
||||
// Handler
|
||||
import useIntegrationSepEntry from '~/handlers/integration-sep-entry.handler'
|
||||
|
||||
// Constants
|
||||
import {
|
||||
serviceTypes,
|
||||
serviceAssessments,
|
||||
registerMethods,
|
||||
trafficAccidents,
|
||||
supportCodes,
|
||||
procedureTypes,
|
||||
purposeOfVisits,
|
||||
classLevels,
|
||||
classLevelUpgrades,
|
||||
classPaySources,
|
||||
} from '~/lib/constants.vclaim'
|
||||
|
||||
// Services
|
||||
import {
|
||||
getList as getSpecialistList,
|
||||
getValueTreeItems as getSpecialistTreeItems,
|
||||
} from '~/services/specialist.service'
|
||||
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 getMemberList } from '~/services/vclaim-member.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 {
|
||||
const {
|
||||
openPatient,
|
||||
openLetter,
|
||||
openHistory,
|
||||
selectedLetter,
|
||||
selectedObjects,
|
||||
selectedServiceType,
|
||||
selectedAdmissionType,
|
||||
histories,
|
||||
letters,
|
||||
doctors,
|
||||
diagnoses,
|
||||
facilitiesFrom,
|
||||
facilitiesTo,
|
||||
supportCodesList,
|
||||
serviceTypesList,
|
||||
registerMethodsList,
|
||||
accidentsList,
|
||||
purposeOfVisitsList,
|
||||
proceduresList,
|
||||
assessmentsList,
|
||||
provincesList,
|
||||
citiesList,
|
||||
districtsList,
|
||||
classLevelsList,
|
||||
classLevelUpgradesList,
|
||||
classPaySourcesList,
|
||||
isServiceHidden,
|
||||
isSaveLoading,
|
||||
isLetterReadonly,
|
||||
isLoadingPatient,
|
||||
specialistsTree,
|
||||
handleSaveLetter,
|
||||
handleSavePatient,
|
||||
handleEvent,
|
||||
handleFetch,
|
||||
handleInit,
|
||||
getLetterMappers,
|
||||
patients,
|
||||
selectedPatient,
|
||||
selectedPatientObject,
|
||||
paginationMeta,
|
||||
getPatientsList,
|
||||
getPatientCurrent,
|
||||
getPatientByIdentifierSearch,
|
||||
} from '~/handlers/patient.handler'
|
||||
|
||||
const userStore = useUserStore()
|
||||
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 isLetterReadonly = ref(false)
|
||||
const isLoadingPatient = ref(false)
|
||||
const specialistsTree = ref<TreeItem[]>([])
|
||||
const resourceType = ref('')
|
||||
const resourcePath = 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: '',
|
||||
information: {
|
||||
facility: lettersRaw?.asalFaskes || '',
|
||||
diagnose: lettersRaw?.rujukan?.diagnosa?.kode || '',
|
||||
serviceType: lettersRaw?.rujukan?.pelayanan?.kode || '',
|
||||
classLevel: lettersRaw?.rujukan?.peserta?.hakKelas?.kode || '',
|
||||
poly: lettersRaw?.rujukan?.poliRujukan?.kode || '',
|
||||
cardNumber: lettersRaw?.rujukan?.peserta?.noKartu || '',
|
||||
identity: lettersRaw?.rujukan?.peserta?.nik || '',
|
||||
patientName: lettersRaw?.rujukan?.peserta?.nama || '',
|
||||
patientPhone: lettersRaw?.rujukan?.peserta?.mr?.noTelepon || '',
|
||||
medicalRecordNumber: lettersRaw?.rujukan?.peserta?.mr?.noMR || '',
|
||||
destination: lettersRaw?.rujukan?.provPerujuk?.kode || '',
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getPatientInternalMappers(id: string) {
|
||||
try {
|
||||
await getPatientCurrent(id)
|
||||
if (selectedPatientObject.value) {
|
||||
const patient = selectedPatientObject.value
|
||||
selectedObjects.value['cardNumber'] = '-'
|
||||
selectedObjects.value['nationalIdentity'] = patient?.person?.residentIdentityNumber || '-'
|
||||
selectedObjects.value['medicalRecordNumber'] = patient?.number || '-'
|
||||
selectedObjects.value['patientName'] = patient?.person?.name || '-'
|
||||
selectedObjects.value['phoneNumber'] = patient?.person?.contacts?.[0]?.value || '-'
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to load patient from query params:', err)
|
||||
}
|
||||
}
|
||||
|
||||
async function getPatientExternalMappers(id: string, type: string) {
|
||||
try {
|
||||
isLoadingPatient.value = true
|
||||
const result = await getMemberList({
|
||||
mode: type,
|
||||
number: id,
|
||||
date: new Date().toISOString().substring(0, 10),
|
||||
})
|
||||
if (result && result.success && result.body) {
|
||||
const memberRaws = result.body?.response || null
|
||||
selectedObjects.value['cardNumber'] = memberRaws?.peserta?.noKartu || ''
|
||||
selectedObjects.value['nationalIdentity'] = memberRaws?.peserta?.nik || ''
|
||||
selectedObjects.value['medicalRecordNumber'] = memberRaws?.peserta?.mr?.noMR || ''
|
||||
selectedObjects.value['patientName'] = memberRaws?.peserta?.nama || ''
|
||||
selectedObjects.value['phoneNumber'] = memberRaws?.peserta?.mr?.noTelepon || ''
|
||||
selectedObjects.value['classLevel'] = memberRaws?.peserta?.hakKelas?.kode || ''
|
||||
selectedObjects.value['status'] = memberRaws?.statusPeserta?.kode || ''
|
||||
}
|
||||
isLoadingPatient.value = false
|
||||
} catch (err) {
|
||||
console.error('Failed to load patient from query params:', err)
|
||||
isLoadingPatient.value = false
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map letter data to form fields for save-sep
|
||||
* Maps data from letters.value[0].information to selectedObjects and form values
|
||||
*/
|
||||
function mapLetterDataToForm(formValues: any): any {
|
||||
if (selectedAdmissionType.value === '3' || letters.value.length === 0) {
|
||||
return formValues
|
||||
}
|
||||
|
||||
const letterData = letters.value[0]
|
||||
const info = letterData.information || {}
|
||||
|
||||
// Map data to selectedObjects for form population
|
||||
if (info.cardNumber) {
|
||||
selectedObjects.value['cardNumber'] = info.cardNumber
|
||||
}
|
||||
if (info.medicalRecordNumber) {
|
||||
selectedObjects.value['medicalRecordNumber'] = info.medicalRecordNumber
|
||||
}
|
||||
if (info.patientPhone) {
|
||||
selectedObjects.value['phoneNumber'] = info.patientPhone
|
||||
}
|
||||
if (info.classLevel) {
|
||||
selectedObjects.value['classLevel'] = info.classLevel
|
||||
}
|
||||
|
||||
// Map data to formValues for makeSepData
|
||||
const mappedValues = { ...formValues }
|
||||
|
||||
// response.rujukan.peserta.noKartu → cardNumber (noKartu)
|
||||
if (info.cardNumber) {
|
||||
mappedValues.cardNumber = info.cardNumber
|
||||
}
|
||||
|
||||
// response.rujukan.tglKunjungan → referralLetterDate (rujukan.tglRujukan)
|
||||
if (letterData.plannedDate) {
|
||||
mappedValues.referralLetterDate = letterData.plannedDate
|
||||
}
|
||||
|
||||
// response.rujukan.noKunjungan → referralLetterNumber (rujukan.noRujukan)
|
||||
if (letterData.letterNumber) {
|
||||
mappedValues.referralLetterNumber = letterData.letterNumber
|
||||
}
|
||||
|
||||
// response.rujukan.provPerujuk.kode → fromClinic (rujukan.ppkRujukan)
|
||||
if (info.destination) {
|
||||
mappedValues.referralTo = info.destination
|
||||
}
|
||||
|
||||
// response.rujukan.poliRujukan.kode → polyCode
|
||||
if (info.poly) {
|
||||
mappedValues.polyCode = info.poly
|
||||
}
|
||||
|
||||
// response.asalFaskes → asalRujukan (1 = Faskes 1, 2 = Faskes RS)
|
||||
// Map facility to referralFrom (asalRujukan)
|
||||
if (info.facility) {
|
||||
mappedValues.referralFrom = info.facility
|
||||
}
|
||||
|
||||
// response.rujukan.diagnosa.kode → initialDiagnosis (diagAwal)
|
||||
if (info.diagnoses) {
|
||||
mappedValues.initialDiagnosis = info.diagnoses
|
||||
}
|
||||
|
||||
// response.rujukan.poliRujukan.kode → destinationClinic (poli.tujuan)
|
||||
if (info.poly) {
|
||||
mappedValues.destinationClinic = info.poly
|
||||
}
|
||||
|
||||
// response.rujukan.peserta.hakKelas.kode → classLevel (klsRawat.klsRawatHak)
|
||||
if (info.classLevel) {
|
||||
mappedValues.classLevel = info.classLevel
|
||||
}
|
||||
|
||||
// response.rujukan.peserta.mr.noMR → medicalRecordNumber (noMR)
|
||||
if (info.medicalRecordNumber) {
|
||||
mappedValues.medicalRecordNumber = info.medicalRecordNumber
|
||||
}
|
||||
|
||||
// response.rujukan.peserta.mr.noTelepon → phoneNumber (noTelp)
|
||||
if (info.patientPhone) {
|
||||
mappedValues.phoneNumber = info.patientPhone
|
||||
}
|
||||
|
||||
return mappedValues
|
||||
}
|
||||
|
||||
async function handleSavePatient() {
|
||||
selectedPatientObject.value = null
|
||||
await getPatientInternalMappers(selectedPatient.value)
|
||||
}
|
||||
|
||||
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 || '2',
|
||||
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-patient-by-identifier') {
|
||||
if (isLoadingPatient.value) return
|
||||
const text = value.text
|
||||
const type = value.type
|
||||
const prevCardNumber = selectedObjects.value['cardNumber'] || ''
|
||||
const prevNationalIdentity = selectedObjects.value['nationalIdentity'] || ''
|
||||
if (type === 'indentity' && text !== prevNationalIdentity) {
|
||||
await getPatientByIdentifierSearch(text)
|
||||
await getPatientExternalMappers(text, 'by-identity')
|
||||
}
|
||||
if (type === 'cardNumber' && text !== prevCardNumber) {
|
||||
await getPatientExternalMappers(text, 'by-card')
|
||||
}
|
||||
return
|
||||
}
|
||||
if (menu === 'search-letter') {
|
||||
isLetterReadonly.value = false
|
||||
getLetterMappers(value.admissionType, value.search).then(async () => {
|
||||
if (letters.value.length > 0) {
|
||||
const copyObjects = { ...selectedObjects.value }
|
||||
const letter = letters.value[0]
|
||||
selectedObjects.value = {}
|
||||
selectedLetter.value = letter.letterNumber
|
||||
isLetterReadonly.value = true
|
||||
if (letter.information || letter.clinic) {
|
||||
const poly = value.admissionType === '3' ? letter.clinic : letter.information?.poly
|
||||
if (poly) {
|
||||
const resultControl = await getControlLetterList({
|
||||
mode: 'by-schedule',
|
||||
controlDate: letter.plannedDate,
|
||||
controlType: selectedServiceType.value,
|
||||
polyCode: poly,
|
||||
})
|
||||
if (resultControl && resultControl.success && resultControl.body) {
|
||||
const resultData = resultControl.body?.response?.list || []
|
||||
const resultUnique = [...new Map(resultData.map((item: any) => [item.kodeDokter, item])).values()]
|
||||
const controlLetters = resultUnique.map((item: any) => ({
|
||||
value: item.kodeDokter ? String(item.kodeDokter) : '',
|
||||
label: `${item.kodeDokter} - ${item.namaDokter} - ${item.jadwalPraktek} (${item.kapasitas})`,
|
||||
}))
|
||||
doctors.value = controlLetters
|
||||
}
|
||||
}
|
||||
}
|
||||
setTimeout(async () => {
|
||||
selectedObjects.value = copyObjects
|
||||
selectedObjects.value['letterDate'] = letter.plannedDate
|
||||
selectedObjects.value['cardNumber'] = letter.information?.cardNumber || ''
|
||||
selectedObjects.value['nationalIdentity'] = letter.information?.identity || ''
|
||||
selectedObjects.value['medicalRecordNumber'] = letter.information?.medicalRecordNumber || ''
|
||||
selectedObjects.value['patientName'] = letter.information?.patientName || ''
|
||||
selectedObjects.value['phoneNumber'] = letter.information?.patientPhone || ''
|
||||
selectedObjects.value['facility'] = letter.information?.facility || ''
|
||||
selectedObjects.value['diagnose'] = letter.information?.diagnose || ''
|
||||
selectedObjects.value['serviceType'] = letter.information?.serviceType || ''
|
||||
selectedObjects.value['classLevel'] = letter.information?.classLevel || ''
|
||||
selectedObjects.value['poly'] = letter.information?.poly || ''
|
||||
selectedObjects.value['destination'] = letter.information?.destination || ''
|
||||
if (!!selectedObjects.value['diagnose']) {
|
||||
const diagnoseRes: any = await getDiagnoseLabelList({ diagnosa: selectedObjects.value['diagnose'] })
|
||||
diagnoses.value = diagnoseRes
|
||||
if (diagnoseRes && diagnoseRes.length > 0) {
|
||||
selectedObjects.value['diagnoseLabel'] = diagnoseRes[0].value
|
||||
}
|
||||
}
|
||||
}, 250)
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
if (menu === 'open-letter') {
|
||||
openLetter.value = true
|
||||
return
|
||||
}
|
||||
if (menu === 'history-sep') {
|
||||
getMonitoringHistoryMappers().then(() => {
|
||||
openHistory.value = true
|
||||
})
|
||||
return
|
||||
}
|
||||
if (menu === 'sep-number-changed') {
|
||||
// Update sepNumber when it changes in form (only if different to prevent loop)
|
||||
}
|
||||
if (menu === 'back') {
|
||||
navigateTo('/integration/bpjs/sep')
|
||||
}
|
||||
if (menu === 'save-sep') {
|
||||
isSaveLoading.value = true
|
||||
|
||||
// Map letter data to form if admissionType !== '3' and letters.value has data
|
||||
let mappedValues = value
|
||||
if (selectedAdmissionType.value !== '3') {
|
||||
if (letters.value.length > 0) {
|
||||
// Map data from letters.value to form values
|
||||
mappedValues = mapLetterDataToForm(value)
|
||||
} else {
|
||||
// Fallback: use getPatientExternalMappers if letters.value is empty
|
||||
// Get card number from form values or selectedObjects
|
||||
const cardNumberToSearch = value.cardNumber || selectedObjects.value['cardNumber'] || ''
|
||||
if (cardNumberToSearch && cardNumberToSearch !== '-') {
|
||||
await getPatientExternalMappers(cardNumberToSearch, 'by-card')
|
||||
// Update mappedValues with data from getPatientExternalMappers
|
||||
if (selectedObjects.value['cardNumber']) {
|
||||
mappedValues.cardNumber = selectedObjects.value['cardNumber']
|
||||
}
|
||||
if (selectedObjects.value['medicalRecordNumber']) {
|
||||
mappedValues.medicalRecordNumber = selectedObjects.value['medicalRecordNumber']
|
||||
}
|
||||
if (selectedObjects.value['phoneNumber']) {
|
||||
mappedValues.phoneNumber = selectedObjects.value['phoneNumber']
|
||||
}
|
||||
if (selectedObjects.value['classLevel']) {
|
||||
mappedValues.classLevel = selectedObjects.value['classLevel']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!value.destinationClinic) {
|
||||
mappedValues.destinationClinic = selectedObjects.value['destination'] || ''
|
||||
}
|
||||
if (!value.clinicExcecutive) {
|
||||
mappedValues.clinicExcecutive = 'no'
|
||||
}
|
||||
|
||||
mappedValues.userName = userStore.user?.user_name || ''
|
||||
|
||||
createSep(makeSepData(mappedValues))
|
||||
.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(resourcePath.value)
|
||||
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 || 2,
|
||||
})
|
||||
}
|
||||
if (menu === 'clinic-to') {
|
||||
facilitiesTo.value = await getHealthFacilityLabelList({
|
||||
healthcare: value,
|
||||
healthcareType: selectedServiceType.value || 2,
|
||||
})
|
||||
}
|
||||
if (menu === 'province') {
|
||||
citiesList.value = await getCityList({ province: value })
|
||||
districtsList.value = []
|
||||
}
|
||||
if (menu === 'city') {
|
||||
districtsList.value = await getDistrictList({ city: value })
|
||||
}
|
||||
}
|
||||
|
||||
async function handleFetchSpecialists() {
|
||||
try {
|
||||
const specialistsResult = await getSpecialistList({ 'page-size': 100, includes: 'subspecialists' })
|
||||
if (specialistsResult.success) {
|
||||
const specialists = specialistsResult.body?.data || []
|
||||
specialistsTree.value = getSpecialistTreeItems(specialists)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching specialist-subspecialist tree:', error)
|
||||
}
|
||||
}
|
||||
|
||||
async function handleInit() {
|
||||
selectedServiceType.value = '2'
|
||||
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 || '2',
|
||||
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
|
||||
await handleFetchSpecialists()
|
||||
if (route.query) {
|
||||
const queries = route.query as any
|
||||
isServiceHidden.value = queries['is-service'] === 'true'
|
||||
selectedObjects.value = {}
|
||||
if (queries['resource']) resourceType.value = queries['resource']
|
||||
if (queries['resource-path']) resourcePath.value = queries['resource-path']
|
||||
if (queries['doctor-code']) selectedObjects.value['doctorCode'] = queries['doctor-code']
|
||||
if (queries['specialist-code']) selectedObjects.value['subSpecialistCode'] = queries['specialist-code']
|
||||
if (queries['sub-specialist-code']) selectedObjects.value['subSpecialistCode'] = queries['sub-specialist-code']
|
||||
if (queries['card-number']) selectedObjects.value['cardNumber'] = queries['card-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['payment-type']) selectedObjects.value['paymentType'] = queries['payment-type']
|
||||
if (queries['patient-id']) {
|
||||
await getPatientInternalMappers(queries['patient-id'])
|
||||
}
|
||||
if (queries['card-number']) {
|
||||
const resultMember = await getMemberList({
|
||||
mode: 'by-card',
|
||||
number: queries['card-number'],
|
||||
date: new Date().toISOString().substring(0, 10),
|
||||
})
|
||||
console.log(resultMember)
|
||||
}
|
||||
delete selectedObjects.value['is-service']
|
||||
}
|
||||
}
|
||||
} = useIntegrationSepEntry()
|
||||
|
||||
onMounted(async () => {
|
||||
await handleInit()
|
||||
@@ -645,20 +62,44 @@ onMounted(async () => {
|
||||
|
||||
<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" />
|
||||
<Icon
|
||||
name="i-lucide-panel-bottom"
|
||||
class="me-2"
|
||||
/>
|
||||
<span class="font-semibold">Tambah</span>
|
||||
SEP
|
||||
</div>
|
||||
<AppSepEntryForm :is-save-loading="isSaveLoading" :is-service="isServiceHidden" :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" :specialists="specialistsTree" :objects="selectedObjects"
|
||||
@fetch="handleFetch" @event="handleEvent" />
|
||||
<AppViewPatient v-model:open="openPatient" v-model:selected="selectedPatient" :patients="patients"
|
||||
:pagination-meta="paginationMeta" @fetch="
|
||||
<AppSepEntryForm
|
||||
:is-save-loading="isSaveLoading"
|
||||
:is-service="isServiceHidden"
|
||||
: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"
|
||||
:specialists="specialistsTree"
|
||||
: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.)
|
||||
@@ -668,10 +109,20 @@ onMounted(async () => {
|
||||
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"
|
||||
"
|
||||
@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" />
|
||||
@fetch="(value) => getLetterMappers(value.admissionType, value.search)"
|
||||
@save="handleSaveLetter"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,692 @@
|
||||
import { ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
// Components
|
||||
import { toast } from '~/components/pub/ui/toast'
|
||||
|
||||
// Types
|
||||
import type { SepHistoryData } from '~/components/app/sep/list-cfg.history'
|
||||
import type { TreeItem } from '~/components/pub/my-ui/select-tree/type'
|
||||
|
||||
// Constants
|
||||
import {
|
||||
serviceTypes,
|
||||
serviceAssessments,
|
||||
registerMethods,
|
||||
trafficAccidents,
|
||||
supportCodes,
|
||||
procedureTypes,
|
||||
purposeOfVisits,
|
||||
classLevels,
|
||||
classLevelUpgrades,
|
||||
classPaySources,
|
||||
} from '~/lib/constants.vclaim'
|
||||
|
||||
// Services
|
||||
import {
|
||||
getList as getSpecialistList,
|
||||
getValueTreeItems as getSpecialistTreeItems,
|
||||
} from '~/services/specialist.service'
|
||||
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 getMemberList } from '~/services/vclaim-member.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'
|
||||
|
||||
export function useIntegrationSepEntry() {
|
||||
const userStore = useUserStore()
|
||||
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 isLetterReadonly = ref(false)
|
||||
const isLoadingPatient = ref(false)
|
||||
const specialistsTree = ref<TreeItem[]>([])
|
||||
const resourceType = ref('')
|
||||
const resourcePath = ref('')
|
||||
|
||||
/**
|
||||
* Map letter data to form fields for save-sep
|
||||
* Maps data from letters.value[0].information to selectedObjects and form values
|
||||
*/
|
||||
function mapLetterDataToForm(formValues: any): any {
|
||||
if (selectedAdmissionType.value === '3' || letters.value.length === 0) {
|
||||
return formValues
|
||||
}
|
||||
|
||||
const letterData = letters.value[0]
|
||||
const info = letterData.information || {}
|
||||
|
||||
// Map data to selectedObjects for form population
|
||||
if (info.cardNumber) {
|
||||
selectedObjects.value['cardNumber'] = info.cardNumber
|
||||
}
|
||||
if (info.medicalRecordNumber) {
|
||||
selectedObjects.value['medicalRecordNumber'] = info.medicalRecordNumber
|
||||
}
|
||||
if (info.patientPhone) {
|
||||
selectedObjects.value['phoneNumber'] = info.patientPhone
|
||||
}
|
||||
if (info.classLevel) {
|
||||
selectedObjects.value['classLevel'] = info.classLevel
|
||||
}
|
||||
|
||||
// Map data to formValues for makeSepData
|
||||
const mappedValues = { ...formValues }
|
||||
|
||||
// response.rujukan.peserta.noKartu → cardNumber (noKartu)
|
||||
if (info.cardNumber) {
|
||||
mappedValues.cardNumber = info.cardNumber
|
||||
}
|
||||
|
||||
// response.rujukan.tglKunjungan → referralLetterDate (rujukan.tglRujukan)
|
||||
if (letterData.plannedDate) {
|
||||
mappedValues.referralLetterDate = letterData.plannedDate
|
||||
}
|
||||
|
||||
// response.rujukan.noKunjungan → referralLetterNumber (rujukan.noRujukan)
|
||||
if (letterData.letterNumber) {
|
||||
mappedValues.referralLetterNumber = letterData.letterNumber
|
||||
}
|
||||
|
||||
// response.rujukan.provPerujuk.kode → fromClinic (rujukan.ppkRujukan)
|
||||
if (info.destination) {
|
||||
mappedValues.referralTo = info.destination
|
||||
}
|
||||
|
||||
// response.rujukan.poliRujukan.kode → polyCode
|
||||
if (info.poly) {
|
||||
mappedValues.polyCode = info.poly
|
||||
}
|
||||
|
||||
// response.asalFaskes → asalRujukan (1 = Faskes 1, 2 = Faskes RS)
|
||||
// Map facility to referralFrom (asalRujukan)
|
||||
if (info.facility) {
|
||||
mappedValues.referralFrom = info.facility
|
||||
}
|
||||
|
||||
// response.rujukan.diagnosa.kode → initialDiagnosis (diagAwal)
|
||||
if (info.diagnoses) {
|
||||
mappedValues.initialDiagnosis = info.diagnoses
|
||||
}
|
||||
|
||||
// response.rujukan.poliRujukan.kode → destinationClinic (poli.tujuan)
|
||||
if (info.poly) {
|
||||
mappedValues.destinationClinic = info.poly
|
||||
}
|
||||
|
||||
// response.rujukan.peserta.hakKelas.kode → classLevel (klsRawat.klsRawatHak)
|
||||
if (info.classLevel) {
|
||||
mappedValues.classLevel = info.classLevel
|
||||
}
|
||||
|
||||
// response.rujukan.peserta.mr.noMR → medicalRecordNumber (noMR)
|
||||
if (info.medicalRecordNumber) {
|
||||
mappedValues.medicalRecordNumber = info.medicalRecordNumber
|
||||
}
|
||||
|
||||
// response.rujukan.peserta.mr.noTelepon → phoneNumber (noTelp)
|
||||
if (info.patientPhone) {
|
||||
mappedValues.phoneNumber = info.patientPhone
|
||||
}
|
||||
|
||||
return mappedValues
|
||||
}
|
||||
|
||||
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: '',
|
||||
information: {
|
||||
facility: lettersRaw?.asalFaskes || '',
|
||||
diagnose: lettersRaw?.rujukan?.diagnosa?.kode || '',
|
||||
serviceType: lettersRaw?.rujukan?.pelayanan?.kode || '',
|
||||
classLevel: lettersRaw?.rujukan?.peserta?.hakKelas?.kode || '',
|
||||
poly: lettersRaw?.rujukan?.poliRujukan?.kode || '',
|
||||
cardNumber: lettersRaw?.rujukan?.peserta?.noKartu || '',
|
||||
identity: lettersRaw?.rujukan?.peserta?.nik || '',
|
||||
patientName: lettersRaw?.rujukan?.peserta?.nama || '',
|
||||
patientPhone: lettersRaw?.rujukan?.peserta?.mr?.noTelepon || '',
|
||||
medicalRecordNumber: lettersRaw?.rujukan?.peserta?.mr?.noMR || '',
|
||||
destination: lettersRaw?.rujukan?.provPerujuk?.kode || '',
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getPatientInternalMappers(id: string) {
|
||||
try {
|
||||
await getPatientCurrent(id)
|
||||
if (selectedPatientObject.value) {
|
||||
const patient = selectedPatientObject.value
|
||||
selectedObjects.value['cardNumber'] = '-'
|
||||
selectedObjects.value['nationalIdentity'] = patient?.person?.residentIdentityNumber || '-'
|
||||
selectedObjects.value['medicalRecordNumber'] = patient?.number || '-'
|
||||
selectedObjects.value['patientName'] = patient?.person?.name || '-'
|
||||
selectedObjects.value['phoneNumber'] = patient?.person?.contacts?.[0]?.value || '-'
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to load patient from query params:', err)
|
||||
}
|
||||
}
|
||||
|
||||
async function getPatientExternalMappers(id: string, type: string) {
|
||||
try {
|
||||
isLoadingPatient.value = true
|
||||
const result = await getMemberList({
|
||||
mode: type,
|
||||
number: id,
|
||||
date: new Date().toISOString().substring(0, 10),
|
||||
})
|
||||
if (result && result.success && result.body) {
|
||||
const memberRaws = result.body?.response || null
|
||||
selectedObjects.value['cardNumber'] = memberRaws?.peserta?.noKartu || ''
|
||||
selectedObjects.value['nationalIdentity'] = memberRaws?.peserta?.nik || ''
|
||||
selectedObjects.value['medicalRecordNumber'] = memberRaws?.peserta?.mr?.noMR || ''
|
||||
selectedObjects.value['patientName'] = memberRaws?.peserta?.nama || ''
|
||||
selectedObjects.value['phoneNumber'] = memberRaws?.peserta?.mr?.noTelepon || ''
|
||||
selectedObjects.value['classLevel'] = memberRaws?.peserta?.hakKelas?.kode || ''
|
||||
selectedObjects.value['status'] = memberRaws?.statusPeserta?.kode || ''
|
||||
}
|
||||
isLoadingPatient.value = false
|
||||
} catch (err) {
|
||||
console.error('Failed to load patient from query params:', err)
|
||||
isLoadingPatient.value = false
|
||||
}
|
||||
}
|
||||
|
||||
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 handleSavePatient() {
|
||||
selectedPatientObject.value = null
|
||||
await getPatientInternalMappers(selectedPatient.value)
|
||||
}
|
||||
|
||||
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 || '2',
|
||||
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-patient-by-identifier') {
|
||||
if (isLoadingPatient.value) return
|
||||
const text = value.text
|
||||
const type = value.type
|
||||
const prevCardNumber = selectedObjects.value['cardNumber'] || ''
|
||||
const prevNationalIdentity = selectedObjects.value['nationalIdentity'] || ''
|
||||
if (type === 'indentity' && text !== prevNationalIdentity) {
|
||||
await getPatientByIdentifierSearch(text)
|
||||
await getPatientExternalMappers(text, 'by-identity')
|
||||
}
|
||||
if (type === 'cardNumber' && text !== prevCardNumber) {
|
||||
await getPatientExternalMappers(text, 'by-card')
|
||||
}
|
||||
return
|
||||
}
|
||||
if (menu === 'search-letter') {
|
||||
isLetterReadonly.value = false
|
||||
getLetterMappers(value.admissionType, value.search).then(async () => {
|
||||
if (letters.value.length > 0) {
|
||||
const copyObjects = { ...selectedObjects.value }
|
||||
const letter = letters.value[0]
|
||||
selectedObjects.value = {}
|
||||
selectedLetter.value = letter.letterNumber
|
||||
isLetterReadonly.value = true
|
||||
if (letter.information || letter.clinic) {
|
||||
const poly = value.admissionType === '3' ? letter.clinic : letter.information?.poly
|
||||
if (poly) {
|
||||
const resultControl = await getControlLetterList({
|
||||
mode: 'by-schedule',
|
||||
controlDate: letter.plannedDate,
|
||||
controlType: selectedServiceType.value,
|
||||
polyCode: poly,
|
||||
})
|
||||
if (resultControl && resultControl.success && resultControl.body) {
|
||||
const resultData = resultControl.body?.response?.list || []
|
||||
const resultUnique = [...new Map(resultData.map((item: any) => [item.kodeDokter, item])).values()]
|
||||
const controlLetters = resultUnique.map((item: any) => ({
|
||||
value: item.kodeDokter ? String(item.kodeDokter) : '',
|
||||
label: `${item.kodeDokter} - ${item.namaDokter} - ${item.jadwalPraktek} (${item.kapasitas})`,
|
||||
}))
|
||||
doctors.value = controlLetters
|
||||
}
|
||||
}
|
||||
}
|
||||
setTimeout(async () => {
|
||||
selectedObjects.value = copyObjects
|
||||
selectedObjects.value['letterDate'] = letter.plannedDate
|
||||
selectedObjects.value['cardNumber'] = letter.information?.cardNumber || ''
|
||||
selectedObjects.value['nationalIdentity'] = letter.information?.identity || ''
|
||||
selectedObjects.value['medicalRecordNumber'] = letter.information?.medicalRecordNumber || ''
|
||||
selectedObjects.value['patientName'] = letter.information?.patientName || ''
|
||||
selectedObjects.value['phoneNumber'] = letter.information?.patientPhone || ''
|
||||
selectedObjects.value['facility'] = letter.information?.facility || ''
|
||||
selectedObjects.value['diagnose'] = letter.information?.diagnose || ''
|
||||
selectedObjects.value['serviceType'] = letter.information?.serviceType || ''
|
||||
selectedObjects.value['classLevel'] = letter.information?.classLevel || ''
|
||||
selectedObjects.value['poly'] = letter.information?.poly || ''
|
||||
selectedObjects.value['destination'] = letter.information?.destination || ''
|
||||
if (!!selectedObjects.value['diagnose']) {
|
||||
const diagnoseRes: any = await getDiagnoseLabelList({ diagnosa: selectedObjects.value['diagnose'] })
|
||||
diagnoses.value = diagnoseRes
|
||||
if (diagnoseRes && diagnoseRes.length > 0) {
|
||||
selectedObjects.value['diagnoseLabel'] = diagnoseRes[0].value
|
||||
}
|
||||
}
|
||||
}, 250)
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
if (menu === 'open-letter') {
|
||||
openLetter.value = true
|
||||
return
|
||||
}
|
||||
if (menu === 'history-sep') {
|
||||
getMonitoringHistoryMappers().then(() => {
|
||||
openHistory.value = true
|
||||
})
|
||||
return
|
||||
}
|
||||
if (menu === 'sep-number-changed') {
|
||||
// Update sepNumber when it changes in form (only if different to prevent loop)
|
||||
}
|
||||
if (menu === 'back') {
|
||||
navigateTo('/integration/bpjs/sep')
|
||||
}
|
||||
if (menu === 'save-sep') {
|
||||
isSaveLoading.value = true
|
||||
|
||||
// Map letter data to form if admissionType !== '3' and letters.value has data
|
||||
let mappedValues = value
|
||||
if (selectedAdmissionType.value !== '3') {
|
||||
if (letters.value.length > 0) {
|
||||
// Map data from letters.value to form values
|
||||
mappedValues = mapLetterDataToForm(value)
|
||||
} else {
|
||||
// Fallback: use getPatientExternalMappers if letters.value is empty
|
||||
// Get card number from form values or selectedObjects
|
||||
const cardNumberToSearch = value.cardNumber || selectedObjects.value['cardNumber'] || ''
|
||||
if (cardNumberToSearch && cardNumberToSearch !== '-') {
|
||||
await getPatientExternalMappers(cardNumberToSearch, 'by-card')
|
||||
// Update mappedValues with data from getPatientExternalMappers
|
||||
if (selectedObjects.value['cardNumber']) {
|
||||
mappedValues.cardNumber = selectedObjects.value['cardNumber']
|
||||
}
|
||||
if (selectedObjects.value['medicalRecordNumber']) {
|
||||
mappedValues.medicalRecordNumber = selectedObjects.value['medicalRecordNumber']
|
||||
}
|
||||
if (selectedObjects.value['phoneNumber']) {
|
||||
mappedValues.phoneNumber = selectedObjects.value['phoneNumber']
|
||||
}
|
||||
if (selectedObjects.value['classLevel']) {
|
||||
mappedValues.classLevel = selectedObjects.value['classLevel']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!value.destinationClinic) {
|
||||
mappedValues.destinationClinic = selectedObjects.value['destination'] || ''
|
||||
}
|
||||
if (!value.clinicExcecutive) {
|
||||
mappedValues.clinicExcecutive = 'no'
|
||||
}
|
||||
|
||||
mappedValues.userName = userStore.user?.user_name || ''
|
||||
|
||||
createSep(makeSepData(mappedValues))
|
||||
.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(resourcePath.value)
|
||||
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 || 2,
|
||||
})
|
||||
}
|
||||
if (menu === 'clinic-to') {
|
||||
facilitiesTo.value = await getHealthFacilityLabelList({
|
||||
healthcare: value,
|
||||
healthcareType: selectedServiceType.value || 2,
|
||||
})
|
||||
}
|
||||
if (menu === 'province') {
|
||||
citiesList.value = await getCityList({ province: value })
|
||||
districtsList.value = []
|
||||
}
|
||||
if (menu === 'city') {
|
||||
districtsList.value = await getDistrictList({ city: value })
|
||||
}
|
||||
}
|
||||
|
||||
async function handleFetchSpecialists() {
|
||||
try {
|
||||
const specialistsResult = await getSpecialistList({ 'page-size': 100, includes: 'subspecialists' })
|
||||
if (specialistsResult.success) {
|
||||
const specialists = specialistsResult.body?.data || []
|
||||
specialistsTree.value = getSpecialistTreeItems(specialists)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching specialist-subspecialist tree:', error)
|
||||
}
|
||||
}
|
||||
|
||||
async function handleInit() {
|
||||
selectedServiceType.value = '2'
|
||||
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 || '2',
|
||||
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
|
||||
await handleFetchSpecialists()
|
||||
if (route.query) {
|
||||
const queries = route.query as any
|
||||
isServiceHidden.value = queries['is-service'] === 'true'
|
||||
selectedObjects.value = {}
|
||||
if (queries['resource']) resourceType.value = queries['resource']
|
||||
if (queries['resource-path']) resourcePath.value = queries['resource-path']
|
||||
if (queries['doctor-code']) selectedObjects.value['doctorCode'] = queries['doctor-code']
|
||||
if (queries['specialist-code']) selectedObjects.value['subSpecialistCode'] = queries['specialist-code']
|
||||
if (queries['sub-specialist-code']) selectedObjects.value['subSpecialistCode'] = queries['sub-specialist-code']
|
||||
if (queries['card-number']) selectedObjects.value['cardNumber'] = queries['card-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['payment-type']) selectedObjects.value['paymentType'] = queries['payment-type']
|
||||
if (queries['patient-id']) {
|
||||
await getPatientInternalMappers(queries['patient-id'])
|
||||
}
|
||||
if (queries['card-number']) {
|
||||
const resultMember = await getMemberList({
|
||||
mode: 'by-card',
|
||||
number: queries['card-number'],
|
||||
date: new Date().toISOString().substring(0, 10),
|
||||
})
|
||||
console.log(resultMember)
|
||||
}
|
||||
delete selectedObjects.value['is-service']
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
openPatient,
|
||||
openLetter,
|
||||
openHistory,
|
||||
selectedLetter,
|
||||
selectedObjects,
|
||||
selectedServiceType,
|
||||
selectedAdmissionType,
|
||||
histories,
|
||||
letters,
|
||||
doctors,
|
||||
diagnoses,
|
||||
facilitiesFrom,
|
||||
facilitiesTo,
|
||||
supportCodesList,
|
||||
serviceTypesList,
|
||||
registerMethodsList,
|
||||
accidentsList,
|
||||
purposeOfVisitsList,
|
||||
proceduresList,
|
||||
assessmentsList,
|
||||
provincesList,
|
||||
citiesList,
|
||||
districtsList,
|
||||
classLevelsList,
|
||||
classLevelUpgradesList,
|
||||
classPaySourcesList,
|
||||
isServiceHidden,
|
||||
isSaveLoading,
|
||||
isLetterReadonly,
|
||||
isLoadingPatient,
|
||||
specialistsTree,
|
||||
resourceType,
|
||||
resourcePath,
|
||||
getMonitoringHistoryMappers,
|
||||
getLetterMappers,
|
||||
getPatientInternalMappers,
|
||||
getPatientExternalMappers,
|
||||
handleSaveLetter,
|
||||
mapLetterDataToForm,
|
||||
handleSavePatient,
|
||||
handleEvent,
|
||||
handleFetch,
|
||||
handleFetchSpecialists,
|
||||
handleInit,
|
||||
// Exported from patient.handler
|
||||
patients,
|
||||
selectedPatient,
|
||||
paginationMeta,
|
||||
getPatientsList,
|
||||
getPatientByIdentifierSearch,
|
||||
}
|
||||
}
|
||||
|
||||
export default useIntegrationSepEntry
|
||||
|
||||
@@ -33,7 +33,7 @@ useHead({
|
||||
|
||||
<template>
|
||||
<div v-if="canRead">
|
||||
<Content class-code="ambulatory" sub-class-code="reg" />
|
||||
<Content class-code="ambulatory" sub-class-code="chemo" />
|
||||
</div>
|
||||
<Error v-else :status-code="403" />
|
||||
</template>
|
||||
|
||||
@@ -40,7 +40,7 @@ const canCreate = hasCreateAccess(roleAccess)
|
||||
<Content
|
||||
:id="0"
|
||||
class-code="ambulatory"
|
||||
sub-class-code="reg"
|
||||
sub-class-code="chemo"
|
||||
form-type="Tambah"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -30,14 +30,6 @@ const route = useRoute()
|
||||
useHead({
|
||||
title: () => route.meta.title as string,
|
||||
})
|
||||
|
||||
const { user, getActiveRole } = useUserStore()
|
||||
// const activeRole = getActiveRole()
|
||||
// const activeRoleParts = activeRole ? activeRole.split('|') : ['', '']
|
||||
// const activeRolePos = activeRoleParts[0] // reaching this page means it is already set
|
||||
// const activeRoleType = activeRoleParts[1] == 'rehab' ? activeRoleParts[1] : ''
|
||||
const subClassCode = user.unit_code == 'rehab' ? 'rehab' : 'reg'
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -45,7 +37,7 @@ const subClassCode = user.unit_code == 'rehab' ? 'rehab' : 'reg'
|
||||
<div v-if="canRead">
|
||||
<Content
|
||||
class-code="ambulatory"
|
||||
:sub-class-code="subClassCode"
|
||||
sub-class-code="chemo"
|
||||
type="encounter"
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user