diff --git a/app/components/pub/my-ui/data-table/data-table.vue b/app/components/pub/my-ui/data-table/data-table.vue
index 9d88ffee..431df276 100644
--- a/app/components/pub/my-ui/data-table/data-table.vue
+++ b/app/components/pub/my-ui/data-table/data-table.vue
@@ -1,5 +1,5 @@
+
+
+
+
+
+
diff --git a/app/components/pub/my-ui/data/types.ts b/app/components/pub/my-ui/data/types.ts
index c86e1752..f949d1e5 100644
--- a/app/components/pub/my-ui/data/types.ts
+++ b/app/components/pub/my-ui/data/types.ts
@@ -8,6 +8,7 @@ export interface ListItemDto {
}
export type ComponentType = Component
+export type ComponentWithProps = { component: Component, props: Record }
export interface ButtonNav {
variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link'
@@ -41,17 +42,23 @@ export interface RefSearchNav {
onClear: () => void
}
+export interface RefExportNav {
+ onExportPdf?: () => void
+ onExportCsv?: () => void
+ onExportExcel?: () => void
+}
+
// prepared header for relatively common usage
export interface HeaderPrep {
title?: string
icon?: string
+ components?: ComponentWithProps[]
refSearchNav?: RefSearchNav
quickSearchNav?: QuickSearchNav
filterNav?: ButtonNav
addNav?: ButtonNav
printNav?: ButtonNav
}
-
export interface KeyLabel {
key: string
label: string
diff --git a/app/components/pub/my-ui/nav-footer/ba-dr-su.vue b/app/components/pub/my-ui/nav-footer/ba-dr-su.vue
index e38e12fa..a84c8edb 100644
--- a/app/components/pub/my-ui/nav-footer/ba-dr-su.vue
+++ b/app/components/pub/my-ui/nav-footer/ba-dr-su.vue
@@ -6,6 +6,7 @@ const props = defineProps<{
class?: string
}>()
+const enableDraft = props.enableDraft ?? true
const defaultClass = props.defaultClass ?? 'm-2 flex gap-2 px-2'
const additionalClass = props.class ?? ''
const btnClass = props.smallMode ? '[&_button]:w-7 [&_button]:h-7 [&_button]:2xl:w-8 [&_button]:2xl:h-9 [&_button]:!p-0' : ''
diff --git a/app/components/pub/my-ui/nav-footer/ba.vue b/app/components/pub/my-ui/nav-footer/ba.vue
new file mode 100644
index 00000000..2b8e7767
--- /dev/null
+++ b/app/components/pub/my-ui/nav-footer/ba.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
diff --git a/app/components/pub/my-ui/nav-footer/ok.vue b/app/components/pub/my-ui/nav-footer/ok.vue
new file mode 100644
index 00000000..da2f69ea
--- /dev/null
+++ b/app/components/pub/my-ui/nav-footer/ok.vue
@@ -0,0 +1,32 @@
+
+
+
+
+
diff --git a/app/components/pub/my-ui/nav-header/filter-dialog.vue b/app/components/pub/my-ui/nav-header/filter-dialog.vue
new file mode 100644
index 00000000..c0d5b854
--- /dev/null
+++ b/app/components/pub/my-ui/nav-header/filter-dialog.vue
@@ -0,0 +1,85 @@
+
+
+
+
+
diff --git a/app/components/pub/my-ui/nav-header/filter.vue b/app/components/pub/my-ui/nav-header/filter.vue
index 01b1ab55..74f6d8dc 100644
--- a/app/components/pub/my-ui/nav-header/filter.vue
+++ b/app/components/pub/my-ui/nav-header/filter.vue
@@ -5,11 +5,13 @@ import type { Ref } from 'vue'
import type { DateRange } from 'radix-vue'
import { CalendarDate, DateFormatter, getLocalTimeZone } from '@internationalized/date'
import { cn } from '~/lib/utils'
-import type { HeaderPrep, RefSearchNav } from '~/components/pub/my-ui/data/types'
+import type { HeaderPrep, RefExportNav, RefSearchNav } from '~/components/pub/my-ui/data/types'
const props = defineProps<{
prep: HeaderPrep
refSearchNav?: RefSearchNav
+ enableExport?: boolean
+ refExportNav?: RefExportNav
}>()
// function emitSearchNavClick() {
@@ -34,9 +36,18 @@ const df = new DateFormatter('en-US', {
dateStyle: 'medium',
})
+// Get current date
+const today = new Date()
+const todayCalendar = new CalendarDate(today.getFullYear(), today.getMonth() + 1, today.getDate())
+
+// Get date 1 month ago
+const oneMonthAgo = new Date(today)
+oneMonthAgo.setMonth(today.getMonth() - 1)
+const oneMonthAgoCalendar = new CalendarDate(oneMonthAgo.getFullYear(), oneMonthAgo.getMonth() + 1, oneMonthAgo.getDate())
+
const value = ref({
- start: new CalendarDate(2022, 1, 20),
- end: new CalendarDate(2022, 1, 20).add({ days: 20 }),
+ start: oneMonthAgoCalendar,
+ end: todayCalendar,
}) as Ref
function onFilterClick() {
@@ -48,7 +59,7 @@ function onFilterClick() {
-
+
@@ -88,6 +99,30 @@ function onFilterClick() {
Filter
+
+
+
+
+
+
+
+ Ekspor PDF
+
+
+ Ekspor CSV
+
+
+ Ekspor Excel
+
+
+
+
diff --git a/app/components/pub/my-ui/nav-header/prep.vue b/app/components/pub/my-ui/nav-header/prep.vue
index 63535847..7aa5e4f2 100644
--- a/app/components/pub/my-ui/nav-header/prep.vue
+++ b/app/components/pub/my-ui/nav-header/prep.vue
@@ -30,15 +30,24 @@ function btnClick() {
- {{ props.prep.title }}
+ {{ prep.title }}
+
+
+
+
+
()
const emit = defineEmits<{
@@ -17,8 +21,10 @@ function handlePageChange(page: number) {
diff --git a/app/components/pub/my-ui/pagination/pagination.vue b/app/components/pub/my-ui/pagination/pagination.vue
index 4ba0da5f..9b1618c3 100644
--- a/app/components/pub/my-ui/pagination/pagination.vue
+++ b/app/components/pub/my-ui/pagination/pagination.vue
@@ -15,11 +15,13 @@ interface Props {
paginationMeta: PaginationMeta
onPageChange?: (page: number) => void
showInfo?: boolean
+ showControl?: boolean
}
const props = withDefaults(defineProps
(), {
onPageChange: undefined,
showInfo: true,
+ showControl: true,
})
const emit = defineEmits<{
@@ -65,7 +67,7 @@ const formattedRecordCount = computed(() => {
})
const startRecord = computed(() => {
- const start = ((props.paginationMeta.page - 1) * props.paginationMeta.pageSize) + 1
+ const start = (props.paginationMeta.page - 1) * props.paginationMeta.pageSize + 1
return Number(start).toLocaleString('id-ID')
})
@@ -77,53 +79,95 @@ const endRecord = computed(() => {
function getButtonClass(pageNumber: number) {
const digits = pageNumber.toString().length
- if (digits >= 4) { // 1000+ (1k+)
+ if (digits >= 4) {
+ // 1000+ (1k+)
return 'h-9 px-4 min-w-12'
- } else if (digits === 3) { // 100-999
+ } else if (digits === 3) {
+ // 100-999
return 'h-9 px-3 min-w-10'
- } else { // 1-99
+ } else {
+ // 1-99
return 'w-9 h-9 p-0'
}
}
-
+
-
- Menampilkan {{ startRecord }}
- hingga {{ Number(endRecord).toLocaleString('id-ID') }}
- dari {{ formattedRecordCount }} data
+
+ Menampilkan {{ startRecord }} hingga {{ Number(endRecord).toLocaleString('id-ID') }} dari
+ {{ formattedRecordCount }} data
+
+
+ -
-
-
-
+
-
+
-
-
-
+ v-slot="{ page }"
+ :total="paginationMeta.recordCount"
+ :sibling-count="1"
+ :page="paginationMeta.page"
+ :items-per-page="paginationMeta.pageSize"
+ show-edges
+ >
+
+
+
-
-
+
-
-
+
+
diff --git a/app/components/pub/my-ui/toggle/provided-toggle.vue b/app/components/pub/my-ui/toggle/provided-toggle.vue
new file mode 100644
index 00000000..f028118c
--- /dev/null
+++ b/app/components/pub/my-ui/toggle/provided-toggle.vue
@@ -0,0 +1,34 @@
+
+
+
+ model = !model"
+ :variant="model ? 'default' : 'outline'"
+ >
+ {{ label }}
+
+
+
+
diff --git a/app/components/pub/ui/button/index.ts b/app/components/pub/ui/button/index.ts
index c4063089..43c75876 100644
--- a/app/components/pub/ui/button/index.ts
+++ b/app/components/pub/ui/button/index.ts
@@ -19,7 +19,7 @@ export const buttonVariants = cva(
link: 'text-primary underline-offset-4 hover:underline',
},
size: {
- default: 'md:h8 2xl:h-9 px-4 py-2',
+ default: 'md:h-8 2xl:h-9 px-4 py-2',
xs: 'h-7 rounded px-2',
sm: 'h-8 rounded-md px-3 text-xs',
lg: 'h-10 rounded-md px-8',
diff --git a/app/components/pub/ui/toggle/index.ts b/app/components/pub/ui/toggle/index.ts
index 07acae50..9486e903 100644
--- a/app/components/pub/ui/toggle/index.ts
+++ b/app/components/pub/ui/toggle/index.ts
@@ -4,16 +4,16 @@ import { cva } from 'class-variance-authority'
export { default as Toggle } from './Toggle.vue'
export const toggleVariants = cva(
- 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground',
+ 'inline-flex items-center justify-center rounded-md text-xs 2xl:text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground',
{
variants: {
variant: {
default: 'bg-transparent',
outline:
- 'border border-input bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground',
+ 'border border-slate-300 bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground',
},
size: {
- default: 'h-9 px-3',
+ default: 'md:h-8 2xl:h-9 px-3',
sm: 'h-8 px-2',
lg: 'h-10 px-3',
},
diff --git a/app/handlers/control-letter.handler.ts b/app/handlers/control-letter.handler.ts
new file mode 100644
index 00000000..b096a178
--- /dev/null
+++ b/app/handlers/control-letter.handler.ts
@@ -0,0 +1,24 @@
+// Handlers
+import { genCrudHandler } from '~/handlers/_handler'
+
+// Services
+import { create, update, remove } from '~/services/control-letter.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({
+ create,
+ update,
+ remove,
+})
diff --git a/app/handlers/installation-position.handler.ts b/app/handlers/installation-position.handler.ts
new file mode 100644
index 00000000..e3cfcf38
--- /dev/null
+++ b/app/handlers/installation-position.handler.ts
@@ -0,0 +1,24 @@
+// Handlers
+import { genCrudHandler } from '~/handlers/_handler'
+
+// Services
+import { create, update, remove } from '~/services/installation-position.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({
+ create,
+ update,
+ remove,
+})
diff --git a/app/handlers/mcu-order-item.handler.ts b/app/handlers/mcu-order-item.handler.ts
new file mode 100644
index 00000000..62e1861e
--- /dev/null
+++ b/app/handlers/mcu-order-item.handler.ts
@@ -0,0 +1,17 @@
+import { createCrudHandler, genCrudHandler } from '~/handlers/_handler'
+import { create, update, remove } from '~/services/prescription.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({ create, update, remove})
diff --git a/app/handlers/mcu-order.handler.ts b/app/handlers/mcu-order.handler.ts
new file mode 100644
index 00000000..4b114dfc
--- /dev/null
+++ b/app/handlers/mcu-order.handler.ts
@@ -0,0 +1,17 @@
+import { createCrudHandler, genCrudHandler } from '~/handlers/_handler'
+import { create, update, remove } from '~/services/mcu-order.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({ create, update, remove})
diff --git a/app/handlers/mcu-src-category.handler.ts b/app/handlers/mcu-src-category.handler.ts
new file mode 100644
index 00000000..8369666b
--- /dev/null
+++ b/app/handlers/mcu-src-category.handler.ts
@@ -0,0 +1,24 @@
+// Handlers
+import { genCrudHandler } from '~/handlers/_handler'
+
+// Services
+import { create, update, remove } from '~/services/mcu-src-category.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({
+ create,
+ update,
+ remove,
+})
diff --git a/app/handlers/patient.handler.ts b/app/handlers/patient.handler.ts
index f87eaf71..198b3a22 100644
--- a/app/handlers/patient.handler.ts
+++ b/app/handlers/patient.handler.ts
@@ -1,8 +1,128 @@
// Handlers
import { genCrudHandler } from '~/handlers/_handler'
+// Types
+import type { PatientEntity } from '~/models/patient'
+import type { PaginationMeta } from '~/components/pub/my-ui/pagination/pagination.type'
+
// Services
-import { postPatient as create, patchPatient as update, removePatient as remove } from '~/services/patient.service'
+import {
+ postPatient as create,
+ patchPatient as update,
+ removePatient as remove,
+ getPatientDetail,
+ getPatients,
+ getPatientByIdentifier,
+} from '~/services/patient.service'
+
+const isPatientsLoading = ref(false)
+const patients = ref
>([])
+const selectedPatient = ref('')
+const selectedPatientObject = ref(null)
+const paginationMeta = ref({
+ recordCount: 0,
+ page: 1,
+ pageSize: 10,
+ totalPage: 5,
+ hasNext: false,
+ hasPrev: false,
+})
+
+function mapPatientToRow(patient: PatientEntity) {
+ 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 getPatientByIdentifierSearch(search: string) {
+ try {
+ isPatientsLoading.value = true
+ patients.value = []
+ paginationMeta.value = {} as PaginationMeta
+ const result = await getPatientByIdentifier(search)
+ if (result && result.success && result.body) {
+ if (result.type === 'resident-identity' && result.body.data) {
+ patients.value = [mapPatientToRow(result.body.data)]
+ } else if (result.type === 'identity') {
+ patients.value = Array.isArray(result.body.data) ? result.body.data.map(mapPatientToRow) : result.body.data ? [mapPatientToRow(result.body.data)] : []
+ } else {
+ const meta = result.body.meta
+ patients.value = Array.isArray(result.body.data) ? result.body.data.map(mapPatientToRow) : result.body.data ? [mapPatientToRow(result.body.data)] : []
+ paginationMeta.value = mapPaginationMetaToRow(meta)
+ }
+ } else {
+ patients.value = [] // fallback to empty array
+ }
+ } catch (err) {
+ console.error('Failed to fetch patients by identifier:', err)
+ patients.value = []
+ } finally {
+ isPatientsLoading.value = false
+ }
+}
+
+export {
+ isPatientsLoading,
+ patients,
+ selectedPatient,
+ selectedPatientObject,
+ paginationMeta,
+ getPatientsList,
+ getPatientCurrent,
+ getPatientByIdentifierSearch,
+}
export const {
recId,
diff --git a/app/handlers/prescription-item.handler.ts b/app/handlers/prescription-item.handler.ts
new file mode 100644
index 00000000..70450970
--- /dev/null
+++ b/app/handlers/prescription-item.handler.ts
@@ -0,0 +1,17 @@
+import { createCrudHandler, genCrudHandler } from '~/handlers/_handler'
+import { create, update, remove } from '~/services/prescription-item.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({ create, update, remove})
diff --git a/app/handlers/prescription.handler.ts b/app/handlers/prescription.handler.ts
new file mode 100644
index 00000000..62e1861e
--- /dev/null
+++ b/app/handlers/prescription.handler.ts
@@ -0,0 +1,17 @@
+import { createCrudHandler, genCrudHandler } from '~/handlers/_handler'
+import { create, update, remove } from '~/services/prescription.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({ create, update, remove})
diff --git a/app/handlers/specialist-position.handler.ts b/app/handlers/specialist-position.handler.ts
new file mode 100644
index 00000000..859070ba
--- /dev/null
+++ b/app/handlers/specialist-position.handler.ts
@@ -0,0 +1,24 @@
+// Handlers
+import { genCrudHandler } from '~/handlers/_handler'
+
+// Services
+import { create, update, remove } from '~/services/specialist-position.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({
+ create,
+ update,
+ remove,
+})
diff --git a/app/handlers/subspecialist-position.handler.ts b/app/handlers/subspecialist-position.handler.ts
new file mode 100644
index 00000000..42473f86
--- /dev/null
+++ b/app/handlers/subspecialist-position.handler.ts
@@ -0,0 +1,24 @@
+// Handlers
+import { genCrudHandler } from '~/handlers/_handler'
+
+// Services
+import { create, update, remove } from '~/services/subspecialist-position.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({
+ create,
+ update,
+ remove,
+})
diff --git a/app/handlers/unit-position.handler.ts b/app/handlers/unit-position.handler.ts
new file mode 100644
index 00000000..1cf4994b
--- /dev/null
+++ b/app/handlers/unit-position.handler.ts
@@ -0,0 +1,24 @@
+// Handlers
+import { genCrudHandler } from '~/handlers/_handler'
+
+// Services
+import { create, update, remove } from '~/services/unit-position.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({
+ create,
+ update,
+ remove,
+})
diff --git a/app/lib/constants.vclaim.ts b/app/lib/constants.vclaim.ts
new file mode 100644
index 00000000..84fe5d52
--- /dev/null
+++ b/app/lib/constants.vclaim.ts
@@ -0,0 +1,94 @@
+export const serviceTypes: Record = {
+ '1': 'Rawat Inap',
+ '2': 'Rawat Jalan',
+}
+
+export const registerMethods: Record = {
+ '1': 'Rujukan',
+ '2': 'IGD',
+ '3': 'Kontrol',
+ '4': 'Rujukan Internal',
+}
+
+export const classLevels: Record = {
+ '1': 'Kelas 1',
+ '2': 'Kelas 2',
+ '3': 'Kelas 3',
+}
+
+export const classLevelUpgrades: Record = {
+ '1': 'VVIP',
+ '2': 'VIP',
+ '3': 'Kelas 1',
+ '4': 'Kelas 2',
+ '5': 'Kelas 3',
+ '6': 'ICCU',
+ '7': 'ICU',
+ '8': 'Diatas Kelas 1',
+}
+
+export const classPaySources: Record = {
+ '1': 'Pribadi',
+ '2': 'Pemberi Kerja',
+ '3': 'Asuransi Kesehatan Tambahan',
+}
+
+export const procedureTypes: Record = {
+ '0': 'Prosedur tidak berkelanjutan',
+ '1': 'Prosedur dan terapi berkelanjutan',
+}
+
+export const purposeOfVisits: Record = {
+ '0': 'Normal',
+ '1': 'Prosedur',
+ '2': 'Konsul Dokter',
+}
+
+export const trafficAccidents: Record = {
+ '0': 'Bukan Kecelakaan lalu lintas [BKLL]',
+ '1': 'KLL dan Bukan Kecelakaan Kerja [BKK]',
+ '2': 'KLL dan KK',
+ '3': 'KK',
+}
+
+export const supportCodes: Record = {
+ '1': 'Radioterapi',
+ '2': 'Kemoterapi',
+ '3': 'Rehabilitasi Medik',
+ '4': 'Rehabilitasi Psikososial',
+ '5': 'Transfusi Darah',
+ '6': 'Pelayanan Gigi',
+ '7': 'Laboratorium',
+ '8': 'USG',
+ '9': 'Farmasi',
+ '10': 'Lain-Lain',
+ '11': 'MRI',
+ '12': 'HEMODIALISA',
+}
+
+export const serviceAssessments: Record = {
+ '1': 'Poli spesialis tidak tersedia pada hari sebelumnya',
+ '2': 'Jam Poli telah berakhir pada hari sebelumnya',
+ '3': 'Dokter Spesialis yang dimaksud tidak praktek pada hari sebelumnya',
+ '4': 'Atas Instruksi RS',
+ '5': 'Tujuan Kontrol',
+}
+
+export const paymentTypes: Record = {
+ jkn: 'JKN (Jaminan Kesehatan Nasional)',
+ jkmm: 'JKMM (Jaminan Kesehatan Mandiri)',
+ spm: 'SPM (Sistem Pembayaran Mandiri)',
+ pks: 'PKS (Pembiayaan Kesehatan Sosial)',
+}
+
+export const sepRefTypeCodes: Record = {
+ internal: 'Rujukan Internal',
+ external: 'Faskes Lain',
+}
+
+export const participantGroups: Record = {
+ pbi: 'PBI (Penerima Bantuan Iuran)',
+ ppu: 'PPU (Pekerja Penerima Upah)',
+ pbu: 'PBU (Pekerja Bukan Penerima Upah)',
+ bp: 'BP (Bukan Pekerja)',
+}
\ No newline at end of file
diff --git a/app/lib/date.ts b/app/lib/date.ts
index 502a6cfb..2c7b92cf 100644
--- a/app/lib/date.ts
+++ b/app/lib/date.ts
@@ -41,4 +41,12 @@ export function getAge(dateString: string, comparedDate?: string): { idFormat: s
idFormat,
extFormat
};
+}
+
+export function formatDateYyyyMmDd(isoDateString: string): string {
+ const date = new Date(isoDateString);
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, '0');
+ const day = String(date.getDate()).padStart(2, '0');
+ return `${year}-${month}-${day}`;
}
\ No newline at end of file
diff --git a/app/lib/page-permission.ts b/app/lib/page-permission.ts
index c527a8cc..ab7b5550 100644
--- a/app/lib/page-permission.ts
+++ b/app/lib/page-permission.ts
@@ -2,43 +2,67 @@ import type { RoleAccess } from '~/models/role'
export const PAGE_PERMISSIONS = {
'/patient': {
- doctor: ['R'],
- nurse: ['R'],
- admisi: ['C', 'R', 'U', 'D'],
- pharmacy: ['R'],
- billing: ['R'],
- management: ['R'],
+ 'emp|doc': ['R'],
+ 'emp|nur': ['R'],
+ 'emp|reg': ['C', 'R', 'U', 'D'],
+ 'emp|pha': ['R'],
+ 'emp|pay': ['R'],
+ 'emp|mng': ['R'],
},
'/doctor': {
- doctor: ['C', 'R', 'U', 'D'],
- nurse: ['R'],
- admisi: ['R'],
- pharmacy: ['R'],
- billing: ['R'],
- management: ['R'],
+ 'emp|doc': ['C', 'R', 'U', 'D'],
+ 'emp|nur': ['R'],
+ 'emp|reg': ['R'],
+ 'emp|pha': ['R'],
+ 'emp|pay': ['R'],
+ 'emp|mng': ['R'],
},
'/satusehat': {
- doctor: ['R'],
- nurse: ['R'],
- admisi: ['C', 'R', 'U', 'D'],
- pharmacy: ['R'],
- billing: ['R'],
- management: ['R'],
+ 'emp|doc': ['R'],
+ 'emp|nur': ['R'],
+ 'emp|reg': ['C', 'R', 'U', 'D'],
+ 'emp|pha': ['R'],
+ 'emp|pay': ['R'],
+ 'emp|mng': ['R'],
+ },
+ '/outpatient/encounter': {
+ 'emp|doc': ['C', 'R', 'U', 'D'],
+ 'emp|nur': ['C', 'R', 'U', 'D'],
+ 'emp|reg': ['R'],
+ 'emp|pha': ['R'],
+ 'emp|pay': ['R'],
+ 'emp|mng': ['R'],
+ },
+ '/emergency/encounter': {
+ 'emp|doc': ['C', 'R', 'U', 'D'],
+ 'emp|nur': ['C', 'R', 'U', 'D'],
+ 'emp|reg': ['R'],
+ 'emp|pha': ['R'],
+ 'emp|pay': ['R'],
+ 'emp|mng': ['R'],
+ },
+ '/inpatient/encounter': {
+ 'emp|doc': ['C', 'R', 'U', 'D'],
+ 'emp|nur': ['C', 'R', 'U', 'D'],
+ 'emp|reg': ['R'],
+ 'emp|pha': ['R'],
+ 'emp|pay': ['R'],
+ 'emp|mng': ['R'],
},
'/rehab/encounter': {
- doctor: ['C', 'R', 'U', 'D'],
- nurse: ['R'],
- admisi: ['R'],
- pharmacy: ['R'],
- billing: ['R'],
- management: ['R'],
+ 'emp|doc': ['C', 'R', 'U', 'D'],
+ 'emp|nur': ['R'],
+ 'emp|reg': ['R'],
+ 'emp|pha': ['R'],
+ 'emp|pay': ['R'],
+ 'emp|mng': ['R'],
},
'/rehab/registration': {
- doctor: ['C', 'R', 'U', 'D'],
- nurse: ['R'],
- admisi: ['R'],
- pharmacy: ['R'],
- billing: ['R'],
- management: ['R'],
+ 'emp|doc': ['C', 'R', 'U', 'D'],
+ 'emp|nur': ['R'],
+ 'emp|reg': ['R'],
+ 'emp|pha': ['R'],
+ 'emp|pay': ['R'],
+ 'emp|mng': ['R'],
},
} as const satisfies Record
diff --git a/app/models/consultation.ts b/app/models/consultation.ts
index 09d050a8..595d628e 100644
--- a/app/models/consultation.ts
+++ b/app/models/consultation.ts
@@ -28,9 +28,10 @@ export interface DeleteDto {
export function genCreateDto(): CreateDto {
return {
+ date: '',
encounter_id: 0,
problem: '',
- unit_id: 0,
+ dstUnit_id: 0,
}
}
diff --git a/app/models/control-letter.ts b/app/models/control-letter.ts
new file mode 100644
index 00000000..8f520212
--- /dev/null
+++ b/app/models/control-letter.ts
@@ -0,0 +1,37 @@
+import { type Base, genBase } from "./_base"
+import { genDoctor, type Doctor } from "./doctor"
+import { genEncounter, type Encounter } from "./encounter"
+import { genSpecialist, type Specialist } from "./specialist"
+import { genSubspecialist, type Subspecialist } from "./subspecialist"
+import { genUnit, type Unit } from "./unit"
+
+export interface ControlLetter extends Base {
+ encounter_id: number
+ encounter: Encounter
+ unit_id: number
+ unit: Unit
+ specialist_id: number
+ specialist: Specialist
+ subspecialist_id: number
+ subspecialist: Subspecialist
+ doctor_id: number
+ doctor: Doctor
+ date: ''
+}
+
+export function genControlLetter(): ControlLetter {
+ return {
+ ...genBase(),
+ encounter_id: 0,
+ encounter: genEncounter(),
+ unit_id: 0,
+ unit: genUnit(),
+ specialist_id: 0,
+ specialist: genSpecialist(),
+ subspecialist_id: 0,
+ subspecialist: genSubspecialist(),
+ doctor_id: 0,
+ doctor: genDoctor(),
+ date: ''
+ }
+}
diff --git a/app/models/division-position.ts b/app/models/division-position.ts
index 3bd5e63a..dc263ada 100644
--- a/app/models/division-position.ts
+++ b/app/models/division-position.ts
@@ -1,11 +1,13 @@
import { type Base, genBase } from './_base'
-
+import type { Employee } from './employee'
export interface DivisionPosition extends Base {
code: string
name: string
headStatus?: boolean
division_id: number
employee_id?: number
+
+ employee?: Employee | null
}
export function genDivisionPosition(): DivisionPosition {
diff --git a/app/models/division.ts b/app/models/division.ts
index 0f6d9185..c54a0e24 100644
--- a/app/models/division.ts
+++ b/app/models/division.ts
@@ -1,10 +1,13 @@
-import { type Base, genBase } from "./_base"
-
+import { type Base, genBase } from './_base'
+import type { DivisionPosition } from './division-position'
export interface Division extends Base {
code: string
name: string
parent_id?: number | null
childrens?: Division[] | null
+
+ // preload
+ divisionPosition?: DivisionPosition[] | null
}
export function genDivision(): Division {
diff --git a/app/models/doctor.ts b/app/models/doctor.ts
index 3f517476..1b631907 100644
--- a/app/models/doctor.ts
+++ b/app/models/doctor.ts
@@ -8,10 +8,11 @@ export interface Doctor extends Base {
employee: Employee
ihs_number: string
sip_number: string
- unit_id?: number
- specialist_id?: number
+ code?: string
+ unit_icode?: number
+ specialist_icode?: number
specialist?: Specialist
- subspecialist_id?: number
+ subspecialist_icode?: number
subspecialist?: Subspecialist
bpjs_code?: string
}
@@ -21,9 +22,9 @@ export interface CreateDto {
employee_id: number
ihs_number: string
sip_number: string
- unit_id?: number
- specialist_id?: number
- subspecialist_id?: number
+ unit_code?: number
+ specialist_code?: number
+ subspecialist_code?: number
bpjs_code: string
}
diff --git a/app/models/installation-position.ts b/app/models/installation-position.ts
new file mode 100644
index 00000000..199038d7
--- /dev/null
+++ b/app/models/installation-position.ts
@@ -0,0 +1,23 @@
+import { type Base, genBase } from './_base'
+import type { Employee } from './employee'
+
+export interface InstallationPosition extends Base {
+ installation_id: number
+ code: string
+ name: string
+ headStatus?: boolean
+ employee_id?: number
+
+ employee?: Employee | null
+}
+
+export function genInstallationPosition(): InstallationPosition {
+ return {
+ ...genBase(),
+ installation_id: 0,
+ code: '',
+ name: '',
+ headStatus: false,
+ employee_id: 0,
+ }
+}
diff --git a/app/models/mcu-order.ts b/app/models/mcu-order.ts
index e3899aab..35e4018c 100644
--- a/app/models/mcu-order.ts
+++ b/app/models/mcu-order.ts
@@ -1,14 +1,18 @@
import { type Base, genBase } from "./_base"
+import { type Doctor, genDoctor } from "./doctor"
+import type { McuOrderItem } from "./mcu-order-item"
export interface McuOrder extends Base {
encounter_id: number
doctor_id: number
+ doctor: Doctor
status_code?: string
specimenPickTime: string
examinationDate: string
number?: number
temperature?: number
mcuUrgencyLevel_code?: string
+ items: McuOrderItem[]
}
export function genMcuOrder(): McuOrder {
@@ -16,8 +20,10 @@ export function genMcuOrder(): McuOrder {
...genBase(),
encounter_id: 0,
doctor_id: 0,
+ doctor: genDoctor(),
specimenPickTime: '',
- examinationDate: ''
+ examinationDate: '',
+ items: []
}
}
diff --git a/app/models/prescription.ts b/app/models/prescription.ts
index 543724d2..12d5eb9d 100644
--- a/app/models/prescription.ts
+++ b/app/models/prescription.ts
@@ -1,10 +1,10 @@
+import { type Base, genBase } from "./_base";
import { type Encounter, genEncounter } from "./encounter";
import { type Doctor, genDoctor } from "./doctor";
import { type PrescriptionItem } from "./prescription-item";
import type { SpecialistIntern } from "./specialist-intern";
-export interface Prescription {
- id: number
+export interface Prescription extends Base {
encounter_id: number
encounter: Encounter
doctor_id: number
@@ -44,7 +44,7 @@ export interface DeleteDto {
export function genPresciption(): Prescription {
return {
- id: 0,
+ ...genBase(),
encounter_id: 0,
encounter: genEncounter(),
doctor_id: 0,
diff --git a/app/models/specialist-position.ts b/app/models/specialist-position.ts
new file mode 100644
index 00000000..727e8374
--- /dev/null
+++ b/app/models/specialist-position.ts
@@ -0,0 +1,22 @@
+import { type Base, genBase } from './_base'
+import type { Employee } from './employee'
+
+export interface SpecialistPosition extends Base {
+ specialist_id: number
+ code: string
+ name: string
+ headStatus?: boolean
+ employee_id?: number
+ employee?: Employee | null
+}
+
+export function genSpecialistPosition(): SpecialistPosition {
+ return {
+ ...genBase(),
+ specialist_id: 0,
+ code: '',
+ name: '',
+ headStatus: false,
+ employee_id: 0,
+ }
+}
diff --git a/app/models/specialist.ts b/app/models/specialist.ts
index b4fe1115..d3180a73 100644
--- a/app/models/specialist.ts
+++ b/app/models/specialist.ts
@@ -1,9 +1,12 @@
-import { type Base, genBase } from "./_base"
+import { type Base, genBase } from './_base'
+import type { Unit } from './unit'
+import type { Subspecialist } from "./subspecialist"
export interface Specialist extends Base {
code: string
name: string
- unit_id?: number | string | null
+ unit?: Unit | null
+ subspecialists?: Subspecialist[]
}
export function genSpecialist(): Specialist {
@@ -11,6 +14,6 @@ export function genSpecialist(): Specialist {
...genBase(),
code: '',
name: '',
- unit_id: 0
+ unit_id: 0,
}
}
diff --git a/app/models/subspecialist-position.ts b/app/models/subspecialist-position.ts
new file mode 100644
index 00000000..28ea2287
--- /dev/null
+++ b/app/models/subspecialist-position.ts
@@ -0,0 +1,25 @@
+import { type Base, genBase } from './_base'
+import type { Employee } from './employee'
+import type { Subspecialist } from './subspecialist'
+
+export interface SubSpecialistPosition extends Base {
+ subspecialist_id: number
+ code: string
+ name: string
+ headStatus?: boolean
+ employee_id?: number
+
+ subspecialist?: Subspecialist | null
+ employee?: Employee | null
+}
+
+export function genSubSpecialistPosition(): SubSpecialistPosition {
+ return {
+ ...genBase(),
+ subspecialist_id: 0,
+ code: '',
+ name: '',
+ headStatus: false,
+ employee_id: 0,
+ }
+}
diff --git a/app/models/subspecialist.ts b/app/models/subspecialist.ts
index 6343b847..e67333e9 100644
--- a/app/models/subspecialist.ts
+++ b/app/models/subspecialist.ts
@@ -1,9 +1,11 @@
-import { type Base, genBase } from "./_base"
-
+import { type Base, genBase } from './_base'
+import { type Specialist } from './specialist'
export interface Subspecialist extends Base {
code: string
name: string
specialist_id?: number | string | null
+
+ specialist?: Specialist | null
}
export function genSubspecialist(): Subspecialist {
@@ -11,6 +13,6 @@ export function genSubspecialist(): Subspecialist {
...genBase(),
code: '',
name: '',
- specialist_id: 0
+ specialist_id: 0,
}
}
diff --git a/app/models/unit-position.ts b/app/models/unit-position.ts
new file mode 100644
index 00000000..11e97806
--- /dev/null
+++ b/app/models/unit-position.ts
@@ -0,0 +1,23 @@
+import { type Base, genBase } from './_base'
+import type { Employee } from './employee'
+
+export interface UnitPosition extends Base {
+ unit_id: number
+ code: string
+ name: string
+ headStatus?: boolean
+ employee_id?: number
+
+ employee?: Employee | null
+}
+
+export function genUnitPosition(): UnitPosition {
+ return {
+ ...genBase(),
+ unit_id: 0,
+ code: '',
+ name: '',
+ headStatus: false,
+ employee_id: 0,
+ }
+}
diff --git a/app/models/unit.ts b/app/models/unit.ts
index 142f0570..ba8ba5a1 100644
--- a/app/models/unit.ts
+++ b/app/models/unit.ts
@@ -1,9 +1,11 @@
-import { type Base, genBase } from "./_base"
-
+import { type Base, genBase } from './_base'
+import { type Installation } from '~/models/installation'
export interface Unit extends Base {
code: string
name: string
installation_id?: number | string | null
+
+ installation?: Installation | null
}
export function genUnit(): Unit {
diff --git a/app/models/vclaim.ts b/app/models/vclaim.ts
new file mode 100644
index 00000000..21ffb94f
--- /dev/null
+++ b/app/models/vclaim.ts
@@ -0,0 +1,15 @@
+export interface VclaimSepData {
+ letterDate: string
+ letterNumber: string
+ serviceType: string
+ flow: string
+ medicalRecordNumber: string
+ patientName: string
+ cardNumber: string
+ controlLetterNumber: string
+ controlLetterDate: string
+ clinicDestination: string
+ attendingDoctor: string
+ diagnosis: string
+ careClass: string
+}
diff --git a/app/pages/(features)/emergency/encounter/[id]/edit.vue b/app/pages/(features)/emergency/encounter/[id]/edit.vue
new file mode 100644
index 00000000..92d263d7
--- /dev/null
+++ b/app/pages/(features)/emergency/encounter/[id]/edit.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/emergency/encounter/add.vue b/app/pages/(features)/emergency/encounter/add.vue
new file mode 100644
index 00000000..aa382643
--- /dev/null
+++ b/app/pages/(features)/emergency/encounter/add.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/emergency/encounter/index.vue b/app/pages/(features)/emergency/encounter/index.vue
index 50485cec..ed05c25e 100644
--- a/app/pages/(features)/emergency/encounter/index.vue
+++ b/app/pages/(features)/emergency/encounter/index.vue
@@ -1,10 +1,47 @@
-
-
Hello world!!
-
You are accessing "{{ route.fullPath }}"
+
diff --git a/app/pages/(features)/inpatient/encounter/[id]/edit.vue b/app/pages/(features)/inpatient/encounter/[id]/edit.vue
new file mode 100644
index 00000000..2df3d4f6
--- /dev/null
+++ b/app/pages/(features)/inpatient/encounter/[id]/edit.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/inpatient/encounter/add.vue b/app/pages/(features)/inpatient/encounter/add.vue
new file mode 100644
index 00000000..bd827f79
--- /dev/null
+++ b/app/pages/(features)/inpatient/encounter/add.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/inpatient/encounter/index.vue b/app/pages/(features)/inpatient/encounter/index.vue
index 50485cec..7c9d1ac5 100644
--- a/app/pages/(features)/inpatient/encounter/index.vue
+++ b/app/pages/(features)/inpatient/encounter/index.vue
@@ -1,10 +1,47 @@
-
-
Hello world!!
-
You are accessing "{{ route.fullPath }}"
+
diff --git a/app/pages/(features)/integration/bpjs/control-letter/index.vue b/app/pages/(features)/integration/bpjs/control-letter/index.vue
new file mode 100644
index 00000000..8dcb9006
--- /dev/null
+++ b/app/pages/(features)/integration/bpjs/control-letter/index.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
diff --git a/app/pages/(features)/integration/bpjs/sep/add.vue b/app/pages/(features)/integration/bpjs/sep/add.vue
index 5db12aac..0658780b 100644
--- a/app/pages/(features)/integration/bpjs/sep/add.vue
+++ b/app/pages/(features)/integration/bpjs/sep/add.vue
@@ -22,12 +22,12 @@ const { checkRole, hasCreateAccess } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
-if (!hasAccess) {
- throw createError({
- statusCode: 403,
- statusMessage: 'Access denied',
- })
-}
+// if (!hasAccess) {
+// throw createError({
+// statusCode: 403,
+// statusMessage: 'Access denied',
+// })
+// }
// Define permission-based computed properties
const canCreate = true // hasCreateAccess(roleAccess)
diff --git a/app/pages/(features)/integration/bpjs/sep/index.vue b/app/pages/(features)/integration/bpjs/sep/index.vue
index b8ec57c4..d99dbb5d 100644
--- a/app/pages/(features)/integration/bpjs/sep/index.vue
+++ b/app/pages/(features)/integration/bpjs/sep/index.vue
@@ -22,9 +22,9 @@ const { checkRole, hasReadAccess } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
-if (!hasAccess) {
- navigateTo('/403')
-}
+// if (!hasAccess) {
+// navigateTo('/403')
+// }
// Define permission-based computed properties
const canRead = true // hasReadAccess(roleAccess)
diff --git a/app/pages/(features)/org-src/division-position/index.vue b/app/pages/(features)/org-src/division-position/index.vue
new file mode 100644
index 00000000..53551b48
--- /dev/null
+++ b/app/pages/(features)/org-src/division-position/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/org-src/division/[id]/index.vue b/app/pages/(features)/org-src/division/[id]/index.vue
new file mode 100644
index 00000000..658652d9
--- /dev/null
+++ b/app/pages/(features)/org-src/division/[id]/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/org-src/installation-position/index.vue b/app/pages/(features)/org-src/installation-position/index.vue
new file mode 100644
index 00000000..0b525098
--- /dev/null
+++ b/app/pages/(features)/org-src/installation-position/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/org-src/installation/[id]/index.vue b/app/pages/(features)/org-src/installation/[id]/index.vue
new file mode 100644
index 00000000..0264dd65
--- /dev/null
+++ b/app/pages/(features)/org-src/installation/[id]/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/org-src/specialist-position/index.vue b/app/pages/(features)/org-src/specialist-position/index.vue
new file mode 100644
index 00000000..a2e29428
--- /dev/null
+++ b/app/pages/(features)/org-src/specialist-position/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/org-src/specialist/[id]/index.vue b/app/pages/(features)/org-src/specialist/[id]/index.vue
new file mode 100644
index 00000000..c5554a71
--- /dev/null
+++ b/app/pages/(features)/org-src/specialist/[id]/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/org-src/subspecialist-position/index.vue b/app/pages/(features)/org-src/subspecialist-position/index.vue
new file mode 100644
index 00000000..650ae9ee
--- /dev/null
+++ b/app/pages/(features)/org-src/subspecialist-position/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/org-src/subspecialist/[id]/index.vue b/app/pages/(features)/org-src/subspecialist/[id]/index.vue
new file mode 100644
index 00000000..7bd0b8ee
--- /dev/null
+++ b/app/pages/(features)/org-src/subspecialist/[id]/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/org-src/unit-position/index.vue b/app/pages/(features)/org-src/unit-position/index.vue
new file mode 100644
index 00000000..c40a0654
--- /dev/null
+++ b/app/pages/(features)/org-src/unit-position/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/org-src/unit/[id]/index.vue b/app/pages/(features)/org-src/unit/[id]/index.vue
new file mode 100644
index 00000000..1230b57c
--- /dev/null
+++ b/app/pages/(features)/org-src/unit/[id]/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/outpatient/encounter/[id]/edit.vue b/app/pages/(features)/outpatient/encounter/[id]/edit.vue
new file mode 100644
index 00000000..9713675f
--- /dev/null
+++ b/app/pages/(features)/outpatient/encounter/[id]/edit.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/outpatient/encounter/[id]/index.vue b/app/pages/(features)/outpatient/encounter/[id]/index.vue
new file mode 100644
index 00000000..1864cf2c
--- /dev/null
+++ b/app/pages/(features)/outpatient/encounter/[id]/index.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
diff --git a/app/pages/(features)/outpatient/encounter/add.vue b/app/pages/(features)/outpatient/encounter/add.vue
new file mode 100644
index 00000000..948b16c6
--- /dev/null
+++ b/app/pages/(features)/outpatient/encounter/add.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/outpatient/encounter/index.vue b/app/pages/(features)/outpatient/encounter/index.vue
index 50485cec..1e679c5d 100644
--- a/app/pages/(features)/outpatient/encounter/index.vue
+++ b/app/pages/(features)/outpatient/encounter/index.vue
@@ -1,10 +1,47 @@
-
-
Hello world!!
-
You are accessing "{{ route.fullPath }}"
+
diff --git a/app/pages/(features)/outpation-action/cemotherapy/index.vue b/app/pages/(features)/outpation-action/cemotherapy/index.vue
deleted file mode 100644
index 50485cec..00000000
--- a/app/pages/(features)/outpation-action/cemotherapy/index.vue
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
Hello world!!
-
You are accessing "{{ route.fullPath }}"
-
-
diff --git a/app/pages/(features)/outpation-action/chemotherapy/[mode]/[id]/verification.vue b/app/pages/(features)/outpation-action/chemotherapy/[mode]/[id]/verification.vue
new file mode 100644
index 00000000..ef936ff2
--- /dev/null
+++ b/app/pages/(features)/outpation-action/chemotherapy/[mode]/[id]/verification.vue
@@ -0,0 +1,47 @@
+
+
+
+
+
diff --git a/app/pages/(features)/outpation-action/chemotherapy/[mode]/index.vue b/app/pages/(features)/outpation-action/chemotherapy/[mode]/index.vue
new file mode 100644
index 00000000..cf33691a
--- /dev/null
+++ b/app/pages/(features)/outpation-action/chemotherapy/[mode]/index.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
+
diff --git a/app/pages/(features)/outpation-action/chemotherapy/index.vue b/app/pages/(features)/outpation-action/chemotherapy/index.vue
new file mode 100644
index 00000000..a2dfdea5
--- /dev/null
+++ b/app/pages/(features)/outpation-action/chemotherapy/index.vue
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/app/pages/(features)/outpation-action/chemotherapy/list.vue b/app/pages/(features)/outpation-action/chemotherapy/list.vue
new file mode 100644
index 00000000..a141baaa
--- /dev/null
+++ b/app/pages/(features)/outpation-action/chemotherapy/list.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
diff --git a/app/pages/(features)/rehab/examination-queue/index.vue b/app/pages/(features)/rehab/encounter-queue/index.vue
similarity index 100%
rename from app/pages/(features)/rehab/examination-queue/index.vue
rename to app/pages/(features)/rehab/encounter-queue/index.vue
diff --git a/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/edit.vue b/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/edit.vue
new file mode 100644
index 00000000..cc5d182f
--- /dev/null
+++ b/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/edit.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
diff --git a/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/index.vue b/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/index.vue
new file mode 100644
index 00000000..612315ad
--- /dev/null
+++ b/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/index.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
diff --git a/app/pages/(features)/rehab/encounter/[id]/control-letter/add.vue b/app/pages/(features)/rehab/encounter/[id]/control-letter/add.vue
new file mode 100644
index 00000000..1070a29f
--- /dev/null
+++ b/app/pages/(features)/rehab/encounter/[id]/control-letter/add.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
diff --git a/app/pages/(features)/rehab/encounter/[id]/edit.vue b/app/pages/(features)/rehab/encounter/[id]/edit.vue
index 77b0dd3e..02dc5428 100644
--- a/app/pages/(features)/rehab/encounter/[id]/edit.vue
+++ b/app/pages/(features)/rehab/encounter/[id]/edit.vue
@@ -6,7 +6,7 @@ import { PAGE_PERMISSIONS } from '~/lib/page-permission'
definePageMeta({
middleware: ['rbac'],
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
- title: 'Tambah Kunjungan',
+ title: 'Edit Kunjungan',
contentFrame: 'cf-full-width',
})
@@ -18,7 +18,7 @@ useHead({
const roleAccess: PagePermission = PAGE_PERMISSIONS['/rehab/encounter']
-const { checkRole, hasCreateAccess } = useRBAC()
+const { checkRole, hasUpdateAccess } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
@@ -30,12 +30,26 @@ if (!hasAccess) {
}
// Define permission-based computed properties
-const canCreate = hasCreateAccess(roleAccess)
+const canUpdate = hasUpdateAccess(roleAccess)
+
+// Get encounter ID from route params
+const encounterId = computed(() => {
+ const id = route.params.id
+ return typeof id === 'string' ? parseInt(id) : 0
+})
-
-
+
+
-
+
diff --git a/app/pages/(features)/rehab/encounter/[id]/process.vue b/app/pages/(features)/rehab/encounter/[id]/process.vue
index 3fa7525a..abd0efa7 100644
--- a/app/pages/(features)/rehab/encounter/[id]/process.vue
+++ b/app/pages/(features)/rehab/encounter/[id]/process.vue
@@ -22,15 +22,15 @@ const { checkRole, hasCreateAccess } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
-if (!hasAccess) {
- throw createError({
- statusCode: 403,
- statusMessage: 'Access denied',
- })
-}
+// if (!hasAccess) {
+// throw createError({
+// statusCode: 403,
+// statusMessage: 'Access denied',
+// })
+// }
// Define permission-based computed properties
-const canCreate = hasCreateAccess(roleAccess)
+const canCreate = true // hasCreateAccess(roleAccess)
diff --git a/app/pages/(features)/rehab/encounter/add.vue b/app/pages/(features)/rehab/encounter/add.vue
index f20b90c1..fe7dd98c 100644
--- a/app/pages/(features)/rehab/encounter/add.vue
+++ b/app/pages/(features)/rehab/encounter/add.vue
@@ -35,7 +35,15 @@ const canCreate = hasCreateAccess(roleAccess)
-
+
-
+
diff --git a/app/pages/(features)/rehab/encounter/index.vue b/app/pages/(features)/rehab/encounter/index.vue
index 7a8564a8..f50ad954 100644
--- a/app/pages/(features)/rehab/encounter/index.vue
+++ b/app/pages/(features)/rehab/encounter/index.vue
@@ -5,7 +5,7 @@ import { PAGE_PERMISSIONS } from '~/lib/page-permission'
definePageMeta({
middleware: ['rbac'],
- roles: ['system', 'doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
+ roles: ['system', 'emp-doc', 'emp-nur', 'emp-reg', 'emp-pha', 'emp-pay', 'emp-mng'],
title: 'Daftar Kunjungan',
contentFrame: 'cf-full-width',
})
@@ -23,18 +23,25 @@ const { checkRole, hasReadAccess } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
if (!hasAccess) {
- navigateTo('/403')
+ // navigateTo('/403')
}
// Define permission-based computed properties
-const canRead = hasReadAccess(roleAccess)
+const canRead = true // hasReadAccess(roleAccess)
diff --git a/app/pages/(features)/rehab/examination/index.vue b/app/pages/(features)/rehab/examination/index.vue
deleted file mode 100644
index 806b2650..00000000
--- a/app/pages/(features)/rehab/examination/index.vue
+++ /dev/null
@@ -1,3 +0,0 @@
-
- Examination
-
diff --git a/app/schemas/chemotherapy.schema.ts b/app/schemas/chemotherapy.schema.ts
new file mode 100644
index 00000000..212e5358
--- /dev/null
+++ b/app/schemas/chemotherapy.schema.ts
@@ -0,0 +1,73 @@
+import { z } from 'zod'
+
+const dateStringSchema = z.string().min(1)
+
+export const chemotherapySchema = z.object({
+ // Data Pasien
+ namaPasien: z.string({
+ required_error: 'Nama pasien harus diisi',
+ }).min(1, 'Nama pasien harus diisi'),
+
+ tanggalLahir: z.string({
+ required_error: 'Tanggal lahir harus diisi',
+ }).min(1, 'Tanggal lahir harus diisi'),
+
+ noRM: z.string({
+ required_error: 'Nomor RM harus diisi',
+ }).min(1, 'Nomor RM harus diisi'),
+
+ alamat: z.string({
+ required_error: 'Alamat harus diisi',
+ }).min(1, 'Alamat harus diisi'),
+
+ beratBadan: z.union([
+ z.string(),
+ z.number()
+ ]).transform(val => val === '' ? null : Number(val))
+ .refine(val => val === null || (val >= 0 && val <= 500), {
+ message: 'Berat badan harus di antara 0-500 kg',
+ }),
+
+ tinggiBadan: z.union([
+ z.string(),
+ z.number()
+ ]).transform(val => val === '' ? null : Number(val))
+ .refine(val => val === null || (val >= 0 && val <= 300), {
+ message: 'Tinggi badan harus di antara 0-300 cm',
+ }),
+
+ diagnosa: z.string({
+ required_error: 'Diagnosa harus dipilih',
+ }).min(1, 'Diagnosa harus dipilih'),
+
+ // Protokol Kemoterapi
+ siklus: z.string({
+ required_error: 'Siklus harus diisi',
+ }).min(1, 'Siklus harus diisi'),
+
+ periodeAwal: z.string({
+ required_error: 'Periode awal harus diisi',
+ }).min(1, 'Periode awal harus diisi'),
+
+ periodeAkhir: dateStringSchema.refine((val) => {
+ if (!val) return false
+ const date = new Date(val)
+ return !isNaN(date.getTime())
+ }, {
+ message: 'Format tanggal tidak valid'
+ }),
+
+ tanggalKemoterapi: dateStringSchema.refine((val) => {
+ if (!val) return false
+ const date = new Date(val)
+ return !isNaN(date.getTime())
+ }, {
+ message: 'Format tanggal tidak valid'
+ }),
+
+ dokterKRJ: z.string({
+ required_error: 'Dokter harus dipilih',
+ }).refine(val => val !== '', {
+ message: 'Dokter harus dipilih',
+ }),
+})
\ No newline at end of file
diff --git a/app/schemas/control-letter.schema.ts b/app/schemas/control-letter.schema.ts
new file mode 100644
index 00000000..c82ffaac
--- /dev/null
+++ b/app/schemas/control-letter.schema.ts
@@ -0,0 +1,47 @@
+import { z } from 'zod'
+
+const ControlLetterSchema = z.object({
+ sepStatus: z.string({
+ required_error: 'Mohon isi status SEP',
+ }).default('SEP Internal'),
+ unit_code: z.string({
+ required_error: 'Mohon isi Unit',
+ }),
+ specialist_code: z.string({
+ required_error: 'Mohon isi Spesialis',
+ }),
+ subspecialist_code: z.string({
+ required_error: 'Mohon isi Sub Spesialis',
+ }),
+ doctor_code: z.string({
+ required_error: 'Mohon isi DPJP',
+ }),
+ encounter_code: z.string().optional(),
+ date: z.string({
+ required_error: 'Mohon lengkapi Tanggal Kontrol',
+ })
+ .refine(
+ (date) => {
+ // Jika kosong, return false untuk required validation
+ if (!date || date.trim() === '') return false
+
+ // Jika ada isi, validasi format tanggal
+ try {
+ const dateObj = new Date(date)
+ // Cek apakah tanggal valid dan tahun >= 1900
+ return !isNaN(dateObj.getTime()) && dateObj.getFullYear() >= 1900
+ } catch {
+ return false
+ }
+ },
+ {
+ message: 'Mohon lengkapi Tanggal Kontrol dengan format yang valid',
+ },
+ )
+ .transform((dateStr) => new Date(dateStr).toISOString()),
+})
+
+type ControlLetterFormData = z.infer
+
+export { ControlLetterSchema }
+export type { ControlLetterFormData }
diff --git a/app/schemas/installation-position.schema.ts b/app/schemas/installation-position.schema.ts
new file mode 100644
index 00000000..5990fc6c
--- /dev/null
+++ b/app/schemas/installation-position.schema.ts
@@ -0,0 +1,20 @@
+import { z } from 'zod'
+import type { InstallationPosition } from '~/models/installation-position'
+
+const InstallationPositionSchema = z.object({
+ code: z.string({ required_error: 'Kode harus diisi' }).min(1, 'Kode minimum 1 karakter'),
+ name: z.string({ required_error: 'Nama harus diisi' }).min(1, 'Nama minimum 1 karakter'),
+ headStatus: z.boolean().optional().nullable(),
+ installation_id: z.union([
+ z.string({ required_error: 'Instalasi Induk harus diisi' }),
+ z.number({ required_error: 'Instalasi Induk harus diisi' }),
+ ]),
+ employee_id: z
+ .union([z.string({ required_error: 'Karyawan harus diisi' }), z.number({ required_error: 'Karyawan harus diisi' })])
+ .optional()
+ .nullable(),
+})
+type InstallationPositionFormData = z.infer & Partial
+
+export { InstallationPositionSchema }
+export type { InstallationPositionFormData }
diff --git a/app/schemas/integration-bpjs.schema.ts b/app/schemas/integration-bpjs.schema.ts
new file mode 100644
index 00000000..47206edf
--- /dev/null
+++ b/app/schemas/integration-bpjs.schema.ts
@@ -0,0 +1,255 @@
+import { z } from 'zod'
+
+const ERROR_MESSAGES = {
+ required: {
+ sepDate: 'Tanggal wajib diisi',
+ serviceType: 'Jenis Pelayanan wajib diisi',
+ admissionType: 'Jenis Pendaftaran wajib diisi',
+ cardNumber: 'No. Kartu BPJS wajib diisi',
+ nationalId: 'Nomor ID wajib diisi',
+ medicalRecordNumber: 'Nomor Rekam Medis wajib diisi',
+ patientName: 'Nama wajib diisi',
+ phoneNumber: 'Nomor Telepon wajib diisi',
+ referralLetterNumber: 'Nomor Surat Kontrol wajib diisi',
+ referralLetterDate: 'Tanggal Surat Kontrol wajib diisi',
+ fromClinic: 'Faskes Asal wajib diisi',
+ destinationClinic: 'Klinik Tujuan wajib diisi',
+ attendingDoctor: 'Dokter wajib diisi',
+ initialDiagnosis: 'Diagnosa Awal wajib diisi',
+ cob: 'COB wajib diisi',
+ cataract: 'Katarak wajib diisi',
+ clinicExcecutive: 'Klinkik eksekutif wajib diisi',
+ subSpecialistId: 'Subspesialis wajib diisi',
+ procedureType: 'Jenis Prosedur wajib diisi',
+ supportCode: 'Kode Penunjang wajib diisi',
+ note: 'Catatan wajib diisi',
+ trafficAccident: 'Kejadian lalu lintas wajib diisi',
+ purposeOfVisit: 'Tujuan Kunjungan wajib diisi',
+ serviceAssessment: 'Assemen Pelayanan wajib diisi',
+ lpNumber: 'Nomor LP wajib diisi',
+ accidentDate: 'Tanggal Kejadian lalu lintas wajib diisi',
+ accidentNote: 'Keterangan Kejadian lalu lintas wajib diisi',
+ accidentProvince: 'Provinsi Kejadian lalu lintas wajib diisi',
+ accidentCity: 'Kota Kejadian lalu lintas wajib diisi',
+ accidentDistrict: 'Kecamatan Kejadian lalu lintas wajib diisi',
+ suplesi: 'Suplesi wajib diisi',
+ suplesiNumber: 'Nomor Suplesi wajib diisi',
+ classLevel: 'Kelas Rawat wajib diisi',
+ classLevelUpgrade: 'Kelas Rawat Naik wajib diisi',
+ classPaySource: 'Pembiayaan wajib diisi',
+ responsiblePerson: 'Penanggung Jawab wajib diisi',
+ },
+}
+
+const IntegrationBpjsSchema = z
+ .object({
+ sepDate: z.string({ required_error: ERROR_MESSAGES.required.sepDate }).min(1, ERROR_MESSAGES.required.sepDate),
+ serviceType: z
+ .string({ required_error: ERROR_MESSAGES.required.serviceType })
+ .min(1, ERROR_MESSAGES.required.serviceType)
+ .optional(),
+ admissionType: z
+ .string({ required_error: ERROR_MESSAGES.required.admissionType })
+ .min(1, ERROR_MESSAGES.required.admissionType),
+ cardNumber: z
+ .string({ required_error: ERROR_MESSAGES.required.cardNumber })
+ .min(1, ERROR_MESSAGES.required.cardNumber),
+ nationalId: z
+ .string({ required_error: ERROR_MESSAGES.required.nationalId })
+ .min(1, ERROR_MESSAGES.required.nationalId),
+ medicalRecordNumber: z
+ .string({ required_error: ERROR_MESSAGES.required.medicalRecordNumber })
+ .min(1, ERROR_MESSAGES.required.medicalRecordNumber),
+ patientName: z
+ .string({ required_error: ERROR_MESSAGES.required.patientName })
+ .min(1, ERROR_MESSAGES.required.patientName),
+ phoneNumber: z
+ .string({ required_error: ERROR_MESSAGES.required.phoneNumber })
+ .min(1, ERROR_MESSAGES.required.phoneNumber),
+ referralLetterNumber: z
+ .string({ required_error: ERROR_MESSAGES.required.referralLetterNumber })
+ .min(1, ERROR_MESSAGES.required.referralLetterNumber).optional(),
+ referralLetterDate: z
+ .string({ required_error: ERROR_MESSAGES.required.referralLetterDate })
+ .min(1, ERROR_MESSAGES.required.referralLetterDate).optional(),
+ fromClinic: z
+ .string({ required_error: ERROR_MESSAGES.required.fromClinic })
+ .min(1, ERROR_MESSAGES.required.fromClinic)
+ .optional(),
+ destinationClinic: z
+ .string({ required_error: ERROR_MESSAGES.required.destinationClinic })
+ .min(1, ERROR_MESSAGES.required.destinationClinic),
+ attendingDoctor: z
+ .string({ required_error: ERROR_MESSAGES.required.attendingDoctor })
+ .min(1, ERROR_MESSAGES.required.attendingDoctor),
+ initialDiagnosis: z
+ .string({ required_error: ERROR_MESSAGES.required.initialDiagnosis })
+ .min(1, ERROR_MESSAGES.required.initialDiagnosis),
+ cob: z.string({ required_error: ERROR_MESSAGES.required.cob }).min(1, ERROR_MESSAGES.required.cob),
+ cataract: z.string({ required_error: ERROR_MESSAGES.required.cataract }).min(1, ERROR_MESSAGES.required.cataract),
+ clinicExcecutive: z
+ .string({ required_error: ERROR_MESSAGES.required.clinicExcecutive })
+ .min(1, ERROR_MESSAGES.required.clinicExcecutive),
+ subSpecialistId: z
+ .string({ required_error: ERROR_MESSAGES.required.subSpecialistId })
+ .min(1, ERROR_MESSAGES.required.subSpecialistId)
+ .optional(),
+ procedureType: z
+ .string({ required_error: ERROR_MESSAGES.required.procedureType })
+ .min(1, ERROR_MESSAGES.required.procedureType)
+ .optional(),
+ supportCode: z
+ .string({ required_error: ERROR_MESSAGES.required.supportCode })
+ .min(1, ERROR_MESSAGES.required.supportCode)
+ .optional(),
+ note: z.string({ required_error: ERROR_MESSAGES.required.note }).min(1, ERROR_MESSAGES.required.note).optional(),
+ trafficAccident: z
+ .string({ required_error: ERROR_MESSAGES.required.trafficAccident })
+ .min(1, ERROR_MESSAGES.required.trafficAccident)
+ .optional(),
+ purposeOfVisit: z
+ .string({ required_error: ERROR_MESSAGES.required.purposeOfVisit })
+ .min(1, ERROR_MESSAGES.required.purposeOfVisit)
+ .optional(),
+ serviceAssessment: z
+ .string({ required_error: ERROR_MESSAGES.required.serviceAssessment })
+ .min(1, ERROR_MESSAGES.required.serviceAssessment)
+ .optional(),
+ lpNumber: z.string({ required_error: ERROR_MESSAGES.required.lpNumber }).optional(),
+ accidentDate: z.string({ required_error: ERROR_MESSAGES.required.accidentDate }).optional(),
+ accidentNote: z.string({ required_error: ERROR_MESSAGES.required.accidentNote }).optional(),
+ accidentProvince: z.string({ required_error: ERROR_MESSAGES.required.accidentProvince }).optional(),
+ accidentCity: z.string({ required_error: ERROR_MESSAGES.required.accidentCity }).optional(),
+ accidentDistrict: z.string({ required_error: ERROR_MESSAGES.required.accidentDistrict }).optional(),
+ suplesi: z.string({ required_error: ERROR_MESSAGES.required.suplesi }).optional(),
+ suplesiNumber: z.string({ required_error: ERROR_MESSAGES.required.suplesiNumber }).optional(),
+ classLevel: z.string({ required_error: ERROR_MESSAGES.required.classLevel }).optional(),
+ classLevelUpgrade: z.string({ required_error: ERROR_MESSAGES.required.classLevelUpgrade }).optional(),
+ classPaySource: z.string({ required_error: ERROR_MESSAGES.required.classPaySource }).optional(),
+ responsiblePerson: z.string({ required_error: ERROR_MESSAGES.required.responsiblePerson }).optional(),
+ })
+ .refine(
+ (data) => {
+ if (data.trafficAccident && data.trafficAccident.trim() !== '') {
+ return data.accidentDate && data.accidentDate.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.accidentDate,
+ path: ['accidentDate'],
+ },
+ )
+ .refine(
+ (data) => {
+ if (data.trafficAccident && data.trafficAccident.trim() !== '') {
+ return data.accidentProvince && data.accidentProvince.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.accidentProvince,
+ path: ['accidentProvince'],
+ },
+ )
+ .refine(
+ (data) => {
+ if (data.trafficAccident && data.trafficAccident.trim() !== '') {
+ return data.accidentCity && data.accidentCity.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.accidentCity,
+ path: ['accidentCity'],
+ },
+ )
+ .refine(
+ (data) => {
+ if (data.trafficAccident && data.trafficAccident.trim() !== '') {
+ return data.accidentDistrict && data.accidentDistrict.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.accidentDistrict,
+ path: ['accidentDistrict'],
+ },
+ )
+ .refine(
+ (data) => {
+ if (data.trafficAccident && data.trafficAccident.trim() !== '') {
+ return data.suplesi && data.suplesi.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.suplesi,
+ path: ['suplesi'],
+ },
+ )
+ .refine(
+ (data) => {
+ if (data.trafficAccident && data.trafficAccident.trim() !== '' && data.suplesi?.trim() === 'yes') {
+ return data.suplesiNumber && data.suplesiNumber.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.suplesiNumber,
+ path: ['suplesiNumber'],
+ },
+ )
+ .refine(
+ (data) => {
+ if (data.serviceType === '1') {
+ return data.classLevel && data.classLevel.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.classLevel,
+ path: ['classLevel'],
+ },
+ )
+ .refine(
+ (data) => {
+ if (data.serviceType === '1') {
+ return data.classLevelUpgrade && data.classLevelUpgrade.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.classLevelUpgrade,
+ path: ['classLevelUpgrade'],
+ },
+ )
+ .refine(
+ (data) => {
+ if (data.serviceType === '1' && data.classLevelUpgrade?.trim() !== '') {
+ return data.classPaySource && data.classPaySource.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.classPaySource,
+ path: ['classPaySource'],
+ },
+ )
+ .refine(
+ (data) => {
+ if (data.serviceType === '1' && data.classPaySource?.trim() !== '') {
+ return data.responsiblePerson && data.responsiblePerson.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.responsiblePerson,
+ path: ['responsiblePerson'],
+ },
+ )
+
+type IntegrationBpjsFormData = z.infer
+
+export { IntegrationBpjsSchema }
+export type { IntegrationBpjsFormData }
diff --git a/app/schemas/integration-encounter.schema.ts b/app/schemas/integration-encounter.schema.ts
new file mode 100644
index 00000000..32327328
--- /dev/null
+++ b/app/schemas/integration-encounter.schema.ts
@@ -0,0 +1,133 @@
+import { z } from 'zod'
+
+const ERROR_MESSAGES = {
+ required: {
+ doctorId: 'Dokter wajib diisi',
+ registerDate: 'Tanggal Daftar wajib diisi',
+ paymentType: 'Jenis Pembayaran wajib diisi',
+ subSpecialistId: 'Subspesialis wajib diisi',
+ patientCategory: 'Kelompok Peserta wajib diisi',
+ cardNumber: 'No. Kartu BPJS wajib diisi',
+ sepType: 'Jenis SEP wajib diisi',
+ sepNumber: 'No. SEP wajib diisi',
+ },
+}
+
+const ACCEPTED_UPLOAD_TYPES = ['image/jpeg', 'image/png', 'application/pdf']
+
+const IntegrationEncounterSchema = z
+ .object({
+ // Patient data (readonly, populated from selected patient)
+ patientName: z.string().optional(),
+ nationalIdentity: z.string().optional(),
+ medicalRecordNumber: z.string().optional(),
+
+ // Visit data
+ doctorId: z
+ .string({ required_error: ERROR_MESSAGES.required.doctorId })
+ .min(1, ERROR_MESSAGES.required.doctorId),
+ subSpecialistId: z
+ .string({ required_error: ERROR_MESSAGES.required.subSpecialistId })
+ .min(1, ERROR_MESSAGES.required.subSpecialistId)
+ .optional(),
+ registerDate: z
+ .string({ required_error: ERROR_MESSAGES.required.registerDate })
+ .min(1, ERROR_MESSAGES.required.registerDate),
+ paymentType: z
+ .string({ required_error: ERROR_MESSAGES.required.paymentType })
+ .min(1, ERROR_MESSAGES.required.paymentType),
+
+ // BPJS related fields
+ patientCategory: z
+ .string()
+ .min(1, ERROR_MESSAGES.required.patientCategory)
+ .optional(),
+ cardNumber: z
+ .string()
+ .min(1, ERROR_MESSAGES.required.cardNumber)
+ .optional(),
+ sepType: z
+ .string()
+ .min(1, ERROR_MESSAGES.required.sepType)
+ .optional(),
+ sepNumber: z
+ .string()
+ .min(1, ERROR_MESSAGES.required.sepNumber)
+ .optional(),
+
+ // File uploads
+ sepFile: z
+ .any()
+ .optional()
+ .refine((f) => !f || f instanceof File, { message: 'Harus berupa file yang valid' })
+ .refine((f) => !f || ACCEPTED_UPLOAD_TYPES.includes(f.type), {
+ message: 'Format file harus JPG, PNG, atau PDF',
+ })
+ .refine((f) => !f || f.size <= 1 * 1024 * 1024, { message: 'Maksimal 1MB' }),
+ sippFile: z
+ .any()
+ .optional()
+ .refine((f) => !f || f instanceof File, { message: 'Harus berupa file yang valid' })
+ .refine((f) => !f || ACCEPTED_UPLOAD_TYPES.includes(f.type), {
+ message: 'Format file harus JPG, PNG, atau PDF',
+ })
+ .refine((f) => !f || f.size <= 1 * 1024 * 1024, { message: 'Maksimal 1MB' }),
+ })
+ .refine(
+ (data) => {
+ // If payment type is jkn, then patient category is required
+ if (data.paymentType === 'jkn') {
+ return data.patientCategory && data.patientCategory.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.patientCategory,
+ path: ['patientCategory'],
+ },
+ )
+ .refine(
+ (data) => {
+ // If payment type is jkn, then card number is required
+ if (data.paymentType === 'jkn') {
+ return data.cardNumber && data.cardNumber.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.cardNumber,
+ path: ['cardNumber'],
+ },
+ )
+ .refine(
+ (data) => {
+ // If payment type is jkn, then SEP type is required
+ if (data.paymentType === 'jkn') {
+ return data.sepType && data.sepType.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.sepType,
+ path: ['sepType'],
+ },
+ )
+ .refine(
+ (data) => {
+ // If payment type is jkn and SEP type is selected, then SEP number is required
+ if (data.paymentType === 'jkn' && data.sepType && data.sepType.trim() !== '') {
+ return data.sepNumber && data.sepNumber.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.sepNumber,
+ path: ['sepNumber'],
+ },
+ )
+
+type IntegrationEncounterFormData = z.infer
+
+export { IntegrationEncounterSchema }
+export type { IntegrationEncounterFormData }
+
diff --git a/app/schemas/prescription-item.schema.ts b/app/schemas/prescription-item.schema.ts
new file mode 100644
index 00000000..7c3ca7d3
--- /dev/null
+++ b/app/schemas/prescription-item.schema.ts
@@ -0,0 +1,10 @@
+import { z } from 'zod'
+import type { PrescriptionItem } from '~/models/prescription-item'
+
+const PrescriptionItemSchema = z.object({
+})
+
+type PrescriptionItemFormData = z.infer & PrescriptionItem
+
+export { PrescriptionItemSchema }
+export type { PrescriptionItemFormData }
diff --git a/app/schemas/prescription.schema.ts b/app/schemas/prescription.schema.ts
new file mode 100644
index 00000000..1e23f642
--- /dev/null
+++ b/app/schemas/prescription.schema.ts
@@ -0,0 +1,11 @@
+import { z } from 'zod'
+import type { Prescription } from '~/models/prescription'
+
+const PrescriptionSchema = z.object({
+ 'encounter-id': z.number().nullable().optional(),
+})
+
+type PrescriptionFormData = z.infer & Prescription
+
+export { PrescriptionSchema }
+export type { PrescriptionFormData }
diff --git a/app/schemas/specialist-position.schema.ts b/app/schemas/specialist-position.schema.ts
new file mode 100644
index 00000000..7aacef37
--- /dev/null
+++ b/app/schemas/specialist-position.schema.ts
@@ -0,0 +1,24 @@
+import { z } from 'zod'
+import type { SpecialistPosition } from '~/models/specialist-position'
+
+const SpecialistPositionSchema = z.object({
+ code: z.string({ required_error: 'Kode harus diisi' }).min(1, 'Kode minimum 1 karakter'),
+ name: z.string({ required_error: 'Nama harus diisi' }).min(1, 'Nama minimum 1 karakter'),
+ headStatus: z.boolean().optional().nullable(),
+ specialist_id: z
+ .union([
+ z.string({ required_error: 'Spesialis harus diisi' }),
+ z.number({ required_error: 'Spesialis harus diisi' }),
+ ])
+ .optional()
+ .nullable(),
+ employee_id: z
+ .union([z.string({ required_error: 'Karyawan harus diisi' }), z.number({ required_error: 'Karyawan harus diisi' })])
+ .optional()
+ .nullable(),
+})
+
+type SpecialistPositionFormData = z.infer & Partial
+
+export { SpecialistPositionSchema }
+export type { SpecialistPositionFormData }
diff --git a/app/schemas/subspecialist-position.schema.ts b/app/schemas/subspecialist-position.schema.ts
new file mode 100644
index 00000000..7f458e7b
--- /dev/null
+++ b/app/schemas/subspecialist-position.schema.ts
@@ -0,0 +1,24 @@
+import { z } from 'zod'
+import type { SubSpecialistPosition } from '~/models/subspecialist-position'
+
+const SubSpecialistPositionSchema = z.object({
+ code: z.string({ required_error: 'Kode harus diisi' }).min(1, 'Kode minimum 1 karakter'),
+ name: z.string({ required_error: 'Nama harus diisi' }).min(1, 'Nama minimum 1 karakter'),
+ headStatus: z.boolean().optional().nullable(),
+ subspecialist_id: z
+ .union([
+ z.string({ required_error: 'Spesialis harus diisi' }),
+ z.number({ required_error: 'Spesialis harus diisi' }),
+ ])
+ .optional()
+ .nullable(),
+ employee_id: z
+ .union([z.string({ required_error: 'Karyawan harus diisi' }), z.number({ required_error: 'Karyawan harus diisi' })])
+ .optional()
+ .nullable(),
+})
+
+type SubSpecialistPositionFormData = z.infer & Partial
+
+export { SubSpecialistPositionSchema }
+export type { SubSpecialistPositionFormData }
diff --git a/app/schemas/unit-position.schema.ts b/app/schemas/unit-position.schema.ts
new file mode 100644
index 00000000..2422b9a1
--- /dev/null
+++ b/app/schemas/unit-position.schema.ts
@@ -0,0 +1,24 @@
+import { z } from 'zod'
+import type { UnitPosition } from '~/models/unit-position'
+
+const UnitPositionSchema = z.object({
+ code: z.string({ required_error: 'Kode harus diisi' }).min(1, 'Kode minimum 1 karakter'),
+ name: z.string({ required_error: 'Nama harus diisi' }).min(1, 'Nama minimum 1 karakter'),
+ headStatus: z.boolean().optional().nullable(),
+ unit_id: z
+ .union([
+ z.string({ required_error: 'Unit Induk harus diisi' }),
+ z.number({ required_error: 'Unit Induk harus diisi' }),
+ ])
+ .optional()
+ .nullable(),
+ employee_id: z
+ .union([z.string({ required_error: 'Karyawan harus diisi' }), z.number({ required_error: 'Karyawan harus diisi' })])
+ .optional()
+ .nullable(),
+})
+
+type UnitPositionFormData = z.infer & Partial
+
+export { UnitPositionSchema }
+export type { UnitPositionFormData }
diff --git a/app/services/control-letter.service.ts b/app/services/control-letter.service.ts
new file mode 100644
index 00000000..29b3722b
--- /dev/null
+++ b/app/services/control-letter.service.ts
@@ -0,0 +1,28 @@
+// Base
+import * as base from './_crud-base'
+
+// Constants
+import { encounterClassCodes } from '~/lib/constants'
+
+const path = '/api/v1/control-letter'
+const name = 'control-letter'
+
+export function create(data: any) {
+ return base.create(path, data, name)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export function getDetail(id: number | string, params?: any) {
+ return base.getDetail(path, id, name, params)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data, name)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id, name)
+}
\ No newline at end of file
diff --git a/app/services/doctor.service.ts b/app/services/doctor.service.ts
index 64ab22e9..e6ae0051 100644
--- a/app/services/doctor.service.ts
+++ b/app/services/doctor.service.ts
@@ -3,7 +3,7 @@ import * as base from './_crud-base'
import type { Doctor } from "~/models/doctor";
const path = '/api/v1/doctor'
-const name = 'device'
+const name = 'doctor'
export function create(data: any) {
return base.create(path, data, name)
@@ -25,14 +25,16 @@ export function remove(id: number | string) {
return base.remove(path, id, name)
}
-export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+export async function getValueLabelList(params: any = null, useCodeAsValue = false): Promise<{ value: string; label: string }[]> {
let data: { value: string; label: string }[] = []
const result = await getList(params)
if (result.success) {
const resultData = result.body?.data || []
data = resultData.map((item: Doctor) => ({
- value: item.id,
- label: item.employee.person.name,
+ value: useCodeAsValue ? item.code
+ : item.id ? Number(item.id)
+ : item.id,
+ label: item.employee?.person?.name || '',
}))
}
return data
diff --git a/app/services/employee.service.ts b/app/services/employee.service.ts
index 366ef71e..3121e7a2 100644
--- a/app/services/employee.service.ts
+++ b/app/services/employee.service.ts
@@ -1,4 +1,5 @@
// Base
+import type { Employee } from '~/models/employee'
import * as base from './_crud-base'
const path = '/api/v1/employee'
@@ -29,9 +30,9 @@ export async function getValueLabelList(params: any = null): Promise<{ value: st
const result = await getList(params)
if (result.success) {
const resultData = result.body?.data || []
- data = resultData.map((item: any) => ({
- value: item.id ? Number(item.id) : item.code,
- label: item.person.name,
+ data = resultData.map((item: Employee) => ({
+ value: item.id,
+ label: `${item.person.frontTitle} ${item.person.name} ${item.person.endTitle}`.trim(),
}))
}
return data
diff --git a/app/services/installation-position.service.ts b/app/services/installation-position.service.ts
new file mode 100644
index 00000000..13d5e914
--- /dev/null
+++ b/app/services/installation-position.service.ts
@@ -0,0 +1,41 @@
+// Base
+import * as base from './_crud-base'
+
+// Types
+import type { Installation } from '~/models/installation'
+
+const path = '/api/v1/installation-position'
+const name = 'installation'
+
+export function create(data: any) {
+ return base.create(path, data, name)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export function getDetail(id: number | string) {
+ return base.getDetail(path, id, name)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data, name)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id, name)
+}
+
+export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+ let data: { value: string; label: string }[] = []
+ const result = await getList(params)
+ if (result.success) {
+ const resultData = result.body?.data || []
+ data = resultData.map((item: Installation) => ({
+ value: item.id ? Number(item.id) : item.code,
+ label: item.name,
+ }))
+ }
+ return data
+}
diff --git a/app/services/mcu-order-item.service.ts b/app/services/mcu-order-item.service.ts
new file mode 100644
index 00000000..b7ffbbfe
--- /dev/null
+++ b/app/services/mcu-order-item.service.ts
@@ -0,0 +1,24 @@
+import * as base from './_crud-base'
+
+const path = '/api/v1/mcu-order-item'
+const name = 'mcu-order-item'
+
+export function create(data: any) {
+ return base.create(path, data)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params)
+}
+
+export function getDetail(id: number | string, params?: any) {
+ return base.getDetail(path, id, name, params)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id)
+}
diff --git a/app/services/mcu-order.service.ts b/app/services/mcu-order.service.ts
new file mode 100644
index 00000000..77e023d7
--- /dev/null
+++ b/app/services/mcu-order.service.ts
@@ -0,0 +1,24 @@
+import * as base from './_crud-base'
+
+const path = '/api/v1/mcu-order'
+const name = 'mcu-order'
+
+export function create(data: any) {
+ return base.create(path, data)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params)
+}
+
+export function getDetail(id: number | string, params?: any) {
+ return base.getDetail(path, id, name, params)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id)
+}
diff --git a/app/services/mcu-src-category.service.ts b/app/services/mcu-src-category.service.ts
new file mode 100644
index 00000000..c154b1dc
--- /dev/null
+++ b/app/services/mcu-src-category.service.ts
@@ -0,0 +1,25 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/v1/mcu-src-category'
+const name = 'mcu-src-category'
+
+export function create(data: any) {
+ return base.create(path, data, name)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export function getDetail(id: number | string) {
+ return base.getDetail(path, id, name)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data, name)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id, name)
+}
diff --git a/app/services/mcu-src.service.ts b/app/services/mcu-src.service.ts
new file mode 100644
index 00000000..a7a466b8
--- /dev/null
+++ b/app/services/mcu-src.service.ts
@@ -0,0 +1,25 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/v1/mcu-src'
+const name = 'mcu-src'
+
+export function create(data: any) {
+ return base.create(path, data, name)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export function getDetail(id: number | string) {
+ return base.getDetail(path, id, name)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data, name)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id, name)
+}
diff --git a/app/services/patient.service.ts b/app/services/patient.service.ts
index 7591f356..6a7742c3 100644
--- a/app/services/patient.service.ts
+++ b/app/services/patient.service.ts
@@ -40,6 +40,22 @@ export async function getPatientDetail(id: number) {
}
}
+export async function getPatientByIdentifier(search: string) {
+ try {
+ const urlPath = search.length === 16 ? `by-resident-identity/search=${encodeURIComponent(search)}` : `/search/${search}`
+ const url = `${mainUrl}/${urlPath}`
+ const resp = await xfetch(url, 'GET')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ result.type = urlPath.includes('by-resident-identity') ? 'resident-identity' : 'identity'
+ return result
+ } catch (error) {
+ console.error('Error fetching patient by identifier:', error)
+ throw new Error('Failed to get patient by identifier')
+ }
+}
+
export async function postPatient(record: any) {
try {
const resp = await xfetch(mainUrl, 'POST', record)
diff --git a/app/services/prescription-item.service.ts b/app/services/prescription-item.service.ts
new file mode 100644
index 00000000..22649e14
--- /dev/null
+++ b/app/services/prescription-item.service.ts
@@ -0,0 +1,23 @@
+import * as base from './_crud-base'
+
+const path = '/api/v1/prescription-item'
+
+export function create(data: any) {
+ return base.create(path, data)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params)
+}
+
+export function getDetail(id: number | string) {
+ return base.getDetail(path, id)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id)
+}
diff --git a/app/services/prescription.service.ts b/app/services/prescription.service.ts
new file mode 100644
index 00000000..150357ab
--- /dev/null
+++ b/app/services/prescription.service.ts
@@ -0,0 +1,24 @@
+import * as base from './_crud-base'
+
+const path = '/api/v1/prescription'
+const name = 'prescription'
+
+export function create(data: any) {
+ return base.create(path, data)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params)
+}
+
+export function getDetail(id: number | string, params?: any) {
+ return base.getDetail(path, id, name, params)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id)
+}
diff --git a/app/services/specialist-position.service.ts b/app/services/specialist-position.service.ts
new file mode 100644
index 00000000..6966ca60
--- /dev/null
+++ b/app/services/specialist-position.service.ts
@@ -0,0 +1,25 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/v1/specialist-position'
+const name = 'specialist-position'
+
+export function create(data: any) {
+ return base.create(path, data, name)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export function getDetail(id: number | string) {
+ return base.getDetail(path, id, name)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data, name)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id, name)
+}
diff --git a/app/services/specialist.service.ts b/app/services/specialist.service.ts
index c2c34e3f..d4c81b5c 100644
--- a/app/services/specialist.service.ts
+++ b/app/services/specialist.service.ts
@@ -3,6 +3,7 @@ import * as base from './_crud-base'
// Types
import type { Specialist } from '~/models/specialist'
+import type { TreeItem } from '~/models/_base'
const path = '/api/v1/specialist'
const name = 'specialist'
@@ -15,8 +16,8 @@ export function getList(params: any = null) {
return base.getList(path, params, name)
}
-export function getDetail(id: number | string) {
- return base.getDetail(path, id, name)
+export function getDetail(id: number | string, params?: any) {
+ return base.getDetail(path, id, name, params)
}
export function update(id: number | string, data: any) {
@@ -27,16 +28,35 @@ export function remove(id: number | string) {
return base.remove(path, id, name)
}
-export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+export async function getValueLabelList(params: any = null, useCodeAsValue = false): Promise<{ value: string; label: string }[]> {
let data: { value: string; label: string }[] = []
const result = await getList(params)
if (result.success) {
const resultData = result.body?.data || []
data = resultData.map((item: Specialist) => ({
- value: item.id ? Number(item.id) : item.code,
+ value: useCodeAsValue ? item.code
+ : item.id ? Number(item.id)
+ : item.id,
label: item.name,
parent: item.unit_id ? Number(item.unit_id) : null,
}))
}
return data
}
+
+/**
+ * Convert specialist response to TreeItem[] with subspecialist children
+ * @param specialists Array of specialist objects from API
+ * @returns TreeItem[]
+ */
+export function getValueTreeItems(specialists: any[], byCode = true): TreeItem[] {
+ return specialists.map((specialist: Specialist) => ({
+ value: byCode ? String(specialist.code) : String(specialist.id),
+ label: specialist.name,
+ hasChildren: Array.isArray(specialist.subspecialists) && specialist.subspecialists.length > 0,
+ children:
+ Array.isArray(specialist.subspecialists) && specialist.subspecialists.length > 0
+ ? getValueTreeItems(specialist.subspecialists)
+ : undefined,
+ }))
+}
diff --git a/app/services/subspecialist-position.service.ts b/app/services/subspecialist-position.service.ts
new file mode 100644
index 00000000..9653100b
--- /dev/null
+++ b/app/services/subspecialist-position.service.ts
@@ -0,0 +1,25 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/v1/subspecialist-position'
+const name = 'subspecialist-position'
+
+export function create(data: any) {
+ return base.create(path, data, name)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export function getDetail(id: number | string) {
+ return base.getDetail(path, id, name)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data, name)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id, name)
+}
diff --git a/app/services/subspecialist.service.ts b/app/services/subspecialist.service.ts
index 94e70a09..f13c715f 100644
--- a/app/services/subspecialist.service.ts
+++ b/app/services/subspecialist.service.ts
@@ -15,8 +15,8 @@ export function getList(params: any = null) {
return base.getList(path, params, name)
}
-export function getDetail(id: number | string) {
- return base.getDetail(path, id, name)
+export function getDetail(id: number | string, params?: any) {
+ return base.getDetail(path, id, name, params)
}
export function update(id: number | string, data: any) {
@@ -27,13 +27,15 @@ export function remove(id: number | string) {
return base.remove(path, id, name)
}
-export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+export async function getValueLabelList(params: any = null, useCodeAsValue = false): Promise<{ value: string; label: string }[]> {
let data: { value: string; label: string }[] = []
const result = await getList(params)
if (result.success) {
const resultData = result.body?.data || []
data = resultData.map((item: Subspecialist) => ({
- value: item.id ? Number(item.id) : item.code,
+ value: useCodeAsValue ? item.code
+ : item.id ? Number(item.id)
+ : item.id,
label: item.name,
parent: item.specialist_id ? Number(item.specialist_id) : null,
}))
diff --git a/app/services/unit-position.service.ts b/app/services/unit-position.service.ts
new file mode 100644
index 00000000..ee9cf89c
--- /dev/null
+++ b/app/services/unit-position.service.ts
@@ -0,0 +1,25 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/v1/unit-position'
+const name = 'unit-position'
+
+export function create(data: any) {
+ return base.create(path, data, name)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export function getDetail(id: number | string) {
+ return base.getDetail(path, id, name)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data, name)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id, name)
+}
diff --git a/app/services/unit.service.ts b/app/services/unit.service.ts
index 438625f1..402504b6 100644
--- a/app/services/unit.service.ts
+++ b/app/services/unit.service.ts
@@ -2,7 +2,7 @@
import * as base from './_crud-base'
// Types
-import type { Unit } from "~/models/unit";
+import type { Unit } from '~/models/unit'
const path = '/api/v1/unit'
const name = 'unit'
@@ -27,13 +27,15 @@ export function remove(id: number | string) {
return base.remove(path, id, name)
}
-export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+export async function getValueLabelList(params: any = null, useCodeAsValue = false): Promise<{ value: string; label: string }[]> {
let data: { value: string; label: string }[] = []
const result = await getList(params)
if (result.success) {
const resultData = result.body?.data || []
data = resultData.map((item: Unit) => ({
- value: item.id,
+ value: useCodeAsValue ? item.code
+ : item.id ? Number(item.id)
+ : item.id,
label: item.name,
}))
}
diff --git a/app/services/vclaim-control-letter.service.ts b/app/services/vclaim-control-letter.service.ts
new file mode 100644
index 00000000..007e91c5
--- /dev/null
+++ b/app/services/vclaim-control-letter.service.ts
@@ -0,0 +1,29 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim-swagger/RencanaKontrol'
+const name = 'rencana-kontrol'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.letterNumber && params.mode === 'by-control') {
+ url += `/noSuratKontrol/${params.letterNumber}`
+ }
+ if (params?.letterNumber && params.mode === 'by-card') {
+ url += `/noka/${params.letterNumber}`
+ }
+ if (params?.letterNumber && params.mode === 'by-sep') {
+ url += `/${params.letterNumber}`
+ }
+ if (params?.letterNumber && params.mode === 'by-schedule') {
+ url += `/jadwalDokter?jeniskontrol=${params.controlType}&kodepoli=${params.poliCode}&tanggalkontrol=${params.controlDate}`
+ delete params.controlType
+ delete params.poliCode
+ delete params.controlDate
+ }
+ if (params) {
+ delete params.letterNumber
+ delete params.mode
+ }
+ return base.getList(url, params, name)
+}
\ No newline at end of file
diff --git a/app/services/vclaim-diagnose-referral.service.ts b/app/services/vclaim-diagnose-referral.service.ts
new file mode 100644
index 00000000..34b94780
--- /dev/null
+++ b/app/services/vclaim-diagnose-referral.service.ts
@@ -0,0 +1,9 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/reference/diagnose-prb'
+const name = 'diagnose-referral'
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
diff --git a/app/services/vclaim-diagnose.service.ts b/app/services/vclaim-diagnose.service.ts
new file mode 100644
index 00000000..a676f516
--- /dev/null
+++ b/app/services/vclaim-diagnose.service.ts
@@ -0,0 +1,28 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/reference/diagnose'
+const name = 'diagnose'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params && params?.diagnosa) {
+ url += `/${params.diagnosa}`
+ delete params.diagnosa
+ }
+ return base.getList(url, params, name)
+}
+
+export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+ let data: { value: string; label: string }[] = []
+ const result = await getList(params)
+ if (result.success) {
+ const resultData = result.body?.response?.diagnosa || []
+ const resultUnique = [...new Map(resultData.map((item: any) => [item.kode, item])).values()]
+ data = resultUnique.map((item: any) => ({
+ value: item.kode ? String(item.kode) : '',
+ label: `${item.kode} - ${item.nama}`,
+ }))
+ }
+ return data
+}
diff --git a/app/services/vclaim-doctor.service.ts b/app/services/vclaim-doctor.service.ts
new file mode 100644
index 00000000..0d5ec9dc
--- /dev/null
+++ b/app/services/vclaim-doctor.service.ts
@@ -0,0 +1,36 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/reference/responsible-doctor'
+const name = 'responsible-doctor'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.serviceType) {
+ url += `/${params.serviceType}`
+ delete params.serviceType
+ }
+ if (params?.serviceDate) {
+ url += `/${params.serviceDate}`
+ delete params.serviceDate
+ }
+ if (params?.specialistCode || (Number(params.specialistCode) === 0)) {
+ url += `/${params.specialistCode}`
+ delete params.specialistCode
+ }
+ return base.getList(url, params, name)
+}
+
+export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+ let data: { value: string; label: string }[] = []
+ const result = await getList(params)
+ if (result.success) {
+ const resultData = result.body?.response?.list || []
+ const resultUnique = [...new Map(resultData.map((item: any) => [item.kode, item])).values()]
+ data = resultUnique.map((item: any) => ({
+ value: item.kode ? String(item.kode) : '',
+ label: `${item.kode} - ${item.nama}`,
+ }))
+ }
+ return data
+}
diff --git a/app/services/vclaim-healthcare.service.ts b/app/services/vclaim-healthcare.service.ts
new file mode 100644
index 00000000..09cc0089
--- /dev/null
+++ b/app/services/vclaim-healthcare.service.ts
@@ -0,0 +1,32 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/reference/healthcare'
+const name = 'healthcare'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.healthcare) {
+ url += `/${params.healthcare}`
+ delete params.healthcare
+ }
+ if (params?.healthcareType) {
+ url += `/${params.healthcareType}`
+ delete params.healthcareType
+ }
+ return base.getList(url, params, name)
+}
+
+export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+ let data: { value: string; label: string }[] = []
+ const result = await getList(params)
+ if (result.success) {
+ const resultData = result.body?.response?.faskes || []
+ const resultUnique = [...new Map(resultData.map((item: any) => [item.kode, item])).values()]
+ data = resultUnique.map((item: any) => ({
+ value: item.kode ? String(item.kode) : '',
+ label: `${item.kode} - ${item.nama}`,
+ }))
+ }
+ return data
+}
diff --git a/app/services/vclaim-medicine.service.ts b/app/services/vclaim-medicine.service.ts
new file mode 100644
index 00000000..15a42050
--- /dev/null
+++ b/app/services/vclaim-medicine.service.ts
@@ -0,0 +1,22 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/reference/medicine'
+const name = 'medicine'
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+ let data: { value: string; label: string }[] = []
+ const result = await getList(params)
+ if (result.success) {
+ const resultData = result.body?.response?.list || []
+ data = resultData.map((item: any) => ({
+ value: item.kode ? String(item.kode) : '',
+ label: item.nama,
+ }))
+ }
+ return data
+}
diff --git a/app/services/vclaim-member.service.ts b/app/services/vclaim-member.service.ts
new file mode 100644
index 00000000..bbe054ec
--- /dev/null
+++ b/app/services/vclaim-member.service.ts
@@ -0,0 +1,21 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/member'
+const name = 'member'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.number && params.mode === 'by-identity') {
+ url += `/nik/${params.number}/${params.date}`
+ }
+ if (params?.number && params.mode === 'by-card') {
+ url += `/bpjs/${params.number}/${params.date}`
+ }
+ if (params) {
+ delete params.number
+ delete params.mode
+ delete params.date
+ }
+ return base.getList(url, params, name)
+}
diff --git a/app/services/vclaim-monitoring-history.service.ts b/app/services/vclaim-monitoring-history.service.ts
new file mode 100644
index 00000000..ac9f2113
--- /dev/null
+++ b/app/services/vclaim-monitoring-history.service.ts
@@ -0,0 +1,17 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/monitoring/hist'
+const name = 'monitoring-history'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params && params?.cardNumber) {
+ url += `/${params.cardNumber}/${params.startDate}/${params.endDate}`
+ delete params.cardNumber
+ delete params.startDate
+ delete params.endDate
+ }
+
+ return base.getList(url, params, name)
+}
diff --git a/app/services/vclaim-monitoring-visit.service.ts b/app/services/vclaim-monitoring-visit.service.ts
new file mode 100644
index 00000000..0c5da64e
--- /dev/null
+++ b/app/services/vclaim-monitoring-visit.service.ts
@@ -0,0 +1,71 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/monitoring/visit'
+const name = 'monitoring-visit'
+
+const dummyResponse = {
+ metaData: {
+ code: '200',
+ message: 'Sukses',
+ },
+ response: {
+ sep: [
+ {
+ diagnosa: 'K65.0',
+ jnsPelayanan: 'R.Inap',
+ kelasRawat: '2',
+ nama: 'HANIF ABDURRAHMAN',
+ noKartu: '0001819122189',
+ noSep: '0301R00110170000004',
+ noRujukan: '0301U01108180200084',
+ poli: null,
+ tglPlgSep: '2017-10-03',
+ tglSep: '2017-10-01',
+ },
+ {
+ diagnosa: 'I50.0',
+ jnsPelayanan: 'R.Inap',
+ kelasRawat: '3',
+ nama: 'ASRIZAL',
+ noKartu: '0002283324674',
+ noSep: '0301R00110170000005',
+ noRujukan: '0301U01108180200184',
+ poli: null,
+ tglPlgSep: '2017-10-10',
+ tglSep: '2017-10-01',
+ },
+ ],
+ },
+}
+
+export async function getList(params: any = null) {
+ try {
+ let url = path
+ if (params?.date && params.serviceType) {
+ url += `/${params.date}/${params.serviceType}`
+ }
+ if (params) {
+ delete params.date
+ delete params.serviceType
+ }
+ const resp = await base.getList(url, params, name)
+
+ // Jika success false, return dummy response
+ if (!resp.success || !resp.body?.response) {
+ return {
+ success: true,
+ body: dummyResponse,
+ }
+ }
+
+ return resp
+ } catch (error) {
+ // Jika terjadi error, return dummy response
+ console.error(`Error fetching ${name}s:`, error)
+ return {
+ success: true,
+ body: dummyResponse,
+ }
+ }
+}
diff --git a/app/services/vclaim-reference-hospital-letter.service.ts b/app/services/vclaim-reference-hospital-letter.service.ts
new file mode 100644
index 00000000..115f6558
--- /dev/null
+++ b/app/services/vclaim-reference-hospital-letter.service.ts
@@ -0,0 +1,16 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim-swagger/Rujukan/RS'
+const name = 'rujukan-rumah-sakit'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.letterNumber) {
+ url += `/${params.letterNumber}`
+ }
+ if (params) {
+ delete params.letterNumber
+ }
+ return base.getList(url, params, name)
+}
\ No newline at end of file
diff --git a/app/services/vclaim-reference-letter.service.ts b/app/services/vclaim-reference-letter.service.ts
new file mode 100644
index 00000000..0a721d19
--- /dev/null
+++ b/app/services/vclaim-reference-letter.service.ts
@@ -0,0 +1,16 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim-swagger/RujukanKhusus'
+const name = 'rujukan-khusus'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.letterNumber) {
+ url += `?noRujukan=${params.letterNumber}`
+ }
+ if (params) {
+ delete params.letterNumber
+ }
+ return base.getList(url, params, name)
+}
\ No newline at end of file
diff --git a/app/services/vclaim-region-city.service.ts b/app/services/vclaim-region-city.service.ts
new file mode 100644
index 00000000..4ebfca20
--- /dev/null
+++ b/app/services/vclaim-region-city.service.ts
@@ -0,0 +1,27 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/reference/regency'
+const name = 'cities'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.province) {
+ url += `/${params.province}`
+ delete params.province
+ }
+ return base.getList(url, params, name)
+}
+
+export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+ let data: { value: string; label: string }[] = []
+ const result = await getList(params)
+ if (result.success) {
+ const resultData = result.body?.response?.list || []
+ data = resultData.map((item: any) => ({
+ value: item.kode ? String(item.kode) : '',
+ label: item.nama,
+ }))
+ }
+ return data
+}
diff --git a/app/services/vclaim-region-district.service.ts b/app/services/vclaim-region-district.service.ts
new file mode 100644
index 00000000..0b0585a8
--- /dev/null
+++ b/app/services/vclaim-region-district.service.ts
@@ -0,0 +1,27 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/reference/district'
+const name = 'districts'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.city) {
+ url += `/${params.city}`
+ delete params.city
+ }
+ return base.getList(url, params, name)
+}
+
+export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+ let data: { value: string; label: string }[] = []
+ const result = await getList(params)
+ if (result.success) {
+ const resultData = result.body?.response?.list || []
+ data = resultData.map((item: any) => ({
+ value: item.kode ? String(item.kode) : '',
+ label: item.nama,
+ }))
+ }
+ return data
+}
diff --git a/app/services/vclaim-region-province.service.ts b/app/services/vclaim-region-province.service.ts
new file mode 100644
index 00000000..5d58bb26
--- /dev/null
+++ b/app/services/vclaim-region-province.service.ts
@@ -0,0 +1,22 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/reference/province'
+const name = 'provinces'
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+ let data: { value: string; label: string }[] = []
+ const result = await getList(params)
+ if (result.success) {
+ const resultData = result.body?.response?.list || []
+ data = resultData.map((item: any) => ({
+ value: item.kode ? String(item.kode) : '',
+ label: item.nama,
+ }))
+ }
+ return data
+}
diff --git a/app/services/vclaim-sep.service.ts b/app/services/vclaim-sep.service.ts
new file mode 100644
index 00000000..fdccc9c4
--- /dev/null
+++ b/app/services/vclaim-sep.service.ts
@@ -0,0 +1,95 @@
+// Base
+import * as base from './_crud-base'
+
+// Types
+import type { IntegrationBpjsFormData } from '~/schemas/integration-bpjs.schema'
+
+const path = '/api/vclaim-swagger/sep'
+const name = 'sep'
+
+export function create(data: any) {
+ return base.create(path, data, name)
+}
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.number) {
+ url += `/${params.number}`
+ delete params.number
+ }
+ return base.getList(url, params, name)
+}
+
+export function makeSepData(
+ data: IntegrationBpjsFormData & {
+ referralFrom?: string
+ referralTo?: string
+ referralLetterDate?: string
+ referralLetterNumber?: string
+ },
+) {
+ const content = {
+ noKartu: data.cardNumber || '',
+ tglSep: data.sepDate,
+ ppkPelayanan: data.fromClinic || '',
+ jnsPelayanan: data.admissionType ? String(data.admissionType) : '1',
+ noMR: data.medicalRecordNumber || '',
+ catatan: data.note || '',
+ diagAwal: data.initialDiagnosis || '',
+ poli: {
+ tujuan: data.destinationClinic || '',
+ eksekutif: data.clinicExcecutive === 'yes' ? '1' : '0',
+ },
+ cob: {
+ cob: data.cob === 'yes' ? '1' : '0',
+ },
+ katarak: {
+ katarak: data.cataract === 'yes' ? '1' : '0',
+ },
+ tujuanKunj: data.purposeOfVisit || '',
+ flagProcedure: data.procedureType || '',
+ kdPenunjang: data.supportCode || '',
+ assesmentPel: data.serviceAssessment || '',
+ skdp: {
+ noSurat: ['3'].includes(data.admissionType) ? data.referralLetterNumber : '',
+ kodeDPJP: ['3'].includes(data.admissionType)? data.attendingDoctor : '',
+ },
+ rujukan: {
+ asalRujukan: ['2'].includes(data.admissionType) ? data?.referralFrom || '' : '',
+ tglRujukan: ['2'].includes(data.admissionType) ? data?.referralLetterDate || '' : '',
+ noRujukan: ['2'].includes(data.admissionType) ? data?.referralLetterNumber || '' : '',
+ ppkRujukan: ['2'].includes(data.admissionType) ? data?.referralTo || '' : '',
+ },
+ klsRawat: {
+ klsRawatHak: data.classLevel || '',
+ klsRawatNaik: data.classLevelUpgrade || '',
+ pembiayaan: data.classPaySource || '',
+ penanggungJawab: data.responsiblePerson || '',
+ },
+ dpjpLayan: data.attendingDoctor || '',
+ noTelp: data.phoneNumber || '',
+ user: data.patientName || '',
+ jaminan: {
+ lakaLantas: data.trafficAccident || '0',
+ noLP: data.lpNumber || '',
+ penjamin: {
+ tglKejadian: data.accidentDate || '',
+ keterangan: data.accidentNote || '',
+ suplesi: {
+ suplesi: data.suplesi === 'yes' ? '1' : '0',
+ noSepSuplesi: data.suplesiNumber || '',
+ lokasiLaka: {
+ kdPropinsi: data.accidentProvince || '',
+ kdKabupaten: data.accidentCity || '',
+ kdKecamatan: data.accidentDistrict || '',
+ },
+ },
+ },
+ },
+ }
+ return {
+ request: {
+ t_sep: content,
+ },
+ }
+}
diff --git a/app/services/vclaim-unit.service.ts b/app/services/vclaim-unit.service.ts
new file mode 100644
index 00000000..970a3f00
--- /dev/null
+++ b/app/services/vclaim-unit.service.ts
@@ -0,0 +1,28 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/reference/unit'
+const name = 'unit'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.unitCode) {
+ url += `/${params.unitCode}`
+ delete params.unitCode
+ }
+ return base.getList(url, params, name)
+}
+
+export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+ let data: { value: string; label: string }[] = []
+ const result = await getList(params)
+ if (result.success) {
+ const resultData = result.body?.response?.faskes || []
+ const resultUnique = [...new Map(resultData.map((item: any) => [item.kode, item])).values()]
+ data = resultUnique.map((item: any) => ({
+ value: item.kode ? String(item.kode) : '',
+ label: `${item.kode} - ${item.nama}`,
+ }))
+ }
+ return data
+}
diff --git a/app/stores/user.ts b/app/stores/user.ts
index 14ab7134..97bd4665 100644
--- a/app/stores/user.ts
+++ b/app/stores/user.ts
@@ -5,12 +5,13 @@ export const useUserStore = defineStore(
// const token = useCookie('authentication')
const isAuthenticated = computed(() => !!user.value)
+
const userRole = computed(() => {
- const roles = user.value?.roles || []
- return roles.map((input: string) => {
- const parts = input.split('-')
- return parts.length > 1 ? parts[1]: parts[0]
- })
+ return user.value?.roles || []
+ // return roles.map((input: string) => {
+ // const parts = input.split('|')
+ // return parts.length > 1 ? parts[1]: parts[0]
+ // })
})
const login = async (userData: any) => {
@@ -21,12 +22,30 @@ export const useUserStore = defineStore(
user.value = null
}
+ const setActiveRole = (role: string) => {
+ if (user.value && user.value.roles.includes(role)) {
+ user.value.activeRole = role
+ }
+ }
+
+ const getActiveRole = () => {
+ if (user.value?.activeRole) {
+ return user.value.activeRole
+ }
+ if (user.value?.roles.length > 0) {
+ user.value.activeRole = user.value.roles[0]
+ return user.value.activeRole
+ }
+ }
+
return {
user,
isAuthenticated,
userRole,
login,
logout,
+ setActiveRole,
+ getActiveRole,
}
},
{
diff --git a/nuxt.config.ts b/nuxt.config.ts
index 55cdb6bf..f4f0b231 100644
--- a/nuxt.config.ts
+++ b/nuxt.config.ts
@@ -5,8 +5,12 @@ export default defineNuxtConfig({
devtools: { enabled: true },
runtimeConfig: {
API_ORIGIN: process.env.NUXT_API_ORIGIN || 'http://localhost:3000',
+ VCLAIM: process.env.NUXT_API_VCLAIM || 'http://localhost:3000',
+ VCLAIM_SWAGGER: process.env.NUXT_API_VCLAIM_SWAGGER || 'http://localhost:3000',
public: {
API_ORIGIN: process.env.NUXT_API_ORIGIN || 'http://localhost:3000',
+ VCLAIM: process.env.NUXT_API_VCLAIM || 'http://localhost:3000',
+ VCLAIM_SWAGGER: process.env.NUXT_API_VCLAIM_SWAGGER || 'http://localhost:3000',
},
},
ssr: false,
diff --git a/public/side-menu-items/blank.json b/public/side-menu-items/blank.json
new file mode 100644
index 00000000..9d7a78b3
--- /dev/null
+++ b/public/side-menu-items/blank.json
@@ -0,0 +1,12 @@
+[
+ {
+ "heading": "Menu Utama",
+ "items": [
+ {
+ "title": "Dashboard",
+ "icon": "i-lucide-home",
+ "link": "/"
+ }
+ ]
+ }
+]
diff --git a/public/side-menu-items/div-crd.json b/public/side-menu-items/div-crd.json
new file mode 100644
index 00000000..9d7a78b3
--- /dev/null
+++ b/public/side-menu-items/div-crd.json
@@ -0,0 +1,12 @@
+[
+ {
+ "heading": "Menu Utama",
+ "items": [
+ {
+ "title": "Dashboard",
+ "icon": "i-lucide-home",
+ "link": "/"
+ }
+ ]
+ }
+]
diff --git a/public/side-menu-items/doc.json b/public/side-menu-items/emp-doc.json
similarity index 96%
rename from public/side-menu-items/doc.json
rename to public/side-menu-items/emp-doc.json
index e3ab2cdf..b7ecb430 100644
--- a/public/side-menu-items/doc.json
+++ b/public/side-menu-items/emp-doc.json
@@ -84,12 +84,12 @@
{
"title": "Kemoterapi",
"icon": "i-lucide-droplets",
- "link": "/outpatient-action/cemotherapy"
+ "link": "/outpation-action/chemotherapy"
},
{
"title": "Hemofilia",
"icon": "i-lucide-droplet-off",
- "link": "/outpatient-action/hemophilia/encounter"
+ "link": "/outpation-action/hemophilia"
}
]
},
diff --git a/public/side-menu-items/lab.json b/public/side-menu-items/emp-lab.json
similarity index 100%
rename from public/side-menu-items/lab.json
rename to public/side-menu-items/emp-lab.json
diff --git a/public/side-menu-items/miw.json b/public/side-menu-items/emp-mid.json
similarity index 93%
rename from public/side-menu-items/miw.json
rename to public/side-menu-items/emp-mid.json
index ebb43da6..80eeee7c 100644
--- a/public/side-menu-items/miw.json
+++ b/public/side-menu-items/emp-mid.json
@@ -20,7 +20,7 @@
{
"title": "Rehabilitasi Medik",
"icon": "i-lucide-bike",
- "link": "/rehab/polyclinic-queue"
+ "link": "/rehab/encounter-queue"
},
{
"title": "Rawat Inap",
diff --git a/public/side-menu-items/nur.json b/public/side-menu-items/emp-nur.json
similarity index 89%
rename from public/side-menu-items/nur.json
rename to public/side-menu-items/emp-nur.json
index 8185456c..1c993144 100644
--- a/public/side-menu-items/nur.json
+++ b/public/side-menu-items/emp-nur.json
@@ -13,10 +13,10 @@
"children": [
{
"title": "Antrian Poliklinik",
- "link": "/outpatient/polyclinic-queue"
+ "link": "/outpatient/encounter-queue"
},
{
- "title": "Pendaftaran",
+ "title": "Kunjungan",
"link": "/outpatient/encounter"
}
]
@@ -30,7 +30,7 @@
"link": "/emergency/triage"
},
{
- "title": "Pemeriksaan",
+ "title": "Kunjungan",
"link": "/emergency/encounter"
}
]
@@ -42,7 +42,7 @@
"children": [
{
"title": "Antrean Poliklinik",
- "link": "/rehab/polyclinic-queue"
+ "link": "/rehab/encounter-queue"
},
{
"title": "Kunjungan",
@@ -63,7 +63,7 @@
{
"title": "Kemoterapi",
"icon": "i-lucide-droplets",
- "link": "/outpation-action/cemotherapy"
+ "link": "/outpation-action/chemotherapy"
},
{
"title": "Hemofilia",
diff --git a/public/side-menu-items/nut.json b/public/side-menu-items/emp-nut.json
similarity index 93%
rename from public/side-menu-items/nut.json
rename to public/side-menu-items/emp-nut.json
index 4368b22e..ef71282a 100644
--- a/public/side-menu-items/nut.json
+++ b/public/side-menu-items/emp-nut.json
@@ -35,12 +35,12 @@
{
"title": "Kemoterapi",
"icon": "i-lucide-droplets",
- "link": "/outpatient-action/cemotherapy"
+ "link": "/outpation-action/chemotherapy"
},
{
"title": "Hemofilia",
"icon": "i-lucide-droplet-off",
- "link": "/outpatient-action/hemophilia"
+ "link": "/outpation-action/hemophilia"
}
]
},
diff --git a/public/side-menu-items/pha.json b/public/side-menu-items/emp-pha.json
similarity index 100%
rename from public/side-menu-items/pha.json
rename to public/side-menu-items/emp-pha.json
diff --git a/public/side-menu-items/reg.json b/public/side-menu-items/emp-reg.json
similarity index 100%
rename from public/side-menu-items/reg.json
rename to public/side-menu-items/emp-reg.json
diff --git a/public/side-menu-items/sys.json b/public/side-menu-items/system.json
similarity index 90%
rename from public/side-menu-items/sys.json
rename to public/side-menu-items/system.json
index 19491069..5bf62f36 100644
--- a/public/side-menu-items/sys.json
+++ b/public/side-menu-items/system.json
@@ -17,7 +17,7 @@
},
{
"title": "Antrian Poliklinik",
- "link": "/outpatient/polyclinic-queue"
+ "link": "/outpatient/encounter-queue"
},
{
"title": "Kunjungan",
@@ -57,7 +57,7 @@
},
{
"title": "Antrean Poliklinik",
- "link": "/rehab/polyclinic-queue"
+ "link": "/rehab/encounter-queue"
},
{
"title": "Kunjungan",
@@ -139,7 +139,7 @@
{
"title": "Kemoterapi",
"icon": "i-lucide-droplets",
- "link": "/outpation-action/cemotherapy"
+ "link": "/outpation-action/chemotherapy"
},
{
"title": "Hemofilia",
@@ -199,6 +199,11 @@
"title": "Peserta",
"icon": "i-lucide-circuit-board",
"link": "/integration/bpjs/member"
+ },
+ {
+ "title": "Surat Kontrol",
+ "icon": "i-lucide-circuit-board",
+ "link": "/integration/bpjs/control-letter"
}
]
},
@@ -320,21 +325,41 @@
"title": "Divisi",
"link": "/org-src/division"
},
+ {
+ "title": "Divisi - Posisi",
+ "link": "/org-src/division-position"
+ },
{
"title": "Instalasi",
"link": "/org-src/installation"
},
+ {
+ "title": "Instalasi - Posisi",
+ "link": "/org-src/installation-position"
+ },
{
"title": "Unit",
"link": "/org-src/unit"
},
+ {
+ "title": "Unit - Posisi",
+ "link": "/org-src/unit-position"
+ },
{
"title": "Spesialis",
"link": "/org-src/specialist"
},
+ {
+ "title": "Spesialis - Posisi",
+ "link": "/org-src/specialist-position"
+ },
{
"title": "Sub Spesialis",
"link": "/org-src/subspecialist"
+ },
+ {
+ "title": "Sub Spesialis - Posisi",
+ "link": "/org-src/subspecialist-position"
}
]
},
diff --git a/server/api/[...req].ts b/server/api/[...req].ts
index 8404cc2a..5948eda6 100644
--- a/server/api/[...req].ts
+++ b/server/api/[...req].ts
@@ -5,11 +5,20 @@ export default defineEventHandler(async (event) => {
const headers = getRequestHeaders(event)
const url = getRequestURL(event)
const config = useRuntimeConfig()
-
- const apiOrigin = config.public.API_ORIGIN
- const pathname = url.pathname.replace(/^\/api/, '')
- const targetUrl = apiOrigin + pathname + (url.search || '')
+ const apiOrigin = config.public.API_ORIGIN
+ const apiVclaim = config.public.VCLAIM
+ const apiVclaimSwagger = config.public.VCLAIM_SWAGGER
+ const pathname = url.pathname.replace(/^\/api/, '')
+ const isVclaim = pathname.includes('/vclaim')
+
+ let targetUrl = apiOrigin + pathname + (url.search || '')
+ if (pathname.includes('/vclaim')) {
+ targetUrl = apiVclaim + pathname.replace('/vclaim', '') + (url.search || '')
+ }
+ if (pathname.includes('/vclaim-swagger')) {
+ targetUrl = apiVclaimSwagger + pathname.replace('/vclaim-swagger', '') + (url.search || '')
+ }
const verificationId = headers['verification-id'] as string | undefined
let bearer = ''
@@ -21,8 +30,10 @@ export default defineEventHandler(async (event) => {
}
const forwardHeaders = new Headers()
- if (headers['content-type']) forwardHeaders.set('Content-Type', headers['content-type'])
- forwardHeaders.set('Authorization', `Bearer ${bearer}`)
+ if (!isVclaim) {
+ if (headers['content-type']) forwardHeaders.set('Content-Type', headers['content-type'])
+ forwardHeaders.set('Authorization', `Bearer ${bearer}`)
+ }
let body: any
if (['POST', 'PATCH'].includes(method!)) {
@@ -41,5 +52,15 @@ export default defineEventHandler(async (event) => {
body,
})
+ if (isVclaim) {
+ const resClone = res.clone()
+ const responseBody = await resClone.json()
+ return {
+ status: resClone.status,
+ headers: resClone.headers,
+ ...responseBody,
+ }
+ }
+
return res
})