import { ref, reactive } from 'vue' // Components import { toast } from '~/components/pub/ui/toast' // Types import type { Ref as VueRef } from 'vue' import type { DateRange } from 'radix-vue' import type { DataTableLoader } from '~/components/pub/my-ui/data-table/type' import type { HeaderPrep, RefSearchNav } from '~/components/pub/my-ui/data/types' import type { PaginationMeta } from '~/components/pub/my-ui/pagination/pagination.type' import type { VclaimSepData } from '~/models/vclaim' // Libraries import { CalendarDate, getLocalTimeZone } from '@internationalized/date' import { getFormatDateId } from '~/lib/date' import { downloadCsv, downloadXls } from '~/lib/download' import { serviceTypes } from '~/lib/constants.vclaim' import { getList as geMonitoringVisitList } from '~/services/vclaim-monitoring-visit.service' import { remove as removeSepData, removeOld as removeSepDataOld, makeSepDataForRemove } from '~/services/vclaim-sep.service' const headerKeys = [ 'letterDate', 'letterNumber', 'serviceType', 'flow', 'medicalRecordNumber', 'patientName', 'cardNumber', 'controlLetterNumber', 'controlLetterDate', 'clinicDestination', 'attendingDoctor', 'diagnosis', 'careClass', ] const headerLabels = [ 'Tanggal SEP', 'No. SEP', 'Jenis Pelayanan', 'Alur', 'No. Rekam Medis', 'Nama Pasien', 'No. Kartu BPJS', 'No. Surat Kontrol', 'Tgl Surat Kontrol', 'Poli Tujuan', 'Dokter Penanggung Jawab', 'Diagnosa', 'Kelas Perawatan', ] export function useIntegrationSepList() { const userStore = useUserStore() const today = new Date() const initCalDate = (d: Date) => new CalendarDate(d.getFullYear(), d.getMonth() + 1, d.getDate()) const recId = ref(0) const recAction = ref('') const recItem = ref(null) const data = ref([]) const dateSelection = ref({ start: initCalDate(today), end: initCalDate(today) }) as VueRef const dateRange = ref(`${getFormatDateId(today)} - ${getFormatDateId(today)}`) const serviceType = ref('2') const serviceTypesList = ref([]) const search = ref('') const open = ref(false) const sepData = ref({ sepNumber: '', cardNumber: '', patientName: '', }) const refSearchNav: RefSearchNav = { onClick: () => {}, onInput: (_val: string) => {}, onClear: () => {}, } const headerPrep: HeaderPrep = { title: 'Daftar SEP Prosedur', icon: 'i-lucide-panel-bottom', addNav: { label: 'Tambah', onClick: () => { navigateTo('/integration/bpjs-vclaim/sep/add') }, }, } const paginationMeta = reactive({ recordCount: 0, page: 1, pageSize: 10, totalPage: 5, hasNext: false, hasPrev: false, }) const isLoading = reactive({ isTableLoading: false, }) const getDateFilter = () => { let dateFilter = '' const isTimeLocal = true const dateFirst = dateSelection.value && dateSelection.value.start ? dateSelection.value.start.toDate(getLocalTimeZone()) : new Date() if (isTimeLocal && dateSelection.value && dateSelection.value.end) { const { year, month, day } = dateSelection.value.end dateFilter = `${year}-${month}-${day}` } else { dateFilter = dateFirst.toISOString().substring(0, 10) } return dateFilter } const getMonitoringVisitMappers = async () => { isLoading.dataListLoading = true data.value = [] const dateFilter = getDateFilter() const result = await geMonitoringVisitList({ date: dateFilter || '', serviceType: serviceType.value, }) if (result && result.success && result.body) { const visitsRaw = result.body?.response?.sep || [] if (!visitsRaw) { isLoading.dataListLoading = false return } visitsRaw.forEach((result: any) => { let st = result.jnsPelayanan || '-' if (st === 'R.Inap') st = 'Rawat Inap' else if (st === '1' || st === 'R.Jalan') st = 'Rawat Jalan' data.value.push({ letterDate: result.tglSep || '-', letterNumber: result.noSep || '-', serviceType: st, flow: '-', medicalRecordNumber: '-', patientName: result.nama || '-', cardNumber: result.noKartu || '-', controlLetterNumber: result.noRujukan || '-', controlLetterDate: result.tglPlgSep || '-', clinicDestination: result.poli || '-', attendingDoctor: '-', diagnosis: result.diagnosa || '-', careClass: result.kelasRawat || '-', }) }) } isLoading.dataListLoading = false } const getSepList = async () => { await getMonitoringVisitMappers() } const setServiceTypes = () => { serviceTypesList.value = Object.keys(serviceTypes).map((item) => ({ value: item.toString(), label: serviceTypes[item], })) as any } const setDateRange = () => { const startCal = dateSelection.value.start const endCal = dateSelection.value.end const s = startCal ? startCal.toDate(getLocalTimeZone()) : today const e = endCal ? endCal.toDate(getLocalTimeZone()) : today dateRange.value = `${getFormatDateId(s)} - ${getFormatDateId(e)}` } const handleExportCsv = () => { if (!data.value || data.value.length === 0) { toast({ title: 'Kosong', description: 'Tidak ada data untuk diekspor', variant: 'destructive' }) return } const yyyy = today.getFullYear() const mm = String(today.getMonth() + 1).padStart(2, '0') const dd = String(today.getDate()).padStart(2, '0') const dateStr = `${yyyy}-${mm}-${dd}` const filename = `file-sep-${dateStr}.csv` downloadCsv(headerKeys, headerLabels, data.value, filename, ',', true) } const handleExportExcel = async () => { if (!data.value || data.value.length === 0) { toast({ title: 'Kosong', description: 'Tidak ada data untuk diekspor', variant: 'destructive' }) return } const yyyy = today.getFullYear() const mm = String(today.getMonth() + 1).padStart(2, '0') const dd = String(today.getDate()).padStart(2, '0') const dateStr = `${yyyy}-${mm}-${dd}` const filename = `file-sep-${dateStr}.xlsx` try { await downloadXls(headerKeys, headerLabels, data.value, filename, 'SEP Data') } catch (err: any) { console.error('exportExcel error', err) toast({ title: 'Gagal', description: err?.message || 'Gagal mengekspor data ke Excel', variant: 'destructive' }) } } const handleRowSelected = (row: any) => { if (!row) return sepData.value.sepNumber = row.letterNumber || '' sepData.value.cardNumber = row.cardNumber || '' sepData.value.patientName = row.patientName || '' recItem.value = row recId.value = (row && (row.id || row.recId)) || 0 } const handlePageChange = (page: number) => { console.log('pageChange', page) } const handleRemove = async () => { const isNew = true; try { const result = !isNew ? await removeSepDataOld( makeSepDataForRemove({ ...sepData.value, userName: userStore.user?.user_name }), ) : await removeSepData(sepData.value.sepNumber || '') const backendMessage = result?.body?.message || result?.message || null const backendStatus = result?.body?.status || result?.status || null if ( backendMessage === 'success' || (backendStatus === 'error' && backendMessage === 'Decrypt failed: illegal base64 data at input byte 16') ) { await getSepList() toast({ title: 'Berhasil', description: backendMessage || 'Data berhasil dihapus', variant: 'default' }) } else { toast({ title: 'Gagal', description: backendMessage || 'Gagal menghapus data', variant: 'destructive' }) } } catch (err: any) { console.error('handleRemove error', err) toast({ title: 'Gagal', description: err?.message || 'Terjadi kesalahan saat menghapus data', variant: 'destructive', }) } finally { recId.value = 0 recAction.value = '' open.value = false } } return { recId, recAction, recItem, data, dateSelection, dateRange, serviceType, serviceTypesList, search, open, sepData, headerPrep, refSearchNav, paginationMeta, isLoading, getSepList, setServiceTypes, setDateRange, handleExportCsv, handleExportExcel, handleRowSelected, handlePageChange, handleRemove, } }