+
Belum Ada Data
-
-
+
+
+ Order #{{ data.length - idx }} - {{ item.issuedAt?.substring(0, 10) || item.createdAt?.substring(0, 10) }} - {{ item.status_code }}
+
+
+
+ DPJP
+
+ {{ item.doctor?.employee?.person?.name || '-' }}
+
+
+
+ PPDS
+
+ ...........
+
+
+
+
+
+
+
+
diff --git a/app/components/app/sep/entry-form.vue b/app/components/app/sep/entry-form.vue
index e48d23ec..35956ad7 100644
--- a/app/components/app/sep/entry-form.vue
+++ b/app/components/app/sep/entry-form.vue
@@ -1,91 +1,245 @@
-
-
diff --git a/app/components/app/sep/table-history-sep.vue b/app/components/app/sep/table-history-sep.vue
deleted file mode 100644
index bfe00e51..00000000
--- a/app/components/app/sep/table-history-sep.vue
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
-
diff --git a/app/components/app/sep/table-search-letter.vue b/app/components/app/sep/table-search-letter.vue
deleted file mode 100644
index 64e65ff6..00000000
--- a/app/components/app/sep/table-search-letter.vue
+++ /dev/null
@@ -1,104 +0,0 @@
-
-
-
-
-
diff --git a/app/components/app/sep/table-search-patient.vue b/app/components/app/sep/table-search-patient.vue
deleted file mode 100644
index 13a78651..00000000
--- a/app/components/app/sep/table-search-patient.vue
+++ /dev/null
@@ -1,100 +0,0 @@
-
-
-
-
-
diff --git a/app/components/app/sep/view-history.vue b/app/components/app/sep/view-history.vue
new file mode 100644
index 00000000..a6a6091c
--- /dev/null
+++ b/app/components/app/sep/view-history.vue
@@ -0,0 +1,46 @@
+
+
+
+
+
diff --git a/app/components/app/sep/view-letter.vue b/app/components/app/sep/view-letter.vue
new file mode 100644
index 00000000..e1c0ecf2
--- /dev/null
+++ b/app/components/app/sep/view-letter.vue
@@ -0,0 +1,128 @@
+
+
+
+
+
diff --git a/app/components/app/soapi/early-entry.vue b/app/components/app/soapi/early-entry.vue
index 146a25d4..4d2367be 100644
--- a/app/components/app/soapi/early-entry.vue
+++ b/app/components/app/soapi/early-entry.vue
@@ -63,13 +63,13 @@ const validate = async () => {
}
defineExpose({ validate })
+const icdPreview = inject('icdPreview')
const isExcluded = (key: string) => props.excludeFields?.includes(key)
diff --git a/app/components/app/unit-position/entry-detail.vue b/app/components/app/unit-position/entry-detail.vue
new file mode 100644
index 00000000..fb84e41a
--- /dev/null
+++ b/app/components/app/unit-position/entry-detail.vue
@@ -0,0 +1,192 @@
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+ |
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+
diff --git a/app/components/app/unit-position/entry-form.vue b/app/components/app/unit-position/entry-form.vue
new file mode 100644
index 00000000..b6ab8609
--- /dev/null
+++ b/app/components/app/unit-position/entry-form.vue
@@ -0,0 +1,206 @@
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+ |
+
+
+
+
+
+ |
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+
diff --git a/app/components/app/unit-position/list.cfg.ts b/app/components/app/unit-position/list.cfg.ts
new file mode 100644
index 00000000..fb5e319b
--- /dev/null
+++ b/app/components/app/unit-position/list.cfg.ts
@@ -0,0 +1,61 @@
+import type { Config, RecComponent } from '~/components/pub/my-ui/data-table'
+import { defineAsyncComponent } from 'vue'
+import type { UnitPosition } from '~/models/unit-position'
+
+type SmallDetailDto = any
+
+const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-ud.vue'))
+
+export const config: Config = {
+ cols: [{}, {}, {}, {}, {}, { width: 50 }],
+
+ headers: [
+ [
+ { label: 'Kode Posisi' },
+ { label: 'Nama Posisi' },
+ { label: 'Nama Unit ' },
+ { label: 'Karyawan' },
+ { label: 'Status Kepala' },
+ { label: '' },
+ ],
+ ],
+
+ keys: ['code', 'name', 'unit.name', 'employee', 'head', 'action'],
+
+ delKeyNames: [
+ { key: 'code', label: 'Kode' },
+ { key: 'name', label: 'Nama' },
+ ],
+
+ parses: {
+ employee: (rec: unknown): unknown => {
+ const recX = rec as UnitPosition
+ const fullName = [recX.employee?.person.frontTitle, recX.employee?.person.name, recX.employee?.person.endTitle]
+ .filter(Boolean)
+ .join(' ')
+ .trim()
+
+ return fullName || '-'
+ },
+ head: (rec: unknown): unknown => {
+ const recX = rec as SmallDetailDto
+ return recX.headStatus ? 'Ya' : 'Tidak'
+ },
+ },
+
+ components: {
+ action(rec, idx) {
+ const res: RecComponent = {
+ idx,
+ rec: rec as object,
+ component: action,
+ props: {
+ size: 'sm',
+ },
+ }
+ return res
+ },
+ },
+
+ htmls: {},
+}
diff --git a/app/components/app/unit-position/list.vue b/app/components/app/unit-position/list.vue
new file mode 100644
index 00000000..6ad7dd81
--- /dev/null
+++ b/app/components/app/unit-position/list.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
diff --git a/app/components/app/unit/detail/index.vue b/app/components/app/unit/detail/index.vue
new file mode 100644
index 00000000..9b38aa2b
--- /dev/null
+++ b/app/components/app/unit/detail/index.vue
@@ -0,0 +1,35 @@
+
+
+
+ {{ unit.code || '-' }}
+ {{ unit.name || '-' }}
+
+
+
+
diff --git a/app/components/app/unit/detail/list.cfg.ts b/app/components/app/unit/detail/list.cfg.ts
new file mode 100644
index 00000000..8faf9e61
--- /dev/null
+++ b/app/components/app/unit/detail/list.cfg.ts
@@ -0,0 +1,61 @@
+import type { Config, RecComponent } from '~/components/pub/my-ui/data-table'
+import { defineAsyncComponent } from 'vue'
+import type { UnitPosition } from '~/models/unit-position'
+
+type SmallDetailDto = any
+
+const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-ud.vue'))
+
+export const config: Config = {
+ cols: [{}, {}, {}, {}, {}, { width: 50 }],
+
+ headers: [
+ [
+ { label: '#' },
+ { label: 'Kode Posisi' },
+ { label: 'Nama Posisi' },
+ { label: 'Karyawan' },
+ { label: 'Status Kepala' },
+ { label: '' },
+ ],
+ ],
+
+ keys: ['index', 'code', 'name', 'employee', 'head', 'action'],
+
+ delKeyNames: [
+ { key: 'code', label: 'Kode' },
+ { key: 'name', label: 'Nama' },
+ ],
+
+ parses: {
+ employee: (rec: unknown): unknown => {
+ const recX = rec as UnitPosition
+ const fullName = [recX.employee?.person.frontTitle, recX.employee?.person.name, recX.employee?.person.endTitle]
+ .filter(Boolean)
+ .join(' ')
+ .trim()
+
+ return fullName || '-'
+ },
+ head: (rec: unknown): unknown => {
+ const recX = rec as SmallDetailDto
+ return recX.headStatus ? 'Ya' : 'Tidak'
+ },
+ },
+
+ components: {
+ action(rec, idx) {
+ const res: RecComponent = {
+ idx,
+ rec: rec as object,
+ component: action,
+ props: {
+ size: 'sm',
+ },
+ }
+ return res
+ },
+ },
+
+ htmls: {},
+}
diff --git a/app/components/app/unit/detail/list.vue b/app/components/app/unit/detail/list.vue
new file mode 100644
index 00000000..f878d14c
--- /dev/null
+++ b/app/components/app/unit/detail/list.vue
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
diff --git a/app/components/content/cp-lab-order/entry.vue b/app/components/content/cp-lab-order/entry.vue
new file mode 100644
index 00000000..4d0aa002
--- /dev/null
+++ b/app/components/content/cp-lab-order/entry.vue
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/content/cp-lab-order/list.vue b/app/components/content/cp-lab-order/list.vue
new file mode 100644
index 00000000..73b9361c
--- /dev/null
+++ b/app/components/content/cp-lab-order/list.vue
@@ -0,0 +1,169 @@
+
+
+
+
+
+
+
+ handleActionRemove(recId, getMyList, toast)"
+ @cancel=""
+ />
+
diff --git a/app/components/content/cp-lab-order/main.vue b/app/components/content/cp-lab-order/main.vue
new file mode 100644
index 00000000..033d093f
--- /dev/null
+++ b/app/components/content/cp-lab-order/main.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/app/components/content/division-position/list.vue b/app/components/content/division-position/list.vue
index 019e64a9..4fa8605d 100644
--- a/app/components/content/division-position/list.vue
+++ b/app/components/content/division-position/list.vue
@@ -54,6 +54,7 @@ const {
sort: 'createdAt:asc',
'page-number': params['page-number'] || 0,
'page-size': params['page-size'] || 10,
+ includes: 'division,Employee.Person',
})
return { success: result.success || false, body: result.body || {} }
},
@@ -61,7 +62,7 @@ const {
})
const headerPrep: HeaderPrep = {
- title: 'Divisi',
+ title: 'Divisi - Posisi',
icon: 'i-lucide-box',
refSearchNav: {
placeholder: 'Cari (min. 3 karakter)...',
@@ -105,12 +106,12 @@ watch([recId, recAction], () => {
switch (recAction.value) {
case ActionEvents.showDetail:
getCurrentDivisionDetail(recId.value)
- title.value = 'Detail Divisi'
+ title.value = 'Detail Divisi Position'
isReadonly.value = true
break
case ActionEvents.showEdit:
getCurrentDivisionDetail(recId.value)
- title.value = 'Edit Divisi'
+ title.value = 'Edit Divisi Position'
isReadonly.value = false
break
case ActionEvents.showConfirmDelete:
@@ -120,9 +121,19 @@ watch([recId, recAction], () => {
})
onMounted(async () => {
- divisions.value = await getDivisionLabelList({ sort: 'createdAt:asc', 'page-size': 100 })
- employees.value = await getEmployeeLabelList({ sort: 'createdAt:asc', 'page-size': 100 })
- await getDivisionList()
+ try {
+ divisions.value = await getDivisionLabelList({ sort: 'createdAt:asc', 'page-size': 100 })
+ employees.value = await getEmployeeLabelList({ sort: 'createdAt:asc', 'page-size': 100, includes: 'person' })
+ await getDivisionList()
+ } catch (err) {
+ console.log(err)
+ // show toast
+ toast({
+ title: 'Terjadi Kesalahan',
+ description: 'Terjadi kesalahan saat memuat data',
+ variant: 'destructive',
+ })
+ }
})
@@ -142,7 +153,7 @@ onMounted(async () => {
+
+
+
+
+
+
+ ID:
+ {{ record?.id }}
+
+
+ Pasien:
+ {{ record.patient.person.name }}
+
+
+ Kelas:
+ {{ record.class_code }}
+
+
+
+
diff --git a/app/components/content/encounter/process.vue b/app/components/content/encounter/process.vue
index 71c7fe3d..77c5b1f6 100644
--- a/app/components/content/encounter/process.vue
+++ b/app/components/content/encounter/process.vue
@@ -11,10 +11,12 @@ import CompTab from '~/components/pub/my-ui/comp-tab/comp-tab.vue'
// PLASE ORDER BY TAB POSITION
import Status from '~/components/content/encounter/status.vue'
-import AssesmentFunctionList from '~/components/content/assesment-function/list.vue'
+import AssesmentFunctionList from '~/components/content/soapi/entry.vue'
import EarlyMedicalAssesmentList from '~/components/content/soapi/entry.vue'
import EarlyMedicalRehabList from '~/components/content/soapi/entry.vue'
-import PrescriptionList from '~/components/content/prescription/list.vue'
+import Prescription from '~/components/content/prescription/main.vue'
+import CpLabOrder from '~/components/content/cp-lab-order/main.vue'
+import Radiology from '~/components/content/radiology-order/main.vue'
import Consultation from '~/components/content/consultation/list.vue'
const route = useRoute()
@@ -38,21 +40,32 @@ const data = dataResBody?.data ?? null
const tabs: TabItem[] = [
{ value: 'status', label: 'Status Masuk/Keluar', component: Status, props: { encounter: data } },
- { value: 'early-medical-assessment', label: 'Pengkajian Awal Medis', component: EarlyMedicalAssesmentList },
+ {
+ value: 'early-medical-assessment',
+ label: 'Pengkajian Awal Medis',
+ component: EarlyMedicalAssesmentList,
+ props: { encounter: data, type: 'early-medic', label: 'Pengkajian Awal Medis' },
+ },
{
value: 'rehab-medical-assessment',
label: 'Pengkajian Awal Medis Rehabilitasi Medis',
component: EarlyMedicalRehabList,
+ props: { encounter: data, type: 'early-rehab', label: 'Pengkajian Awal Medis Rehabilitasi Medis' },
+ },
+ {
+ value: 'function-assessment',
+ label: 'Asesmen Fungsi',
+ component: AssesmentFunctionList,
+ props: { encounter: data, type: 'function', label: 'Asesmen Fungsi' },
},
- { value: 'function-assessment', label: 'Asesmen Fungsi', component: AssesmentFunctionList },
{ value: 'therapy-protocol', label: 'Protokol Terapi' },
{ value: 'education-assessment', label: 'Asesmen Kebutuhan Edukasi' },
{ value: 'consent', label: 'General Consent' },
{ value: 'patient-note', label: 'CPRJ' },
- { value: 'prescription', label: 'Order Obat', component: PrescriptionList },
+ { value: 'prescription', label: 'Order Obat', component: Prescription, props: { encounter_id: data.id } },
{ value: 'device', label: 'Order Alkes' },
- { value: 'mcu-radiology', label: 'Order Radiologi' },
- { value: 'mcu-lab-pc', label: 'Order Lab PK' },
+ { value: 'mcu-radiology', label: 'Order Radiologi', component: Radiology, props: { encounter_id: data.id } },
+ { value: 'mcu-lab-cp', label: 'Order Lab PK', component: CpLabOrder, props: { encounter_id: data.id } },
{ value: 'mcu-lab-micro', label: 'Order Lab Mikro' },
{ value: 'mcu-lab-pa', label: 'Order Lab PA' },
{ value: 'medical-action', label: 'Order Ruang Tindakan' },
diff --git a/app/components/content/installation-position/list.vue b/app/components/content/installation-position/list.vue
new file mode 100644
index 00000000..ea60ee04
--- /dev/null
+++ b/app/components/content/installation-position/list.vue
@@ -0,0 +1,208 @@
+
+
+
+
+
+
+
+ {
+ onResetState()
+ isFormEntryDialogOpen = value
+ }
+ "
+ >
+ , resetForm: () => void) => {
+ if (recId > 0) {
+ handleActionEdit(recId, values, getInstallationPositionList, resetForm, toast)
+ return
+ }
+ handleActionSave(values, getInstallationPositionList, resetForm, toast)
+ }
+ "
+ @cancel="handleCancelForm"
+ />
+
+
+
+ handleActionRemove(recId, getInstallationPositionList, toast)"
+ @cancel=""
+ >
+
+
+
+ ID:
+ {{ record?.id }}
+
+
+ Nama:
+ {{ record.name }}
+
+
+ Kode:
+ {{ record.code }}
+
+
+
+
+
diff --git a/app/components/content/installation/detail.vue b/app/components/content/installation/detail.vue
new file mode 100644
index 00000000..0f12ad8c
--- /dev/null
+++ b/app/components/content/installation/detail.vue
@@ -0,0 +1,235 @@
+
+
+
+
+
+
+
+
+
+
+ {
+ onResetState()
+ isFormEntryDialogOpen = value
+ }
+ "
+ >
+ , resetForm: () => void) => {
+ console.log(values)
+ if (recId > 0) {
+ handleActionEdit(recId, values, getInstallationPositionList, onResetState, toast)
+ return
+ }
+ handleActionSave(values, getInstallationPositionList, onResetState, toast)
+ }
+ "
+ @cancel="handleCancelForm"
+ />
+
+ handleActionRemove(recId, getInstallationPositionList, toast)"
+ @cancel=""
+ >
+
+
+
+ {{ field.label }}:
+ {{ record[field.key] }}
+
+
+
+
+
diff --git a/app/components/content/installation/entry.ts b/app/components/content/installation/entry.ts
deleted file mode 100644
index c003a029..00000000
--- a/app/components/content/installation/entry.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import * as z from 'zod'
-
-export const installationConf = {
- msg: {
- placeholder: '---pilih encounter class (fhir7)',
- },
- items: [
- { value: '1', label: 'Ambulatory', code: 'AMB' },
- { value: '2', label: 'Inpatient', code: 'IMP' },
- { value: '3', label: 'Emergency', code: 'EMER' },
- { value: '4', label: 'Observation', code: 'OBSENC' },
- { value: '5', label: 'Pre-admission', code: 'PRENC' },
- { value: '6', label: 'Short Stay', code: 'SS' },
- { value: '7', label: 'Virtual', code: 'VR' },
- { value: '8', label: 'Home Health', code: 'HH' },
- ],
-}
-
-export const schemaConf = z.object({
- name: z
- .string({
- required_error: 'Nama instalasi harus diisi',
- })
- .min(3, 'Nama instalasi minimal 3 karakter'),
-
- code: z
- .string({
- required_error: 'Kode instalasi harus diisi',
- })
- .min(3, 'Kode instalasi minimal 3 karakter'),
-
- encounterClassCode: z
- .string({
- required_error: 'Kelompok encounter class harus dipilih',
- })
- .min(1, 'Kelompok encounter class harus dipilih'),
-})
diff --git a/app/components/content/installation/list.vue b/app/components/content/installation/list.vue
index 31486097..553d7ebb 100644
--- a/app/components/content/installation/list.vue
+++ b/app/components/content/installation/list.vue
@@ -102,9 +102,23 @@ const getCurrentInstallationDetail = async (id: number | string) => {
watch([recId, recAction], () => {
switch (recAction.value) {
case ActionEvents.showDetail:
- getCurrentInstallationDetail(recId.value)
- title.value = 'Detail Instalasi'
- isReadonly.value = true
+ if (Number(recId.value) > 0) {
+ const id = Number(recId.value)
+
+ recAction.value = ''
+ recItem.value = null
+ recId.value = 0
+ isFormEntryDialogOpen.value = false
+ isReadonly.value = false
+
+ navigateTo({
+ name: 'org-src-installation-id',
+ params: {
+ id,
+ },
+ })
+ }
+
break
case ActionEvents.showEdit:
getCurrentInstallationDetail(recId.value)
diff --git a/app/components/content/prescription/entry.vue b/app/components/content/prescription/entry.vue
new file mode 100644
index 00000000..4b3fa663
--- /dev/null
+++ b/app/components/content/prescription/entry.vue
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/content/prescription/list.vue b/app/components/content/prescription/list.vue
index f8059b9d..844cb04f 100644
--- a/app/components/content/prescription/list.vue
+++ b/app/components/content/prescription/list.vue
@@ -1,37 +1,82 @@
-
+
+
-
-
-
-
-
-
-
-
+ handleActionRemove(recId, getMyList, toast)"
+ @cancel=""
+ >
+
diff --git a/app/components/content/prescription/main.vue b/app/components/content/prescription/main.vue
new file mode 100644
index 00000000..033d093f
--- /dev/null
+++ b/app/components/content/prescription/main.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/app/components/content/radiology-order/entry.vue b/app/components/content/radiology-order/entry.vue
new file mode 100644
index 00000000..4d0aa002
--- /dev/null
+++ b/app/components/content/radiology-order/entry.vue
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pickerDialogOpen = false" class="justify-center" />
+
+
diff --git a/app/components/content/radiology-order/list.vue b/app/components/content/radiology-order/list.vue
new file mode 100644
index 00000000..b2c8571d
--- /dev/null
+++ b/app/components/content/radiology-order/list.vue
@@ -0,0 +1,169 @@
+
+
+
+
+
+
+
+ handleActionRemove(recId, getMyList, toast)"
+ @cancel=""
+ />
+
diff --git a/app/components/content/radiology-order/main.vue b/app/components/content/radiology-order/main.vue
new file mode 100644
index 00000000..033d093f
--- /dev/null
+++ b/app/components/content/radiology-order/main.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/app/components/content/sep/entry.vue b/app/components/content/sep/entry.vue
index 61107232..3a916c4d 100644
--- a/app/components/content/sep/entry.vue
+++ b/app/components/content/sep/entry.vue
@@ -1,113 +1,552 @@
-
- Tambah SEP
+
+ Tambah
+ SEP
-
-
+ {
+ if (value.search && value.search.length >= 3) {
+ // Use identifier search for specific searches (NIK, RM, etc.)
+ getPatientByIdentifierSearch(value.search)
+ } else {
+ // Use regular search for general searches
+ getPatientsList({ ...value, 'page-size': 10, includes: 'person' })
+ }
+ }
+ "
@save="handleSavePatient"
/>
-
-
-
+ getLetterMappers(value.admissionType, value.search)"
+ @save="handleSaveLetter"
+ />
diff --git a/app/components/content/sep/list.vue b/app/components/content/sep/list.vue
index 9a6cd8db..013b076a 100644
--- a/app/components/content/sep/list.vue
+++ b/app/components/content/sep/list.vue
@@ -1,4 +1,5 @@
-
+
-
-
+
@@ -226,9 +241,7 @@ provide('table_data_loader', isLoading)
Hapus SEP
-
- Apakah anda yakin ingin menghapus SEP dengan data:
-
+
Apakah anda yakin ingin menghapus SEP dengan data:
No. SEP : {{ sepData.no_sep }}
@@ -237,11 +250,21 @@ provide('table_data_loader', isLoading)
-
diff --git a/app/components/content/soapi/entry.vue b/app/components/content/soapi/entry.vue
index 7b4ab9d4..ee3c7c32 100644
--- a/app/components/content/soapi/entry.vue
+++ b/app/components/content/soapi/entry.vue
@@ -11,7 +11,7 @@ import FunctionForm from './form-function.vue'
const route = useRoute()
const type = computed(() => (route.query.tab as string) || 'early-medical-assessment')
-const { mode, openForm, backToList } = useQueryMode('mode')
+const { mode, goToEntry, backToList } = useQueryCRUDMode('mode')
const formMap = {
'early-medical-assessment': EarlyForm,
@@ -26,7 +26,8 @@ const ActiveForm = computed(() => formMap[type.value] || EarlyForm)
(null)
+const selectedDiagnose = ref(null)
+const selectedFungsional = ref(null)
const schema = FunctionSoapiSchema
const payload = ref({
encounter_id: 0,
@@ -60,29 +69,55 @@ const isLoading = reactive({
isTableLoading: false,
})
-async function getPatientList() {
+async function getDiagnoses() {
isLoading.isTableLoading = true
- const resp = await xfetch('/api/v1/patient')
+ const resp = await xfetch('/api/v1/diagnose-src')
if (resp.success) {
- data.value = (resp.body as Record).data
+ diagnoses.value = (resp.body as Record).data
+ }
+ isLoading.isTableLoading = false
+}
+
+async function getProcedures() {
+ isLoading.isTableLoading = true
+ const resp = await xfetch('/api/v1/procedure-src')
+ if (resp.success) {
+ procedures.value = (resp.body as Record).data
}
isLoading.isTableLoading = false
}
onMounted(() => {
- getPatientList()
+ getProcedures()
+ getDiagnoses()
})
-function handleOpen(type: string) {
- console.log(type)
- isOpen.value = true
+function handleClick(type: string) {
+ if (type === 'prosedur') {
+ isOpenProcedure.value = true
+ } else if (type === 'diagnosa') {
+ isOpenDiagnose.value = true
+ } else if (type === 'fungsional') {
+ isOpenDiagnose.value = true
+ }
}
-
const entryRehabRef = ref()
async function actionHandler(type: string) {
- console.log(type)
+ if (type === 'back') {
+ backToList()
+ return
+ }
const result = await entryRehabRef.value?.validate()
if (result?.valid) {
+ if (
+ selectedProcedure.value?.length > 0 ||
+ selectedDiagnose.value?.length > 0 ||
+ selectedFungsional.value?.length > 0
+ ) {
+ result.data.procedure = selectedProcedure.value || []
+ result.data.diagnose = selectedDiagnose.value || []
+ result.data.fungsional = selectedFungsional.value || []
+ }
console.log('data', result.data)
handleActionSave(
{
@@ -99,7 +134,23 @@ async function actionHandler(type: string) {
}
}
+const icdPreview = ref({
+ procedures: [],
+ diagnoses: [],
+})
+
+function actionDialogHandler(type: string) {
+ if (type === 'submit') {
+ icdPreview.value.procedures = selectedProcedure.value || []
+ icdPreview.value.diagnoses = selectedDiagnose.value || []
+ icdPreview.value.fungsional = selectedFungsional.value || []
+ }
+ isOpenProcedure.value = false
+ isOpenDiagnose.value = false
+}
+
provide('table_data_loader', isLoading)
+provide('icdPreview', icdPreview)
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/content/soapi/form-rehab.vue b/app/components/content/soapi/form-rehab.vue
index 655063f9..4130f562 100644
--- a/app/components/content/soapi/form-rehab.vue
+++ b/app/components/content/soapi/form-rehab.vue
@@ -2,14 +2,20 @@
import { z } from 'zod'
import Entry from '~/components/app/soapi/entry.vue'
import Action from '~/components/pub/my-ui/nav-footer/ba-dr-su.vue'
+import ActionDialog from '~/components/pub/my-ui/nav-footer/ba-su.vue'
import Dialog from '~/components/pub/my-ui/modal/dialog.vue'
import { EarlyRehabSchema } from '~/schemas/soapi.schema'
import { toast } from '~/components/pub/ui/toast'
import { handleActionSave, handleActionEdit } from '~/handlers/soapi-early.handler'
+const { backToList } = useQueryMode('mode')
const route = useRoute()
-const isOpen = ref(false)
-const data = ref([])
+const isOpenProcedure = ref(false)
+const isOpenDiagnose = ref(false)
+const procedures = ref([])
+const diagnoses = ref([])
+const selectedProcedure = ref(null)
+const selectedDiagnose = ref(null)
const schema = EarlyRehabSchema
const payload = ref({
encounter_id: 0,
@@ -65,29 +71,46 @@ const isLoading = reactive({
isTableLoading: false,
})
-async function getPatientList() {
+async function getDiagnoses() {
isLoading.isTableLoading = true
- const resp = await xfetch('/api/v1/patient')
+ const resp = await xfetch('/api/v1/diagnose-src')
if (resp.success) {
- data.value = (resp.body as Record).data
+ diagnoses.value = (resp.body as Record).data
+ }
+ isLoading.isTableLoading = false
+}
+
+async function getProcedures() {
+ isLoading.isTableLoading = true
+ const resp = await xfetch('/api/v1/procedure-src')
+ if (resp.success) {
+ procedures.value = (resp.body as Record).data
}
isLoading.isTableLoading = false
}
onMounted(() => {
- getPatientList()
+ getProcedures()
+ getDiagnoses()
})
function handleOpen(type: string) {
- console.log(type)
- isOpen.value = true
+ if (type === 'fungsional') {
+ isOpenDiagnose.value = true
+ }
}
const entryRehabRef = ref()
async function actionHandler(type: string) {
- console.log(type)
+ if (type === 'back') {
+ backToList()
+ return
+ }
const result = await entryRehabRef.value?.validate()
if (result?.valid) {
+ if (selectedDiagnose.value?.length > 0) {
+ result.data.diagnose = selectedDiagnose.value || []
+ }
console.log('data', result.data)
handleActionSave(
{
@@ -104,7 +127,22 @@ async function actionHandler(type: string) {
}
}
+const icdPreview = ref({
+ procedures: [],
+ diagnoses: [],
+})
+
+function actionDialogHandler(type: string) {
+ if (type === 'submit') {
+ icdPreview.value.procedures = selectedProcedure.value || []
+ icdPreview.value.diagnoses = selectedDiagnose.value || []
+ }
+ isOpenProcedure.value = false
+ isOpenDiagnose.value = false
+}
+
provide('table_data_loader', isLoading)
+provide('icdPreview', icdPreview)
-
+
+
diff --git a/app/components/content/soapi/form.vue b/app/components/content/soapi/form.vue
index 794daef9..c963a091 100644
--- a/app/components/content/soapi/form.vue
+++ b/app/components/content/soapi/form.vue
@@ -2,14 +2,20 @@
import { z } from 'zod'
import Entry from '~/components/app/soapi/entry.vue'
import Action from '~/components/pub/my-ui/nav-footer/ba-dr-su.vue'
+import ActionDialog from '~/components/pub/my-ui/nav-footer/ba-su.vue'
import Dialog from '~/components/pub/my-ui/modal/dialog.vue'
import { EarlySchema } from '~/schemas/soapi.schema'
import { toast } from '~/components/pub/ui/toast'
import { handleActionSave, handleActionEdit } from '~/handlers/soapi-early.handler'
+const { backToList } = useQueryMode('mode')
const route = useRoute()
-const isOpen = ref(false)
-const data = ref([])
+const isOpenProcedure = ref(false)
+const isOpenDiagnose = ref(false)
+const procedures = ref([])
+const diagnoses = ref([])
+const selectedProcedure = ref(null)
+const selectedDiagnose = ref(null)
const schema = EarlySchema
const payload = ref({
encounter_id: 0,
@@ -38,29 +44,50 @@ const isLoading = reactive({
isTableLoading: false,
})
-async function getPatientList() {
+async function getDiagnoses() {
isLoading.isTableLoading = true
- const resp = await xfetch('/api/v1/patient')
+ const resp = await xfetch('/api/v1/diagnose-src')
if (resp.success) {
- data.value = (resp.body as Record).data
+ diagnoses.value = (resp.body as Record).data
+ }
+ isLoading.isTableLoading = false
+}
+
+async function getProcedures() {
+ isLoading.isTableLoading = true
+ const resp = await xfetch('/api/v1/procedure-src')
+ if (resp.success) {
+ procedures.value = (resp.body as Record).data
}
isLoading.isTableLoading = false
}
onMounted(() => {
- getPatientList()
+ getProcedures()
+ getDiagnoses()
})
function handleOpen(type: string) {
- console.log(type)
- isOpen.value = true
+ if (type === 'prosedur') {
+ isOpenProcedure.value = true
+ } else if (type === 'diagnosa') {
+ isOpenDiagnose.value = true
+ }
}
const entryRef = ref()
async function actionHandler(type: string) {
- console.log(type)
+ if (type === 'back') {
+ backToList()
+ return
+ }
const result = await entryRef.value?.validate()
if (result?.valid) {
+ if (selectedProcedure.value?.length > 0 || selectedDiagnose.value?.length > 0) {
+ result.data.procedure = selectedProcedure.value || []
+ result.data.diagnose = selectedDiagnose.value || []
+ }
+
console.log('data', result.data)
handleActionSave(
{
@@ -77,7 +104,22 @@ async function actionHandler(type: string) {
}
}
+const icdPreview = ref({
+ procedures: [],
+ diagnoses: [],
+})
+
+function actionDialogHandler(type: string) {
+ if (type === 'submit') {
+ icdPreview.value.procedures = selectedProcedure.value || []
+ icdPreview.value.diagnoses = selectedDiagnose.value || []
+ }
+ isOpenProcedure.value = false
+ isOpenDiagnose.value = false
+}
+
provide('table_data_loader', isLoading)
+provide('icdPreview', icdPreview)
-
+
+
+
+
+
+
+
diff --git a/app/components/content/soapi/list.vue b/app/components/content/soapi/list.vue
index a240a65f..5a960d5d 100644
--- a/app/components/content/soapi/list.vue
+++ b/app/components/content/soapi/list.vue
@@ -1,16 +1,41 @@
-
+
+
-
+
+
+ handleActionRemove(recId, getMyList, toast)"
+ @cancel=""
+ >
+
+
+
+ ID:
+ {{ record?.id }}
+
+
+ Nama:
+ {{ record.name }}
+
+
+ Kode:
+ {{ record.code }}
+
+
+
+
diff --git a/app/components/content/specialist-position/list.vue b/app/components/content/specialist-position/list.vue
new file mode 100644
index 00000000..1ebf697e
--- /dev/null
+++ b/app/components/content/specialist-position/list.vue
@@ -0,0 +1,203 @@
+
+
+
+
+
+ {
+ onResetState()
+ isFormEntryDialogOpen = value
+ }
+ "
+ >
+ , resetForm: () => void) => {
+ if (recId > 0) {
+ handleActionEdit(recId, values, getSpecialistList, resetForm, toast)
+ return
+ }
+ handleActionSave(values, getSpecialistList, resetForm, toast)
+ }
+ "
+ @cancel="handleCancelForm"
+ />
+
+
+ handleActionRemove(recId, getSpecialistList, toast)"
+ @cancel=""
+ >
+
+
+
+ {{ field.label }}:
+ {{ record[field.key] }}
+
+
+
+
+
diff --git a/app/components/content/specialist/detail.vue b/app/components/content/specialist/detail.vue
new file mode 100644
index 00000000..df4e79b6
--- /dev/null
+++ b/app/components/content/specialist/detail.vue
@@ -0,0 +1,236 @@
+
+
+
+
+
+
+
+
+
+
+ {
+ onResetState()
+ isFormEntryDialogOpen = value
+ }
+ "
+ >
+ , resetForm: () => void) => {
+ console.log(values)
+ if (recId > 0) {
+ handleActionEdit(recId, values, getPositionList, onResetState, toast)
+ return
+ }
+ handleActionSave(values, getPositionList, onResetState, toast)
+ }
+ "
+ @cancel="handleCancelForm"
+ />
+
+ handleActionRemove(recId, getPositionList, toast)"
+ @cancel=""
+ >
+
+
+
+ {{ field.label }}:
+ {{ record[field.key] }}
+
+
+
+
+
diff --git a/app/components/content/specialist/entry.ts b/app/components/content/specialist/entry.ts
deleted file mode 100644
index c89302c2..00000000
--- a/app/components/content/specialist/entry.ts
+++ /dev/null
@@ -1,95 +0,0 @@
-import * as z from 'zod'
-
-export const schemaConf = z.object({
- name: z
- .string({
- required_error: 'Nama spesialisasi harus diisi',
- })
- .min(3, 'Nama spesialisasi minimal 3 karakter'),
-
- code: z
- .string({
- required_error: 'Kode spesialisasi harus diisi',
- })
- .min(3, 'Kode spesialisasi minimal 3 karakter'),
-
- installationId: z
- .string({
- required_error: 'Instalasi harus dipilih',
- })
- .min(1, 'Instalasi harus dipilih'),
-
- unitId: z
- .string({
- required_error: 'Unit harus dipilih',
- })
- .min(1, 'Unit harus dipilih'),
-})
-
-// Unit mapping berdasarkan installation
-export const installationUnitMapping: Record
= {
- '1': ['1', '3', '5'],
- '2': ['2', '4', '6'],
- '3': ['7', '8', '9', '10', '11'],
-}
-
-export const unitConf = {
- msg: {
- placeholder: '---pilih unit',
- search: 'kode, nama unit',
- empty: 'unit tidak ditemukan',
- },
- items: [
- { value: '1', label: 'Instalasi Medis', code: 'MED' },
- { value: '2', label: 'Instalasi Keperawatan', code: 'NUR' },
- { value: '3', label: 'Instalasi Administrasi', code: 'ADM' },
- { value: '4', label: 'Instalasi Penunjang Non-Medis', code: 'SUP' },
- { value: '5', label: 'Instalasi Pendidikan & Pelatihan', code: 'EDU' },
- { value: '6', label: 'Instalasi Farmasi', code: 'PHA' },
- { value: '7', label: 'Instalasi Radiologi', code: 'RAD' },
- { value: '8', label: 'Instalasi Laboratorium', code: 'LAB' },
- { value: '9', label: 'Instalasi Keuangan', code: 'FIN' },
- { value: '10', label: 'Instalasi SDM', code: 'HR' },
- { value: '11', label: 'Instalasi Teknologi Informasi', code: 'ITS' },
- { value: '12', label: 'Instalasi Pemeliharaan & Sarana', code: 'MNT' },
- { value: '13', label: 'Instalasi Gizi / Catering', code: 'CAT' },
- { value: '14', label: 'Instalasi Keamanan', code: 'SEC' },
- { value: '15', label: 'Instalasi Gawat Darurat', code: 'EMR' },
- { value: '16', label: 'Instalasi Bedah Sentral', code: 'SUR' },
- { value: '17', label: 'Instalasi Rawat Jalan', code: 'OUT' },
- { value: '18', label: 'Instalasi Rawat Inap', code: 'INP' },
- { value: '19', label: 'Instalasi Rehabilitasi Medik', code: 'REB' },
- { value: '20', label: 'Instalasi Penelitian & Pengembangan', code: 'RSH' },
- ],
-}
-
-export const installationConf = {
- msg: {
- placeholder: '---pilih instalasi',
- search: 'kode, nama instalasi',
- empty: 'instalasi tidak ditemukan',
- },
- items: [
- { value: '1', label: 'Ambulatory', code: 'AMB' },
- { value: '2', label: 'Inpatient', code: 'IMP' },
- { value: '3', label: 'Emergency', code: 'EMER' },
- ],
-}
-
-// Helper function untuk filter unit berdasarkan installation
-export function getFilteredUnits(installationId: string) {
- if (!installationId || !installationUnitMapping[installationId]) {
- return []
- }
-
- const allowedUnitIds = installationUnitMapping[installationId]
- return unitConf.items.filter((unit) => allowedUnitIds.includes(unit.value))
-}
-
-// Helper function untuk membuat unit config yang ter-filter
-export function createFilteredUnitConf(installationId: string) {
- return {
- ...unitConf,
- items: getFilteredUnits(installationId),
- }
-}
diff --git a/app/components/content/specialist/list.vue b/app/components/content/specialist/list.vue
index 9bbf755f..ca293026 100644
--- a/app/components/content/specialist/list.vue
+++ b/app/components/content/specialist/list.vue
@@ -103,9 +103,23 @@ const getCurrentSpecialistDetail = async (id: number | string) => {
watch([recId, recAction], () => {
switch (recAction.value) {
case ActionEvents.showDetail:
- getCurrentSpecialistDetail(recId.value)
- title.value = 'Detail Spesialis'
- isReadonly.value = true
+ if (Number(recId.value) > 0) {
+ const id = Number(recId.value)
+
+ recAction.value = ''
+ recItem.value = null
+ recId.value = 0
+ isFormEntryDialogOpen.value = false
+ isReadonly.value = false
+
+ navigateTo({
+ name: 'org-src-specialist-id',
+ params: {
+ id,
+ },
+ })
+ }
+
break
case ActionEvents.showEdit:
getCurrentSpecialistDetail(recId.value)
diff --git a/app/components/content/subspecialist-position/list.vue b/app/components/content/subspecialist-position/list.vue
new file mode 100644
index 00000000..4c833ce2
--- /dev/null
+++ b/app/components/content/subspecialist-position/list.vue
@@ -0,0 +1,211 @@
+
+
+
+
+
+
+
+ {
+ onResetState()
+ isFormEntryDialogOpen = value
+ }
+ "
+ >
+ , resetForm: () => void) => {
+ if (recId > 0) {
+ handleActionEdit(recId, values, getSubSpecialistList, onResetState, toast)
+ return
+ }
+ handleActionSave(values, getSubSpecialistList, onResetState, toast)
+ }
+ "
+ @cancel="handleCancelForm"
+ />
+
+
+
+ handleActionRemove(recId, getSubSpecialistList, toast)"
+ @cancel=""
+ >
+
+
+
+ {{ field.label }}:
+ {{ record[field.key] }}
+
+
+
+
+
diff --git a/app/components/content/subspecialist/detail.vue b/app/components/content/subspecialist/detail.vue
new file mode 100644
index 00000000..d432eb22
--- /dev/null
+++ b/app/components/content/subspecialist/detail.vue
@@ -0,0 +1,239 @@
+
+
+
+
+
+
+
+
+
+
+ {
+ onResetState()
+ isFormEntryDialogOpen = value
+ }
+ "
+ >
+ , resetForm: () => void) => {
+ console.log(values)
+ if (recId > 0) {
+ handleActionEdit(recId, values, getPositionList, onResetState, toast)
+ return
+ }
+ handleActionSave(values, getPositionList, onResetState, toast)
+ }
+ "
+ @cancel="handleCancelForm"
+ />
+
+ handleActionRemove(recId, getPositionList, toast)"
+ @cancel=""
+ >
+
+
+
+ {{ field.label }}:
+ {{ record[field.key] }}
+
+
+
+
+
diff --git a/app/components/content/subspecialist/entry.ts b/app/components/content/subspecialist/entry.ts
deleted file mode 100644
index 5a93847d..00000000
--- a/app/components/content/subspecialist/entry.ts
+++ /dev/null
@@ -1,98 +0,0 @@
-import * as z from 'zod'
-
-export const schemaConf = z.object({
- name: z
- .string({
- required_error: 'Nama spesialisasi harus diisi',
- })
- .min(3, 'Nama spesialisasi minimal 3 karakter'),
-
- code: z
- .string({
- required_error: 'Kode spesialisasi harus diisi',
- })
- .min(3, 'Kode spesialisasi minimal 3 karakter'),
-
- installationId: z
- .string({
- required_error: 'Instalasi harus dipilih',
- })
- .min(1, 'Instalasi harus dipilih'),
-
- unitId: z
- .string({
- required_error: 'Unit harus dipilih',
- })
- .min(1, 'Unit harus dipilih'),
- specialistId: z
- .string({
- required_error: 'Specialist harus dipilih',
- })
- .min(1, 'Specialist harus dipilih'),
-})
-
-// Unit mapping berdasarkan installation
-export const installationUnitMapping: Record = {
- '1': ['1', '3'],
- '2': ['2', '3'],
- '3': ['1', '2', '3'],
-}
-
-export const unitConf = {
- msg: {
- placeholder: '---pilih unit',
- search: 'kode, nama unit',
- empty: 'unit tidak ditemukan',
- },
- items: [
- { value: '1', label: 'Instalasi Medis', code: 'MED' },
- { value: '2', label: 'Instalasi Keperawatan', code: 'NUR' },
- { value: '3', label: 'Instalasi Administrasi', code: 'ADM' },
- ],
-}
-
-export const specialistConf = {
- msg: {
- placeholder: '---pilih specialist',
- search: 'kode, nama specialist',
- empty: 'specialist tidak ditemukan',
- },
- items: [
- { value: '1', label: 'Spesialis Jantung', code: 'CARD' },
- { value: '2', label: 'Spesialis Mata', code: 'OPHT' },
- { value: '3', label: 'Spesialis Bedah', code: 'SURG' },
- { value: '4', label: 'Spesialis Anak', code: 'PEDI' },
- { value: '5', label: 'Spesialis Kandungan', code: 'OBGY' },
- ],
-}
-
-export const installationConf = {
- msg: {
- placeholder: '---pilih instalasi',
- search: 'kode, nama instalasi',
- empty: 'instalasi tidak ditemukan',
- },
- items: [
- { value: '1', label: 'Ambulatory', code: 'AMB' },
- { value: '2', label: 'Inpatient', code: 'IMP' },
- { value: '3', label: 'Emergency', code: 'EMER' },
- ],
-}
-
-// Helper function untuk filter unit berdasarkan installation
-export function getFilteredUnits(installationId: string) {
- if (!installationId || !installationUnitMapping[installationId]) {
- return []
- }
-
- const allowedUnitIds = installationUnitMapping[installationId]
- return unitConf.items.filter((unit) => allowedUnitIds.includes(unit.value))
-}
-
-// Helper function untuk membuat unit config yang ter-filter
-export function createFilteredUnitConf(installationId: string) {
- return {
- ...unitConf,
- items: getFilteredUnits(installationId),
- }
-}
diff --git a/app/components/content/subspecialist/list.vue b/app/components/content/subspecialist/list.vue
index e2c6db52..bb1b63f5 100644
--- a/app/components/content/subspecialist/list.vue
+++ b/app/components/content/subspecialist/list.vue
@@ -103,9 +103,23 @@ const getCurrentSubSpecialistDetail = async (id: number | string) => {
watch([recId, recAction], () => {
switch (recAction.value) {
case ActionEvents.showDetail:
- getCurrentSubSpecialistDetail(recId.value)
- title.value = 'Detail Sub Spesialis'
- isReadonly.value = true
+ if (Number(recId.value) > 0) {
+ const id = Number(recId.value)
+
+ recAction.value = ''
+ recItem.value = null
+ recId.value = 0
+ isFormEntryDialogOpen.value = false
+ isReadonly.value = false
+
+ navigateTo({
+ name: 'org-src-subspecialist-id',
+ params: {
+ id,
+ },
+ })
+ }
+
break
case ActionEvents.showEdit:
getCurrentSubSpecialistDetail(recId.value)
diff --git a/app/components/content/unit-position/list.vue b/app/components/content/unit-position/list.vue
new file mode 100644
index 00000000..55ab3f29
--- /dev/null
+++ b/app/components/content/unit-position/list.vue
@@ -0,0 +1,206 @@
+
+
+
+
+
+
+
+ {
+ onResetState()
+ isFormEntryDialogOpen = value
+ }
+ "
+ >
+ , resetForm: () => void) => {
+ if (recId > 0) {
+ handleActionEdit(recId, values, getListUnit, resetForm, toast)
+ return
+ }
+ handleActionSave(values, getListUnit, resetForm, toast)
+ }
+ "
+ @cancel="handleCancelForm"
+ />
+
+
+ handleActionRemove(recId, getListUnit, toast)"
+ @cancel=""
+ >
+
+
+
+ {{ field.label }}:
+ {{ record[field.key] }}
+
+
+
+
+
diff --git a/app/components/content/unit/detail.vue b/app/components/content/unit/detail.vue
new file mode 100644
index 00000000..6c51624f
--- /dev/null
+++ b/app/components/content/unit/detail.vue
@@ -0,0 +1,234 @@
+
+
+
+
+
+
+
+
+
+
+ {
+ onResetState()
+ isFormEntryDialogOpen = value
+ }
+ "
+ >
+ , resetForm: () => void) => {
+ console.log(values)
+ if (recId > 0) {
+ handleActionEdit(recId, values, getPositionList, onResetState, toast)
+ return
+ }
+ handleActionSave(values, getPositionList, onResetState, toast)
+ }
+ "
+ @cancel="handleCancelForm"
+ />
+
+ handleActionRemove(recId, getPositionList, toast)"
+ @cancel=""
+ >
+
+
+
+ {{ field.label }}:
+ {{ record[field.key] }}
+
+
+
+
+
diff --git a/app/components/content/unit/entry.ts b/app/components/content/unit/entry.ts
deleted file mode 100644
index bf85a0ed..00000000
--- a/app/components/content/unit/entry.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import * as z from 'zod'
-
-export const unitConf = {
- msg: {
- placeholder: '--- pilih instalasi',
- search: 'kode, nama instalasi',
- empty: 'instalasi tidak ditemukan',
- },
- items: [
- { value: '1', label: 'Instalasi Medis', code: 'MED' },
- { value: '2', label: 'Instalasi Keperawatan', code: 'NUR' },
- { value: '3', label: 'Instalasi Administrasi', code: 'ADM' },
- { value: '4', label: 'Instalasi Penunjang Non-Medis', code: 'SUP' },
- { value: '5', label: 'Instalasi Pendidikan & Pelatihan', code: 'EDU' },
- { value: '6', label: 'Instalasi Farmasi', code: 'PHA' },
- { value: '7', label: 'Instalasi Radiologi', code: 'RAD' },
- { value: '8', label: 'Instalasi Laboratorium', code: 'LAB' },
- { value: '9', label: 'Instalasi Keuangan', code: 'FIN' },
- { value: '10', label: 'Instalasi SDM', code: 'HR' },
- { value: '11', label: 'Instalasi Teknologi Informasi', code: 'ITS' },
- { value: '12', label: 'Instalasi Pemeliharaan & Sarana', code: 'MNT' },
- { value: '13', label: 'Instalasi Gizi / Catering', code: 'CAT' },
- { value: '14', label: 'Instalasi Keamanan', code: 'SEC' },
- { value: '15', label: 'Instalasi Gawat Darurat', code: 'EMR' },
- { value: '16', label: 'Instalasi Bedah Sentral', code: 'SUR' },
- { value: '17', label: 'Instalasi Rawat Jalan', code: 'OUT' },
- { value: '18', label: 'Instalasi Rawat Inap', code: 'INP' },
- { value: '19', label: 'Instalasi Rehabilitasi Medik', code: 'REB' },
- { value: '20', label: 'Instalasi Penelitian & Pengembangan', code: 'RSH' },
- ],
-}
-
-export const schemaConf = z.object({
- name: z
- .string({
- required_error: 'Nama unit harus diisi',
- })
- .min(1, 'Nama unit harus diisi'),
-
- code: z
- .string({
- required_error: 'Kode unit harus diisi',
- })
- .min(1, 'Kode unit harus diisi'),
- parentId: z.preprocess(
- (input: unknown) => {
- if (typeof input === 'string') {
- // Handle empty string case
- if (input.trim() === '') {
- return 0
- }
- return Number(input)
- }
-
- return input
- },
- z
- .number({
- required_error: 'Instalasi induk harus dipilih',
- })
- .refine((num) => num > 0, 'Instalasi induk harus dipilih'),
- ),
-})
diff --git a/app/components/content/unit/list.vue b/app/components/content/unit/list.vue
index 03edd231..34b647ef 100644
--- a/app/components/content/unit/list.vue
+++ b/app/components/content/unit/list.vue
@@ -103,9 +103,23 @@ const getCurrentUnitDetail = async (id: number | string) => {
watch([recId, recAction], () => {
switch (recAction.value) {
case ActionEvents.showDetail:
- getCurrentUnitDetail(recId.value)
- title.value = 'Detail Unit'
- isReadonly.value = true
+ if (Number(recId.value) > 0) {
+ const id = Number(recId.value)
+
+ recAction.value = ''
+ recItem.value = null
+ recId.value = 0
+ isFormEntryDialogOpen.value = false
+ isReadonly.value = false
+
+ navigateTo({
+ name: 'org-src-unit-id',
+ params: {
+ id,
+ },
+ })
+ }
+
break
case ActionEvents.showEdit:
getCurrentUnitDetail(recId.value)
diff --git a/app/components/layout/AppSidebar.vue b/app/components/layout/AppSidebar.vue
index 4f51e42c..a14b2137 100644
--- a/app/components/layout/AppSidebar.vue
+++ b/app/components/layout/AppSidebar.vue
@@ -1,5 +1,12 @@
diff --git a/app/components/layout/SidebarNavFooter.vue b/app/components/layout/SidebarNavFooter.vue
index 68d8d9a2..2c1e942c 100644
--- a/app/components/layout/SidebarNavFooter.vue
+++ b/app/components/layout/SidebarNavFooter.vue
@@ -10,8 +10,8 @@ import { useSidebar } from '~/components/pub/ui/sidebar'
// }>()
const { isMobile } = useSidebar()
-const { logout } = useUserStore()
-const userStore = useUserStore().user
+const { user, logout, setActiveRole, getActiveRole } = useUserStore()
+// const userStore = useUserStore().user
function handleLogout() {
navigateTo('/auth/login')
@@ -32,19 +32,19 @@ const showModalTheme = ref(false)
class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
>
-
+
{{
- userStore?.user_name
+ user.user_name
?.split(' ')
- .map((n) => n[0])
+ .map((n: string) => n[0])
.join('') || ''
}}
- {{ userStore?.user_name || '' }}
- {{ userStore?.user_email || '' }}
+ {{ user.user_name || '' }}
+ {{ user.user_email || '' }}
@@ -52,35 +52,40 @@ const showModalTheme = ref(false)
diff --git a/app/components/pub/my-ui/combobox/combobox.vue b/app/components/pub/my-ui/combobox/combobox.vue
index 23505393..713edd57 100644
--- a/app/components/pub/my-ui/combobox/combobox.vue
+++ b/app/components/pub/my-ui/combobox/combobox.vue
@@ -16,22 +16,23 @@ const props = defineProps<{
const emit = defineEmits<{
'update:modelValue': [value: string]
+ 'update:searchText': [value: string]
}>()
const open = ref(false)
-
+const searchText = ref('')
+const debouncedSearchText = refDebounced(searchText, 500) // 500ms debounce
const selectedItem = computed(() => props.items.find((item) => item.value === props.modelValue))
const displayText = computed(() => {
- console.log(selectedItem)
if (selectedItem.value?.label) {
return selectedItem.value.label
}
return props.placeholder || 'Pilih item'
})
-watch(props, () => {
- console.log(props.modelValue)
+watch(debouncedSearchText, (newValue) => {
+ emit('update:searchText', newValue)
})
const searchableItems = computed(() => {
@@ -106,6 +107,11 @@ function onSelect(item: Item) {
class="h-9 border-0 border-b border-gray-200 bg-white text-black focus:ring-0 dark:border-gray-700 dark:bg-gray-800 dark:text-white"
:placeholder="searchPlaceholder || 'Cari...'"
:aria-label="`Cari ${displayText}`"
+ @input="
+ (evt: any) => {
+ searchText = evt?.target?.value || ''
+ }
+ "
/>
{{ emptyMessage || 'Item tidak ditemukan.' }}
diff --git a/app/components/pub/my-ui/comp-tab/comp-tab.vue b/app/components/pub/my-ui/comp-tab/comp-tab.vue
index de045bce..69a47ef2 100644
--- a/app/components/pub/my-ui/comp-tab/comp-tab.vue
+++ b/app/components/pub/my-ui/comp-tab/comp-tab.vue
@@ -12,14 +12,14 @@ const emit = defineEmits<{
}>()
function changeTab(value: string) {
- activeTab.value = value;
- emit('changeTab', value);
+ activeTab.value = value
+ emit('changeTab', value)
}
-
+
+
+
+
+
-
\ No newline at end of file
+
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..f3e2ef43 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/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 @@
+
+
+
+
+
+
+ Back
+
+
+
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.vue b/app/components/pub/my-ui/nav-header/filter.vue
index 01b1ab55..ab28620b 100644
--- a/app/components/pub/my-ui/nav-header/filter.vue
+++ b/app/components/pub/my-ui/nav-header/filter.vue
@@ -34,9 +34,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() {
diff --git a/app/components/pub/my-ui/pagination/pagination-view.vue b/app/components/pub/my-ui/pagination/pagination-view.vue
index 149d425e..8a2271b4 100644
--- a/app/components/pub/my-ui/pagination/pagination-view.vue
+++ b/app/components/pub/my-ui/pagination/pagination-view.vue
@@ -4,6 +4,10 @@ import Pagination from './pagination.vue'
const props = defineProps<{
paginationMeta: PaginationMeta
+ conf?: {
+ showInfo: boolean
+ showControl: boolean
+ }
}>()
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
+ >
+
+
+
-
+ >
+
{{ item.value }}
-
+
-
-
+
+
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/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/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/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)/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/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)/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]/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/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..0c13541b 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,7 +23,7 @@ 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
@@ -33,8 +33,15 @@ const canRead = 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/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/doctor.service.ts b/app/services/doctor.service.ts
index 64ab22e9..74104c2c 100644
--- a/app/services/doctor.service.ts
+++ b/app/services/doctor.service.ts
@@ -1,9 +1,11 @@
// Base
import * as base from './_crud-base'
-import type { Doctor } from "~/models/doctor";
+
+// Types
+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)
@@ -31,8 +33,8 @@ export async function getValueLabelList(params: any = null): Promise<{ value: st
if (result.success) {
const resultData = result.body?.data || []
data = resultData.map((item: Doctor) => ({
- value: item.id,
- label: item.employee.person.name,
+ value: item.id ? String(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..b18eac34 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) {
@@ -40,3 +41,20 @@ export async function getValueLabelList(params: any = null): Promise<{ value: st
}
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..e384f059 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) {
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..ec1ccec0 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'
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 100%
rename from public/side-menu-items/doc.json
rename to public/side-menu-items/emp-doc.json
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 91%
rename from public/side-menu-items/nur.json
rename to public/side-menu-items/emp-nur.json
index edcbd575..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",
diff --git a/public/side-menu-items/nut.json b/public/side-menu-items/emp-nut.json
similarity index 100%
rename from public/side-menu-items/nut.json
rename to public/side-menu-items/emp-nut.json
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 92%
rename from public/side-menu-items/sys.json
rename to public/side-menu-items/system.json
index 52db794c..b020b948 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",
@@ -320,21 +320,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
})