Files
simrsx-fe/app/components/content/sep/entry.vue
T
2025-10-20 14:14:17 +07:00

282 lines
8.9 KiB
Vue

<script setup lang="ts">
import { ref, onMounted } from 'vue'
// Components
import AppViewHistory from '~/components/app/sep/view-history.vue'
// Types
import type { PaginationMeta } from '~/components/pub/my-ui/pagination/pagination.type'
import type { PatientEntity } from '~/models/patient'
import type { SepHistoryData } from '~/components/app/sep/list-cfg.history'
import type { SepVisitData } from '~/components/app/sep/list-cfg.visit'
// Services
import { getPatientDetail, getPatients } from '~/services/patient.service'
import { getList as getProvinceList } from '~/services/vclaim-region-province.service'
import { getList as getCityList } from '~/services/vclaim-region-city.service'
import { getList as getDistrictList } from '~/services/vclaim-region-district.service'
import { getValueLabelList as getDoctorLabelList } from '~/services/vclaim-doctor.service'
import { getValueLabelList as getHealthFacilityLabelList } from '~/services/vclaim-health-facility.service'
import { getList as getDiagnoseReferralList } from '~/services/vclaim-diagnose-referral.service'
import { getList as geMonitoringVisitList } from '~/services/vclaim-monitoring-visit.service'
import { getList as getMonitoringHistoryList } from '~/services/vclaim-monitoring-history.service'
const openPatient = ref(false)
const openLetter = ref(false)
const openHistory = ref(false)
const selectedPatient = ref('')
const selectedPatientObject = ref<PatientEntity | null>(null)
const selectedLetter = ref('SK22334442')
const histories = ref<Array<SepHistoryData>>([])
const visits = ref<Array<SepVisitData>>([])
const patients = ref<Array<{ id: string; identity: string; number: string; bpjs: string; name: string }>>([])
const doctors = ref<Array<{ value: string | number; label: string }>>([])
const facilities = ref<Array<{ value: string | number; label: string }>>([])
const isPatientsLoading = ref(false)
const paginationMeta = ref<PaginationMeta>({
recordCount: 0,
page: 1,
pageSize: 10,
totalPage: 5,
hasNext: false,
hasPrev: false,
})
function mapPatientToRow(patient: PatientEntity) {
// Defensive mapping: try common field names that might be returned by the API
const identity = patient?.person?.residentIdentityNumber || '-'
const number = patient?.number || '-'
const bpjs = '-'
const name = patient?.person?.name || '-'
return { id: patient.id ? String(patient.id) : '-', identity, number, bpjs, name }
}
function mapPaginationMetaToRow(meta: any) {
const recordCount = meta['record_totalCount'] ? Number(meta['record_totalCount']) : 0
const currentCount = meta['record_currentCount'] ? Number(meta['record_currentCount']) : 0
const page = meta['page_number'] ? Number(meta['page_number']) : 1
const pageSize = meta['page_size'] ? Number(meta['page_size']) : 10
const totalPage = Math.ceil(recordCount / pageSize)
return {
recordCount,
page,
pageSize,
totalPage,
hasNext: currentCount < recordCount && page < totalPage,
hasPrev: page > 1,
}
}
async function getPatientsList(params: any = { 'page-size': 10 }) {
try {
isPatientsLoading.value = true
patients.value = []
paginationMeta.value = {} as PaginationMeta
const result = await getPatients(params)
if (result && result.success && result.body && Array.isArray(result.body.data)) {
const meta = result.body.meta
patients.value = result.body.data.map(mapPatientToRow)
paginationMeta.value = mapPaginationMetaToRow(meta)
} else {
patients.value = [] // fallback to empty array
}
} catch (err) {
console.error('Failed to fetch patients for SEP search:', err)
patients.value = []
} finally {
isPatientsLoading.value = false
}
}
async function getPatientCurrent(id: string) {
try {
const result = await getPatientDetail(Number(id))
if (result && result.success && result.body && result.body.data) {
const patient = result.body.data || null
selectedPatientObject.value = patient
}
} catch (err) {
console.error('Failed to fetch patient:', err)
}
}
async function getMonitoringHistoryMappers() {
histories.value = []
const dateFirst = new Date()
const dateLast = new Date()
dateLast.setMonth(dateFirst.getMonth() - 3)
const result = await getMonitoringHistoryList({
nop: '0002078925513',
tglawal: dateFirst.toISOString().substring(0, 10),
tglakhir: 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 getMonitoringVisitMappers() {
visits.value = []
const dateFirst = new Date()
const result = await geMonitoringVisitList({
nop: '0002078925513',
tglpelayanan: dateFirst.toISOString().substring(0, 10),
jnspelayanan: 1,
})
if (result && result.success && result.body) {
const visitsRaw = result.body?.response?.visit || []
if (!visitsRaw) return
visitsRaw.forEach((result: any) => {
visits.value.push({
letterNumber: result.noSuratKontrol,
letterDate: result.tglRencanaKontrol,
sepNumber: result.noSep,
patientName: result.namaPasien,
bpjsNumber: result.noKartuBPJS,
clinic: '-',
doctor: '-',
})
})
}
}
const letters = [
{
noSurat: 'SK22334442',
tglRencana: '12 Agustus 2025',
noSep: 'SEP3232332',
namaPasien: 'Ahmad Baidowi',
noBpjs: '33442331214',
klinik: 'Penyakit Dalam',
dokter: 'dr. Andi Prasetyo, Sp.PD-KHOM',
},
{
noSurat: 'SK99120039',
tglRencana: '12 Agustus 2025',
noSep: 'SEP4443232',
namaPasien: 'Bian Maulana',
noBpjs: '33442367656',
klinik: 'Gigi',
dokter: 'dr. Achmad Suparjo',
},
]
function handleSavePatient() {
selectedPatientObject.value = null
setTimeout(() => {
getPatientCurrent(selectedPatient.value)
}, 150)
}
function handleSaveLetter() {
console.log('Letter dipilih:', selectedLetter.value)
}
function handleEvent(menu: string, value: string) {
if (menu === 'admission-type') {
console.log('service-type:', value)
return
}
if (menu === 'search-patient') {
// fetch patients from API then open the dialog
getPatientsList({ 'page-size': 10, includes: 'person' }).then(() => {
openPatient.value = true
})
return
}
if (menu === 'search-letter') {
openLetter.value = true
return
}
if (menu === 'history-sep') {
// fetch history sep from API then open the dialog
getMonitoringHistoryMappers().then((value) => {
console.log('value:', value)
})
openHistory.value = true
return
}
if (menu === 'back') {
navigateTo('/bpjs/sep')
}
}
onMounted(async () => {
doctors.value = await getDoctorLabelList({
'jenis-pelayanan': 1,
'tgl-pelayanan': new Date().toISOString().substring(0, 10),
'kode-spesialis': 0,
})
facilities.value = await getHealthFacilityLabelList({ faskes: 'Puskesmas', 'jenis-faskes': 1 })
getProvinceList().then((value) => {
console.log('value:', value)
})
getCityList({ province: '14' }).then((value) => {
console.log('value:', value)
})
getDistrictList({ city: '0187' }).then((value) => {
console.log('value:', value)
})
getDiagnoseReferralList().then((value) => {
console.log('value:', value)
})
geMonitoringVisitList({ tglpelayanan: '2025-10-10', jnspelayanan: 1 }).then((value) => {
console.log('value:', value)
})
getMonitoringHistoryList({ nop: '0002078925513', tglawal: '2025-07-20', tglakhir: '2025-10-10' }).then((value) => {
console.log('value:', value)
})
})
</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"
:facilities="facilities"
:patient="selectedPatientObject"
@event="handleEvent"
/>
<AppSepTableSearchPatient
v-model:open="openPatient"
v-model:selected="selectedPatient"
:patients="patients"
:pagination-meta="paginationMeta"
@fetch="(value) => getPatientsList({ ...value, 'page-size': 10, includes: 'person' })"
@save="handleSavePatient"
/>
<AppSepTableSearchLetter
v-model:open="openLetter"
v-model:selected="selectedLetter"
:letters="letters"
@save="handleSaveLetter"
/>
<AppViewHistory
v-model:open="openHistory"
:histories="histories"
/>
</template>