diff --git a/app/components/pub/my-ui/data/types.ts b/app/components/pub/my-ui/data/types.ts
index a9b2586b..f27a5578 100644
--- a/app/components/pub/my-ui/data/types.ts
+++ b/app/components/pub/my-ui/data/types.ts
@@ -42,6 +42,12 @@ export interface RefSearchNav {
onClear: () => void
}
+export interface RefExportNav {
+ onExportPdf?: () => void
+ onExportCsv?: () => void
+ onExportExcel?: () => void
+}
+
// prepared header for relatively common usage
export interface HeaderPrep {
title?: string
diff --git a/app/components/pub/my-ui/form/input-base.vue b/app/components/pub/my-ui/form/input-base.vue
index aeb4a4af..a3743734 100644
--- a/app/components/pub/my-ui/form/input-base.vue
+++ b/app/components/pub/my-ui/form/input-base.vue
@@ -19,6 +19,8 @@ const props = defineProps<{
maxLength?: number
isRequired?: boolean
isDisabled?: boolean
+ rightLabel?: string
+ bottomLabel?: string
}>()
function handleInput(event: Event) {
@@ -61,7 +63,7 @@ function handleInput(event: Event) {
v-slot="{ componentField }"
:name="fieldName"
>
-
+
+ {{ rightLabel }}
+ {{ bottomLabel }}
diff --git a/app/components/pub/my-ui/nav-header/filter-dialog.vue b/app/components/pub/my-ui/nav-header/filter-dialog.vue
new file mode 100644
index 00000000..c0d5b854
--- /dev/null
+++ b/app/components/pub/my-ui/nav-header/filter-dialog.vue
@@ -0,0 +1,85 @@
+
+
+
+
+
diff --git a/app/components/pub/my-ui/nav-header/filter.vue b/app/components/pub/my-ui/nav-header/filter.vue
index ab28620b..74f6d8dc 100644
--- a/app/components/pub/my-ui/nav-header/filter.vue
+++ b/app/components/pub/my-ui/nav-header/filter.vue
@@ -5,11 +5,13 @@ import type { Ref } from 'vue'
import type { DateRange } from 'radix-vue'
import { CalendarDate, DateFormatter, getLocalTimeZone } from '@internationalized/date'
import { cn } from '~/lib/utils'
-import type { HeaderPrep, RefSearchNav } from '~/components/pub/my-ui/data/types'
+import type { HeaderPrep, RefExportNav, RefSearchNav } from '~/components/pub/my-ui/data/types'
const props = defineProps<{
prep: HeaderPrep
refSearchNav?: RefSearchNav
+ enableExport?: boolean
+ refExportNav?: RefExportNav
}>()
// function emitSearchNavClick() {
@@ -57,7 +59,7 @@ function onFilterClick() {
-
+
@@ -97,6 +99,30 @@ function onFilterClick() {
Filter
+
+
+
+
+
+ Ekspor
+
+
+
+
+ Ekspor PDF
+
+
+ Ekspor CSV
+
+
+ Ekspor Excel
+
+
+
+
diff --git a/app/handlers/control-letter.handler.ts b/app/handlers/control-letter.handler.ts
new file mode 100644
index 00000000..b096a178
--- /dev/null
+++ b/app/handlers/control-letter.handler.ts
@@ -0,0 +1,24 @@
+// Handlers
+import { genCrudHandler } from '~/handlers/_handler'
+
+// Services
+import { create, update, remove } from '~/services/control-letter.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({
+ create,
+ update,
+ remove,
+})
diff --git a/app/lib/date.ts b/app/lib/date.ts
index 502a6cfb..2c7b92cf 100644
--- a/app/lib/date.ts
+++ b/app/lib/date.ts
@@ -41,4 +41,12 @@ export function getAge(dateString: string, comparedDate?: string): { idFormat: s
idFormat,
extFormat
};
+}
+
+export function formatDateYyyyMmDd(isoDateString: string): string {
+ const date = new Date(isoDateString);
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, '0');
+ const day = String(date.getDate()).padStart(2, '0');
+ return `${year}-${month}-${day}`;
}
\ No newline at end of file
diff --git a/app/models/control-letter.ts b/app/models/control-letter.ts
new file mode 100644
index 00000000..8f520212
--- /dev/null
+++ b/app/models/control-letter.ts
@@ -0,0 +1,37 @@
+import { type Base, genBase } from "./_base"
+import { genDoctor, type Doctor } from "./doctor"
+import { genEncounter, type Encounter } from "./encounter"
+import { genSpecialist, type Specialist } from "./specialist"
+import { genSubspecialist, type Subspecialist } from "./subspecialist"
+import { genUnit, type Unit } from "./unit"
+
+export interface ControlLetter extends Base {
+ encounter_id: number
+ encounter: Encounter
+ unit_id: number
+ unit: Unit
+ specialist_id: number
+ specialist: Specialist
+ subspecialist_id: number
+ subspecialist: Subspecialist
+ doctor_id: number
+ doctor: Doctor
+ date: ''
+}
+
+export function genControlLetter(): ControlLetter {
+ return {
+ ...genBase(),
+ encounter_id: 0,
+ encounter: genEncounter(),
+ unit_id: 0,
+ unit: genUnit(),
+ specialist_id: 0,
+ specialist: genSpecialist(),
+ subspecialist_id: 0,
+ subspecialist: genSubspecialist(),
+ doctor_id: 0,
+ doctor: genDoctor(),
+ date: ''
+ }
+}
diff --git a/app/models/doctor.ts b/app/models/doctor.ts
index 3f517476..1b631907 100644
--- a/app/models/doctor.ts
+++ b/app/models/doctor.ts
@@ -8,10 +8,11 @@ export interface Doctor extends Base {
employee: Employee
ihs_number: string
sip_number: string
- unit_id?: number
- specialist_id?: number
+ code?: string
+ unit_icode?: number
+ specialist_icode?: number
specialist?: Specialist
- subspecialist_id?: number
+ subspecialist_icode?: number
subspecialist?: Subspecialist
bpjs_code?: string
}
@@ -21,9 +22,9 @@ export interface CreateDto {
employee_id: number
ihs_number: string
sip_number: string
- unit_id?: number
- specialist_id?: number
- subspecialist_id?: number
+ unit_code?: number
+ specialist_code?: number
+ subspecialist_code?: number
bpjs_code: string
}
diff --git a/app/pages/(features)/integration/bpjs/control-letter/index.vue b/app/pages/(features)/integration/bpjs/control-letter/index.vue
new file mode 100644
index 00000000..8dcb9006
--- /dev/null
+++ b/app/pages/(features)/integration/bpjs/control-letter/index.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
diff --git a/app/pages/(features)/integration/bpjs/sep/add.vue b/app/pages/(features)/integration/bpjs/sep/add.vue
index 5db12aac..0658780b 100644
--- a/app/pages/(features)/integration/bpjs/sep/add.vue
+++ b/app/pages/(features)/integration/bpjs/sep/add.vue
@@ -22,12 +22,12 @@ const { checkRole, hasCreateAccess } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
-if (!hasAccess) {
- throw createError({
- statusCode: 403,
- statusMessage: 'Access denied',
- })
-}
+// if (!hasAccess) {
+// throw createError({
+// statusCode: 403,
+// statusMessage: 'Access denied',
+// })
+// }
// Define permission-based computed properties
const canCreate = true // hasCreateAccess(roleAccess)
diff --git a/app/pages/(features)/integration/bpjs/sep/index.vue b/app/pages/(features)/integration/bpjs/sep/index.vue
index b8ec57c4..d99dbb5d 100644
--- a/app/pages/(features)/integration/bpjs/sep/index.vue
+++ b/app/pages/(features)/integration/bpjs/sep/index.vue
@@ -22,9 +22,9 @@ const { checkRole, hasReadAccess } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
-if (!hasAccess) {
- navigateTo('/403')
-}
+// if (!hasAccess) {
+// navigateTo('/403')
+// }
// Define permission-based computed properties
const canRead = true // hasReadAccess(roleAccess)
diff --git a/app/pages/(features)/outpatient/encounter/[id]/index.vue b/app/pages/(features)/outpatient/encounter/[id]/index.vue
new file mode 100644
index 00000000..1864cf2c
--- /dev/null
+++ b/app/pages/(features)/outpatient/encounter/[id]/index.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
diff --git a/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/edit.vue b/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/edit.vue
new file mode 100644
index 00000000..cc5d182f
--- /dev/null
+++ b/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/edit.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
diff --git a/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/index.vue b/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/index.vue
new file mode 100644
index 00000000..612315ad
--- /dev/null
+++ b/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/index.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
diff --git a/app/pages/(features)/rehab/encounter/[id]/control-letter/add.vue b/app/pages/(features)/rehab/encounter/[id]/control-letter/add.vue
new file mode 100644
index 00000000..1070a29f
--- /dev/null
+++ b/app/pages/(features)/rehab/encounter/[id]/control-letter/add.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
diff --git a/app/schemas/control-letter.schema.ts b/app/schemas/control-letter.schema.ts
new file mode 100644
index 00000000..c82ffaac
--- /dev/null
+++ b/app/schemas/control-letter.schema.ts
@@ -0,0 +1,47 @@
+import { z } from 'zod'
+
+const ControlLetterSchema = z.object({
+ sepStatus: z.string({
+ required_error: 'Mohon isi status SEP',
+ }).default('SEP Internal'),
+ unit_code: z.string({
+ required_error: 'Mohon isi Unit',
+ }),
+ specialist_code: z.string({
+ required_error: 'Mohon isi Spesialis',
+ }),
+ subspecialist_code: z.string({
+ required_error: 'Mohon isi Sub Spesialis',
+ }),
+ doctor_code: z.string({
+ required_error: 'Mohon isi DPJP',
+ }),
+ encounter_code: z.string().optional(),
+ date: z.string({
+ required_error: 'Mohon lengkapi Tanggal Kontrol',
+ })
+ .refine(
+ (date) => {
+ // Jika kosong, return false untuk required validation
+ if (!date || date.trim() === '') return false
+
+ // Jika ada isi, validasi format tanggal
+ try {
+ const dateObj = new Date(date)
+ // Cek apakah tanggal valid dan tahun >= 1900
+ return !isNaN(dateObj.getTime()) && dateObj.getFullYear() >= 1900
+ } catch {
+ return false
+ }
+ },
+ {
+ message: 'Mohon lengkapi Tanggal Kontrol dengan format yang valid',
+ },
+ )
+ .transform((dateStr) => new Date(dateStr).toISOString()),
+})
+
+type ControlLetterFormData = z.infer
+
+export { ControlLetterSchema }
+export type { ControlLetterFormData }
diff --git a/app/services/doctor.service.ts b/app/services/doctor.service.ts
index 74104c2c..e6ae0051 100644
--- a/app/services/doctor.service.ts
+++ b/app/services/doctor.service.ts
@@ -1,8 +1,6 @@
// Base
import * as base from './_crud-base'
-
-// Types
-import type { Doctor } from '~/models/doctor'
+import type { Doctor } from "~/models/doctor";
const path = '/api/v1/doctor'
const name = 'doctor'
@@ -27,13 +25,15 @@ export function remove(id: number | string) {
return base.remove(path, id, name)
}
-export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+export async function getValueLabelList(params: any = null, useCodeAsValue = false): Promise<{ value: string; label: string }[]> {
let data: { value: string; label: string }[] = []
const result = await getList(params)
if (result.success) {
const resultData = result.body?.data || []
data = resultData.map((item: Doctor) => ({
- value: item.id ? String(item.id) : '',
+ value: useCodeAsValue ? item.code
+ : item.id ? Number(item.id)
+ : item.id,
label: item.employee?.person?.name || '',
}))
}
diff --git a/app/services/specialist.service.ts b/app/services/specialist.service.ts
index b18eac34..d4c81b5c 100644
--- a/app/services/specialist.service.ts
+++ b/app/services/specialist.service.ts
@@ -28,13 +28,15 @@ export function remove(id: number | string) {
return base.remove(path, id, name)
}
-export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+export async function getValueLabelList(params: any = null, useCodeAsValue = false): Promise<{ value: string; label: string }[]> {
let data: { value: string; label: string }[] = []
const result = await getList(params)
if (result.success) {
const resultData = result.body?.data || []
data = resultData.map((item: Specialist) => ({
- value: item.id ? Number(item.id) : item.code,
+ value: useCodeAsValue ? item.code
+ : item.id ? Number(item.id)
+ : item.id,
label: item.name,
parent: item.unit_id ? Number(item.unit_id) : null,
}))
diff --git a/app/services/subspecialist.service.ts b/app/services/subspecialist.service.ts
index e384f059..f13c715f 100644
--- a/app/services/subspecialist.service.ts
+++ b/app/services/subspecialist.service.ts
@@ -27,13 +27,15 @@ export function remove(id: number | string) {
return base.remove(path, id, name)
}
-export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+export async function getValueLabelList(params: any = null, useCodeAsValue = false): Promise<{ value: string; label: string }[]> {
let data: { value: string; label: string }[] = []
const result = await getList(params)
if (result.success) {
const resultData = result.body?.data || []
data = resultData.map((item: Subspecialist) => ({
- value: item.id ? Number(item.id) : item.code,
+ value: useCodeAsValue ? item.code
+ : item.id ? Number(item.id)
+ : item.id,
label: item.name,
parent: item.specialist_id ? Number(item.specialist_id) : null,
}))
diff --git a/app/services/unit.service.ts b/app/services/unit.service.ts
index ec1ccec0..402504b6 100644
--- a/app/services/unit.service.ts
+++ b/app/services/unit.service.ts
@@ -27,13 +27,15 @@ export function remove(id: number | string) {
return base.remove(path, id, name)
}
-export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+export async function getValueLabelList(params: any = null, useCodeAsValue = false): Promise<{ value: string; label: string }[]> {
let data: { value: string; label: string }[] = []
const result = await getList(params)
if (result.success) {
const resultData = result.body?.data || []
data = resultData.map((item: Unit) => ({
- value: item.id,
+ value: useCodeAsValue ? item.code
+ : item.id ? Number(item.id)
+ : item.id,
label: item.name,
}))
}
diff --git a/public/side-menu-items/system.json b/public/side-menu-items/system.json
index d5e4fbb4..31890951 100644
--- a/public/side-menu-items/system.json
+++ b/public/side-menu-items/system.json
@@ -199,6 +199,11 @@
"title": "Peserta",
"icon": "i-lucide-circuit-board",
"link": "/integration/bpjs/member"
+ },
+ {
+ "title": "Surat Kontrol",
+ "icon": "i-lucide-circuit-board",
+ "link": "/integration/bpjs/control-letter"
}
]
},
From 94e4ead8fe13ad7dc518ad87d1f3f01620791d01 Mon Sep 17 00:00:00 2001
From: hasyim_kai
Date: Tue, 18 Nov 2025 13:13:52 +0700
Subject: [PATCH 26/40] Fix: debug updaate medicine master
---
app/components/content/equipment/list.vue | 5 +++--
app/components/content/medicine-group/list.vue | 5 +++--
app/components/content/medicine-method/list.vue | 5 +++--
app/components/content/medicine/list.vue | 5 +++--
app/components/content/tools/list.vue | 4 ++--
5 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/app/components/content/equipment/list.vue b/app/components/content/equipment/list.vue
index 19e5d913..0db6034c 100644
--- a/app/components/content/equipment/list.vue
+++ b/app/components/content/equipment/list.vue
@@ -110,6 +110,7 @@ watch([recId, recAction], () => {
getCurrentMaterialDetail(recId.value)
title.value = 'Edit Perlengkapan'
isReadonly.value = false
+ isFormEntryDialogOpen.value = true
break
case ActionEvents.showConfirmDelete:
isRecordConfirmationOpen.value = true
@@ -158,7 +159,7 @@ onMounted(async () => {
@submit="
(values: MaterialFormData, resetForm: any) => {
if (recId > 0) {
- handleActionEdit(recId, values, getEquipmentList, resetForm, toast)
+ handleActionEdit(recItem.code, values, getEquipmentList, resetForm, toast)
return
}
handleActionSave(values, getEquipmentList, resetForm, toast)
@@ -173,7 +174,7 @@ onMounted(async () => {
v-model:open="isRecordConfirmationOpen"
action="delete"
:record="recItem"
- @confirm="() => handleActionRemove(recId, getEquipmentList, toast)"
+ @confirm="() => handleActionRemove(recItem.code, getEquipmentList, toast)"
@cancel=""
>
diff --git a/app/components/content/medicine-group/list.vue b/app/components/content/medicine-group/list.vue
index 80faf1ab..6c695d72 100644
--- a/app/components/content/medicine-group/list.vue
+++ b/app/components/content/medicine-group/list.vue
@@ -108,6 +108,7 @@ watch([recId, recAction], () => {
getCurrentMedicineGroupDetail(recId.value)
title.value = 'Edit Kelompok Obat'
isReadonly.value = false
+ isFormEntryDialogOpen.value = true
break
case ActionEvents.showConfirmDelete:
isRecordConfirmationOpen.value = true
@@ -154,7 +155,7 @@ onMounted(async () => {
@submit="
(values: BaseFormData | Record, resetForm: () => void) => {
if (recId > 0) {
- handleActionEdit(recId, values, getMedicineGroupList, resetForm, toast)
+ handleActionEdit(recItem.code, values, getMedicineGroupList, resetForm, toast)
return
}
handleActionSave(values, getMedicineGroupList, resetForm, toast)
@@ -169,7 +170,7 @@ onMounted(async () => {
v-model:open="isRecordConfirmationOpen"
action="delete"
:record="recItem"
- @confirm="() => handleActionRemove(recId, getMedicineGroupList, toast)"
+ @confirm="() => handleActionRemove(recItem.code, getMedicineGroupList, toast)"
@cancel=""
>
diff --git a/app/components/content/medicine-method/list.vue b/app/components/content/medicine-method/list.vue
index 9e0e5d01..2c8fb8c6 100644
--- a/app/components/content/medicine-method/list.vue
+++ b/app/components/content/medicine-method/list.vue
@@ -108,6 +108,7 @@ watch([recId, recAction], () => {
getCurrentMedicineMethodDetail(recId.value)
title.value = 'Edit Metode Obat'
isReadonly.value = false
+ isFormEntryDialogOpen.value = true
break
case ActionEvents.showConfirmDelete:
isRecordConfirmationOpen.value = true
@@ -154,7 +155,7 @@ onMounted(async () => {
@submit="
(values: BaseFormData | Record, resetForm: () => void) => {
if (recId > 0) {
- handleActionEdit(recId, values, getMedicineMethodList, resetForm, toast)
+ handleActionEdit(recItem.code, values, getMedicineMethodList, resetForm, toast)
return
}
handleActionSave(values, getMedicineMethodList, resetForm, toast)
@@ -169,7 +170,7 @@ onMounted(async () => {
v-model:open="isRecordConfirmationOpen"
action="delete"
:record="recItem"
- @confirm="() => handleActionRemove(recId, getMedicineMethodList, toast)"
+ @confirm="() => handleActionRemove(recItem.code, getMedicineMethodList, toast)"
@cancel=""
>
diff --git a/app/components/content/medicine/list.vue b/app/components/content/medicine/list.vue
index 43667c33..bfbf8750 100644
--- a/app/components/content/medicine/list.vue
+++ b/app/components/content/medicine/list.vue
@@ -118,6 +118,7 @@ watch([recId, recAction], () => {
case ActionEvents.showEdit:
getCurrentMedicineDetail(recId.value)
title.value = 'Edit Obat'
+ isFormEntryDialogOpen.value = true
isReadonly.value = false
break
case ActionEvents.showConfirmDelete:
@@ -173,7 +174,7 @@ onMounted(async () => {
@submit="
(values: MedicineFormData | Record, resetForm: () => void) => {
if (recId > 0) {
- handleActionEdit(recId, values, getMedicineList, resetForm, toast)
+ handleActionEdit(recItem.code, values, getMedicineList, resetForm, toast)
return
}
handleActionSave(values, getMedicineList, resetForm, toast)
@@ -188,7 +189,7 @@ onMounted(async () => {
v-model:open="isRecordConfirmationOpen"
action="delete"
:record="recItem"
- @confirm="() => handleActionRemove(recId, getMedicineList, toast)"
+ @confirm="() => handleActionRemove(recItem.code, getMedicineList, toast)"
@cancel=""
>
diff --git a/app/components/content/tools/list.vue b/app/components/content/tools/list.vue
index da22a976..4f50199f 100644
--- a/app/components/content/tools/list.vue
+++ b/app/components/content/tools/list.vue
@@ -163,7 +163,7 @@ onMounted(async () => {
@submit="
(values: DeviceFormData, resetForm: any) => {
if (recId > 0) {
- handleActionEdit(recId, values, getToolsList, resetForm, toast)
+ handleActionEdit(recItem.code, values, getToolsList, resetForm, toast)
return
}
handleActionSave(values, getToolsList, resetForm, toast)
@@ -178,7 +178,7 @@ onMounted(async () => {
v-model:open="isRecordConfirmationOpen"
action="delete"
:record="recItem"
- @confirm="() => handleActionRemove(recId, getToolsList, toast)"
+ @confirm="() => handleActionRemove(recItem.code, getToolsList, toast)"
@cancel=""
>
From 9d93afed2b4fe4599fa5fad9cffa9407ae0a87b7 Mon Sep 17 00:00:00 2001
From: hasyim_kai
Date: Tue, 18 Nov 2025 13:26:58 +0700
Subject: [PATCH 27/40] Squashed commit of the following:
commit bcfb4c1456b7b58c63d4969985200ceca72aee16
Merge: 1cbde57 975c87d
Author: Munawwirul Jamal <57973347+munaja@users.noreply.github.com>
Date: Mon Nov 17 11:15:14 2025 +0700
Merge pull request #147 from dikstub-rssa/feat/surat-kontrol-135
Feat: Integration Rehab Medik - Surat Kontrol
commit 975c87d99af0471f62111a455fa214abc1f2e998
Merge: f582090 1cbde57
Author: hasyim_kai
Date: Mon Nov 17 10:58:10 2025 +0700
Merge branch 'dev' into feat/surat-kontrol-135
commit 1cbde57cf955ae8665e4649c6d5b4a4c0b68c830
Author: Munawwirul Jamal
Date: Sun Nov 16 00:44:53 2025 +0700
dev: hotfix
comps/pub/myui
+ updated data/types
+ updated data-table
+ updated nav-header
+ added toggle
comps/pub/ui
+ updated button
+ updated toggle
commit ccabe0177b12182e794d71be101b78657bd9f48a
Author: Munawwirul Jamal
Date: Fri Nov 14 16:39:21 2025 +0700
dev: hotfix, added combobox objectsToItems
commit f582090d18fe797e9f7e0e5b8559b1e413c7c921
Author: hasyim_kai
Date: Thu Nov 13 11:56:21 2025 +0700
Fix: Refactor surat kontrol
commit 0d97ba9d25558ed784f4df43477773c41f7a004b
Merge: 02508b2 bb8df3d
Author: Munawwirul Jamal <57973347+munaja@users.noreply.github.com>
Date: Thu Nov 13 11:52:23 2025 +0700
Merge pull request #164 from dikstub-rssa/feeat/pendaftaran-kemoterapi-141
Feat: Pendaftaran Kemoterapi
commit bb8df3d53aab0b5a2d858d9d41a6d8dab2d4b24d
Merge: a592a0b 02508b2
Author: riefive
Date: Thu Nov 13 10:14:17 2025 +0700
Merge branch 'dev' of https://github.com/dikstub-rssa/simrs-fe into feeat/pendaftaran-kemoterapi-141
commit 02508b22de655d6046d1b6cb54deb14b8b2390cb
Merge: 6b933de 295bb81
Author: Munawwirul Jamal <57973347+munaja@users.noreply.github.com>
Date: Thu Nov 13 07:56:31 2025 +0700
Merge pull request #162 from dikstub-rssa/fe-prescription-56
Fe prescription 56
commit 295bb8120f29ed51580db6d85c6bfbc22d49d2ba
Merge: 8462eba 6b933de
Author: Munawwirul Jamal
Date: Thu Nov 13 07:45:48 2025 +0700
Merge branch 'dev' into fe-prescription-56
commit 6b933de212779ecbd59fb115fe121f656a032339
Merge: f2e98fc 471c846
Author: Munawwirul Jamal <57973347+munaja@users.noreply.github.com>
Date: Wed Nov 12 07:13:11 2025 +0700
Merge pull request #156 from dikstub-rssa/feat/cp-lab-order-48
Feat/cp lab order 48
commit f2e98fc732d895450f79cf45bb5b896daace980e
Merge: 2e899c6 9b281de
Author: Munawwirul Jamal <57973347+munaja@users.noreply.github.com>
Date: Wed Nov 12 07:12:40 2025 +0700
Merge pull request #158 from dikstub-rssa/feat/menu-structure
Feat/menu structure
commit 471c846045a8488f09c0a30b55993076d13a3084
Merge: f676c8a 2e899c6
Author: Andrian Roshandy
Date: Wed Nov 12 07:11:46 2025 +0700
Merge branch 'dev' into feat/cp-lab-order-48
commit 9b281de00bae69b619f1382ec8712c16650b4abb
Merge: 80383a5 2e899c6
Author: Andrian Roshandy
Date: Wed Nov 12 07:08:29 2025 +0700
Merge branch 'dev' into feat/menu-structure
commit 2e899c602259a47da7f587c4936a69d1bb9c770b
Merge: 8effefb b7d4fcf
Author: Munawwirul Jamal <57973347+munaja@users.noreply.github.com>
Date: Wed Nov 12 07:04:47 2025 +0700
Merge pull request #157 from dikstub-rssa/feat/encounter-status-107
Feat/encounter status 107
commit 8effefb5ad4e58dd502026c4f6be907163074410
Merge: 3f63f19 8e7f9b1
Author: Munawwirul Jamal <57973347+munaja@users.noreply.github.com>
Date: Wed Nov 12 07:04:17 2025 +0700
Merge pull request #155 from dikstub-rssa/feat/radiology-order-54
Feat/radiology order 54
commit 80383a5f0a23144814b32be675969e19399c0ae2
Author: Andrian Roshandy
Date: Wed Nov 12 06:52:31 2025 +0700
feat/menu-structure: adjust page rehab
commit 93c9e74d081549df3a3602c29a9c4f3dc7ac7e3e
Author: Andrian Roshandy
Date: Wed Nov 12 06:52:14 2025 +0700
feat/menu-structure: adjust menu items all roles
commit f0d2bc4de1fbc418014857e798573c718f624f39
Author: Andrian Roshandy
Date: Wed Nov 12 06:51:37 2025 +0700
feat/menu-structure: update access control
commit 02c14089f100dadfc2259d288ed663d35950bf5d
Author: Andrian Roshandy
Date: Wed Nov 12 06:51:03 2025 +0700
feat/menu-structure: update role switcher
commit a14c4a5d3c334d3ea7b9875feb5620991511d4f0
Author: hasyim_kai
Date: Tue Nov 11 14:21:58 2025 +0700
Fix: Refactor Surat Kontrol CRUD {id} to {code}
commit e9e0e21d1b7ac2a1bd24706514ea04673fe5fb46
Author: Andrian Roshandy
Date: Tue Nov 11 12:30:43 2025 +0700
feat/menu-structure: wip
commit 8e7f9b19e38cb70110f11878f3f5cd39d25fff13
Author: Munawwirul Jamal
Date: Mon Nov 10 23:17:49 2025 +0700
feat/radiology-order-54: upgraded mcu-order/list
commit 24313adef6bd3db52f23ace0675100bea1aaefad
Author: hasyim_kai
Date: Fri Nov 7 10:35:46 2025 +0700
Fix: debug back btn in add, edit, detail content page
commit 59b44b5729161b3e7c014ea440f17bf98fd8b954
Merge: 99a61a0 db15ec9
Author: Muhammad Hasyim Chaidir Ali <68959522+Hasyim-Kai@users.noreply.github.com>
Date: Fri Nov 7 09:11:10 2025 +0700
Merge branch 'dev' into feat/surat-kontrol-135
commit 99a61a0bf2edf2f924d0424600e94a1d64901e48
Author: hasyim_kai
Date: Thu Nov 6 08:06:01 2025 +0700
Feat: add right & bottom label in input base component
commit 8462eba94b22f73e8a9ef10b8afaac6168246310
Author: Andrian Roshandy
Date: Wed Nov 5 21:23:04 2025 +0700
feat/prescription-56: wip
commit db48919325a9c3a7940cb208fee71c1d42ee9a8a
Author: hasyim_kai
Date: Wed Nov 5 13:53:43 2025 +0700
Feat: add banner in List if requirement not met
commit bd57250f7e9bcaed8e11f6533435e3c788347286
Author: hasyim_kai
Date: Wed Nov 5 13:26:48 2025 +0700
Fix: refactor getDetail url param
commit a361922e32f2e8a649edaedd9cec82131aff2793
Author: hasyim_kai
Date: Wed Nov 5 13:19:07 2025 +0700
Feat: Add & integrate add, edit, detail page
commit 331f4a6b20194964d89eb1ada2d7661d8be8f76d
Author: hasyim_kai
Date: Tue Nov 4 16:56:08 2025 +0700
Feat: Integrate Control Letter
commit a592a0be367f571d11f0a51619d22c0b00c56d51
Author: riefive
Date: Tue Nov 4 15:15:38 2025 +0700
feat(cemo): add home encounter
commit be0a761170afd9cbbb1f163bbe9ed6520b71816e
Author: riefive
Date: Tue Nov 4 13:23:52 2025 +0700
feat(cemo): change flow admin
commit 64fe2524fbdb2279e9df651cadaa110dc4aa8896
Author: riefive
Date: Tue Nov 4 12:02:31 2025 +0700
feat(cemo): enhance admin mode functionality and update series handling
commit fb7731188d249dc0f02ba276e034a1030a686b5d
Author: riefive
Date: Mon Nov 3 15:52:35 2025 +0700
feat(cemo): add mode adm + series
commit 89b2fb9cd95a0e60efaa139ee6efcf7ebe00a61e
Author: riefive
Date: Mon Nov 3 15:03:56 2025 +0700
feat(chemo): add page process and modify components
commit f676c8a4b98c037965328cbde25a523942387f53
Author: Andrian Roshandy
Date: Mon Nov 3 08:11:02 2025 +0700
feat/cp-lab-order-48: wip
commit 69ffe6bd494739961dda1bbea412551bca050832
Author: Andrian Roshandy
Date: Fri Oct 31 14:35:39 2025 +0700
feat/radiology-order: added the page
commit d1369d513bf5781a03e39c51786f8485338f6e0f
Author: riefive
Date: Fri Oct 31 16:08:22 2025 +0700
feat(cemo): add list verification
commit a9ab75fd984945703f3ef7dff990811361c54696
Author: Andrian Roshandy
Date: Fri Oct 31 14:35:05 2025 +0700
feat/readiology-order: added mcu
commit 71d68e5a0ee084b586be48ddf4035735647f2f34
Author: riefive
Date: Fri Oct 31 14:49:21 2025 +0700
feat(cemo): add dialog verification and list register
commit f8d906b6c2077db0d3925b1cc4c47d026ccf9dd0
Merge: 66872c9 5f9e441
Author: Andrian Roshandy
Date: Fri Oct 31 14:48:21 2025 +0700
Merge branch 'dev' into fe-prescription-56
commit 40d78a999a13c249997de573cd72864c68b219e9
Author: Andrian Roshandy
Date: Fri Oct 31 14:35:05 2025 +0700
feat/readiology-order: added mcu
commit b3502df0f8f4b0a75a95828f425bdb6edabdbf61
Merge: 831749a 7119f67
Author: riefive
Date: Fri Oct 31 13:12:11 2025 +0700
Merge branch 'feat/fe-kemoterapi' into feeat/pendaftaran-kemoterapi-141
commit 7119f67402b5261226257b3aa6e193d516f33041
Author: riefive
Date: Fri Oct 31 13:09:59 2025 +0700
feat(cemo): modify schema
commit 66872c95f8949b98e7f14cc10736c7d62e0e3b1e
Author: Munawwirul Jamal
Date: Fri Oct 31 07:56:36 2025 +0700
feat/prescription-56: wip
commit 45cc019ec1f37583e5e950a45a095c74ff099538
Author: riefive
Date: Thu Oct 30 15:43:50 2025 +0700
feat(cemo): layouting form
commit e866c0cf2ae2c3daf1b508e31b9b0ad8a28cfa69
Author: riefive
Date: Thu Oct 30 14:41:52 2025 +0700
feat(cemo): layouting protocol
commit dc4edc1dc0053f350cdf8ad82c4c816099285671
Author: riefive
Date: Wed Oct 29 15:58:52 2025 +0700
feat(cemo): show list cemo
commit 323485347300abee84439e5956815cc2dafc5cf9
Author: riefive
Date: Wed Oct 29 15:39:55 2025 +0700
feat(cemo): add list of cemo
commit 67ee129f4b5fdb4c75340adc0d1841d2dfdc39fc
Merge: 9919b4b 9e82d17
Author: Andrian Roshandy
Date: Tue Oct 28 16:20:17 2025 +0700
Merge branch 'dev' into fe-prescription-56
commit 2275f4dc9991a1e51d0fba31748ff88c85d40bcf
Author: hasyim_kai
Date: Mon Oct 27 14:01:58 2025 +0700
Feat: add UI BPJS > Surat Kontrol
commit 89e0e7a2c8a20ae31ca381d3320bd81755b73c34
Author: hasyim_kai
Date: Mon Oct 27 10:21:59 2025 +0700
Feat: add UI CRUD Surat Kontrol at Rehab Medik > kunjungan > Proses
commit 9919b4b8960d5e3d661d818a887b823b50713d2e
Merge: 19a43bd e93e72a
Author: Andrian Roshandy
Date: Sat Oct 25 15:36:29 2025 +0700
Merge branch 'dev' into fe-prescription-56
commit b7d4fcf9391f0b94183fab5826d635124c272a32
Merge: eaac4aa e93e72a
Author: Andrian Roshandy
Date: Sat Oct 25 15:31:30 2025 +0700
Merge branch 'dev' into feat/encounter-status-107
commit 19a43bd2918d62e4f24fa189e1500e9affe6fe11
Merge: d90e400 3558672
Author: Andrian Roshandy
Date: Sat Oct 25 05:02:57 2025 +0700
Merge branch 'dev' into fe-prescription-56
commit eaac4aab852e27ca515b9340146ddb200e230934
Merge: 72e8d43 3558672
Author: Andrian Roshandy
Date: Sat Oct 25 05:01:45 2025 +0700
Merge branch 'dev' into feat/encounter-status-107
commit d90e40043c9c2f5d8ea963b64b1bb5f233f2d11a
Merge: 0c9f9de b90f0c1
Author: Andrian Roshandy
Date: Fri Oct 24 12:40:59 2025 +0700
Merge branch 'dev' into fe-prescription-56
commit 0c9f9deb7e3220410a3bbec863c4cff0c1deedbe
Author: Andrian Roshandy
Date: Fri Oct 24 12:38:02 2025 +0700
fe-prescription-56: wip
commit 729474a2a0bc8a5e8d346672110dcb7982369636
Merge: 7159bd6 ddd35d6
Author: Andrian Roshandy
Date: Thu Oct 23 14:16:52 2025 +0700
Merge branch 'dev' into fe-prescription-56
commit 72e8d431d6f4fa56fdb30b2dd3370792fb02a277
Merge: 3f77d92 2a9b78a
Author: Andrian Roshandy
Date: Wed Oct 22 07:17:41 2025 +0700
Merge branch 'dev' into feat/encounter-status-107
commit 3f77d927b62827433d8a41be02be1bbe11a7c56c
Author: Andrian Roshandy
Date: Tue Oct 21 22:48:34 2025 +0700
feat/encounter: done
commit d8c861d60ceb402edbbf37d86ab154d25a5242a6
Merge: 6bdee66 27ab7c2
Author: Andrian Roshandy
Date: Tue Oct 21 00:15:01 2025 +0700
Merge branch 'dev' into feat/encounter-status-107
commit 7159bd6566d21ffc74d9c1e725cd3041e1d05e0d
Merge: ccc9b0b be5768b
Author: Andrian Roshandy
Date: Mon Oct 13 07:45:15 2025 +0700
Merge branch 'dev' into fe-prescription-56
commit ccc9b0bda38150a319ee1160233325a0c821b6e6
Merge: f94ccd7 cad7ac6
Author: Andrian Roshandy
Date: Mon Oct 13 06:29:03 2025 +0700
Merge branch 'dev' into fe-prescription-56
commit 6bdee66cc6fa8d05315eea10c6a034680f0b8049
Author: Andrian Roshandy
Date: Mon Oct 13 06:26:30 2025 +0700
feat/encounter: wip
commit f7c53fc4e517b24a98f6b6e4283fe6bf51d1fcf7
Merge: a7c7ef6 cad7ac6
Author: Andrian Roshandy
Date: Mon Oct 13 06:24:45 2025 +0700
Merge branch 'dev' into feat/encounter-status-107
commit a7c7ef6dd8b411597edcda168677c1f980693c8d
Merge: 89b051b f52e516
Author: Andrian Roshandy
Date: Sun Oct 12 13:27:06 2025 +0700
Merge branch 'dev' into feat/encounter-status-107
commit 89b051b883dbd4a647dc4a516ea94c78264bbe1f
Author: Andrian Roshandy
Date: Sun Oct 12 13:18:46 2025 +0700
feat/encounter-status-107: wip
commit 743c38804ae3b38bee3c99c0b9c404d6bd618a1a
Merge: d6d60e3 f7b66d2
Author: Andrian Roshandy
Date: Sun Oct 12 11:53:03 2025 +0700
Merge branch 'dev' into feat/encounter-status-107
commit d6d60e38d06ebf0e52264279b30c167e424e8a45
Merge: 9530cdd 18e00bf
Author: Andrian Roshandy
Date: Sun Oct 12 11:49:49 2025 +0700
Merge branch 'dev' into feat/encounter-status-107
commit 18e00bf89aaedd7a4211ef9cc3dee975bc87d3db
Author: Munawwirul Jamal
Date: Sun Oct 12 11:40:53 2025 +0700
dev: hotfix, text-size standardization
commit 9530cdd4f9659c3133282a94882147628e34e96a
Merge: 0820cb6 0d1e469
Author: Andrian Roshandy
Date: Sun Oct 12 11:41:49 2025 +0700
Merge branch 'dev' into feat/encounter-status-107
commit 0d1e469ece38471ed5496f0d424473cac643461b
Author: Munawwirul Jamal
Date: Sun Oct 12 11:40:53 2025 +0700
dev: hotfix, text-size standardization
commit 0820cb653c6b450f9412dab32ffa8bab4e62845c
Merge: fff1ce0 867c1b4
Author: Andrian Roshandy
Date: Sat Oct 11 00:38:10 2025 +0700
Merge branch 'dev' into feat/encounter-status-107
commit fff1ce0eb75c8dd98640b6eef98c9292efb5bfd9
Merge: 1a3edd5 3a4b2aa
Author: Andrian Roshandy
Date: Sat Oct 11 00:35:16 2025 +0700
Merge branch 'dev' into feat/encounter-status-107
commit 3a4b2aa6fb940b9d29bc1d6743f09e7302764c7e
Author: Munawwirul Jamal
Date: Sat Oct 11 00:25:44 2025 +0700
dev: hotfix, moved combobox and datepicker
commit 1a3edd5a1ec40cd33d534da3c6dc7f7fc5a74e08
Author: Munawwirul Jamal
Date: Fri Oct 10 23:58:44 2025 +0700
dev: hotfix, moved combobox and datepicker
commit f94ccd707bfc59d1a1d2aeeffb11c833531fdf71
Merge: 0647675 51d1221
Author: Munawwirul Jamal
Date: Wed Oct 8 08:00:01 2025 +0700
Merge branch 'feat/consultation-82' into fe-prescription-56
commit 06476756fb7160854de95c6b6ef499c4940f5736
Author: Munawwirul Jamal
Date: Wed Oct 8 07:58:48 2025 +0700
fe-prescription-56: wip
commit fdbcfed87ffcc69ec7448977c4abb68d9800c96a
Merge: 4da896a bd66a88
Author: Andrian Roshandy
Date: Tue Oct 7 03:10:19 2025 +0700
Merge branch 'dev' into fe-prescription-56
commit bd66a8887d6523457a02de7d74aa804b009ec236
Merge: 19e00fa ba61d05
Author: Munawwirul Jamal <57973347+munaja@users.noreply.github.com>
Date: Tue Oct 7 03:07:46 2025 +0700
Merge pull request #103 from dikstub-rssa/feat/fe-integrasi-org-src-72
Feat - Integrasi Org Src
commit ba61d05257ea729e3bee9dd30e6fc2e1c2a8b55b
Author: riefive
Date: Mon Oct 6 12:42:08 2025 +0700
fix: adjustment division app + flow
commit 8601d4a4fd50f5a71060145dc648b0509f72e734
Author: riefive
Date: Mon Oct 6 11:07:05 2025 +0700
fix: remove shared handlers
commit fff5f2c11d9d7a78e0d56cc159e89984a621a19b
Author: riefive
Date: Mon Oct 6 11:06:29 2025 +0700
fix: update content list of specialist, subspecialist, etc
commit 301cb8280397fa76937411c074e997a39c95184d
Author: riefive
Date: Mon Oct 6 11:00:14 2025 +0700
fix: update list medicine
commit 3003ec9d80e0d63e7515aaeb6e574fba1576a8f9
Author: riefive
Date: Mon Oct 6 10:45:15 2025 +0700
fix: update list division + equipment
commit d1bcd6e66c81a3b1d9d0dc96fa269b0eaead9b96
Author: riefive
Date: Mon Oct 6 10:38:10 2025 +0700
fix: update some service
commit 78ae8a8aa05da80440f66e608f9658567a32d16e
Author: riefive
Date: Mon Oct 6 10:26:25 2025 +0700
fix: medicine method and group
commit 8eaf95dd3e7bc150ff35f424875ceb95623e29fb
Author: riefive
Date: Mon Oct 6 10:20:05 2025 +0700
fix: update service for unit and uom
commit 58c0dde377fb29a91e9e74735123229b6d40c035
Author: riefive
Date: Mon Oct 6 10:14:51 2025 +0700
fix: update handler for unit and uom
commit fe23c75aca2905c9de2707690eef9a0487b4bb98
Author: riefive
Date: Mon Oct 6 10:09:24 2025 +0700
fix: update some service and handlers
commit 4da896a242f6878ebb514657b09a67eabb2775d2
Merge: 285c3ee 19e00fa
Author: Andrian Roshandy
Date: Mon Oct 6 09:55:24 2025 +0700
Merge branch 'dev' into fe-prescription-56
commit ecdc5d80d902bf7dfbfd7a83c23d6cb1b978d094
Author: riefive
Date: Mon Oct 6 09:51:31 2025 +0700
fix: update device service and handler
commit 45ea70d415728f166805cf3ca3a53c1518246d1d
Author: riefive
Date: Mon Oct 6 09:44:48 2025 +0700
fix: update crud base
commit 51ddb9d8b59e60f99e5c1d2cac91870423597263
Merge: 42a54bb 19e00fa
Author: riefive
Date: Mon Oct 6 09:40:22 2025 +0700
fix: resolve conflict
commit 19e00fa1438a1d6f32ee5095e9ee9bfc7af738c4
Author: Munawwirul Jamal
Date: Mon Oct 6 08:26:08 2025 +0700
dev: hotfix, moved encounter to pub/component
commit 285c3ee4e5a419dad03110f03920d8f3bbfb5fed
Author: Andrian Roshandy
Date: Mon Oct 6 07:56:29 2025 +0700
Merged Stash
commit 421159971e0e1adad3e564519ff86fa2169a1f45
Author: Andrian Roshandy
Date: Mon Oct 6 04:41:21 2025 +0700
feat/prescription-56: wip
commit 3a45de413dda04dc984f06ffdd06cc128a1c1ab8
Author: Andrian Roshandy
Date: Mon Oct 6 04:31:08 2025 +0700
Merge from Stash
commit e959c3ae610b670456d17ad2557a1c3a9322618e
Merge: 32c69af ad4695c
Author: Andrian Roshandy
Date: Mon Oct 6 04:21:06 2025 +0700
Merge branch 'dev' into fe-prescription-56
commit ad4695c8671afd3c8d29c693bfe4ecf05ca087b8
Author: Munawwirul Jamal
Date: Mon Oct 6 04:18:55 2025 +0700
dev: hotfix, encounter content back nav
commit 42a54bbb3bf4b2a77ab8bd577705d15e8ef1345b
Merge: a7cbbee 55559a4
Author: riefive
Date: Sat Oct 4 09:07:03 2025 +0700
fix: solve conflict after pull
commit a7cbbeeda9c3581d99e8cb2cb22e0387bd56994b
Author: riefive
Date: Sat Oct 4 09:05:28 2025 +0700
feat(division): fixing logic treeview
commit 71e0615ee11527b185c9dea1c479ad9a28b5409f
Author: riefive
Date: Sat Oct 4 08:49:38 2025 +0700
feat(division): restructure division parent
commit f02903e7568e6646ad9eb8b176dc88e89d66513c
Author: riefive
Date: Fri Oct 3 15:00:10 2025 +0700
feat(division): change parent id to number before integrate
commit 2e8667a780290cb45d7e32dd97f28baa5899fcc8
Author: riefive
Date: Fri Oct 3 14:47:02 2025 +0700
feat(division): parent id to default null
commit e65e562690ef4288efbc1aa3a098804ac222f9ec
Author: riefive
Date: Fri Oct 3 12:45:05 2025 +0700
feat(division): change form attribute
commit 9407501c49d0befa1db943ff9938213b16df328c
Author: riefive
Date: Fri Oct 3 11:03:19 2025 +0700
feat(division): change compoent combobox to tree select
commit c5ba07a226a96a44b6cf9726c7a1b6da9643a2d0
Author: riefive
Date: Fri Oct 3 10:54:35 2025 +0700
feat(division): create tree item converter for division
commit 8e7ce771b04f55f4efba39577c2783203048bccb
Author: riefive
Date: Thu Oct 2 15:31:27 2025 +0700
test: call division position
commit 7edab334279be1a387a2baf6c1446fcdb309c211
Author: riefive
Date: Thu Oct 2 14:49:55 2025 +0700
fix: handler reset state
commit ce59eac86c428ba2a1ba892fc510023ccf59058c
Author: riefive
Date: Thu Oct 2 14:37:17 2025 +0700
fix: list unit
commit 39d2869ffb9e0a39a1108fc7278b67881aea31ce
Author: riefive
Date: Thu Oct 2 14:34:19 2025 +0700
fix: list with params error
commit 3c046a4d822aa7c27dc9bd0dd912bd5b66dad43c
Author: riefive
Date: Thu Oct 2 14:12:10 2025 +0700
fix: list integration
commit 6feb480a516a25fa1bd19ffd248bafbb9c3ad101
Author: riefive
Date: Thu Oct 2 11:16:23 2025 +0700
fix: change get encounter class to constants
commit d7d984810e87cecaeccab54845757d27d024e3c7
Author: riefive
Date: Thu Oct 2 11:00:05 2025 +0700
remove previous list + form from any features
commit a6377ef9432c366d3ff8e0a73a9c1e5735867f42
Author: riefive
Date: Wed Oct 1 15:24:54 2025 +0700
fix: includes for unit
commit b00b9b198e302b42b7a6df8f43565e9b91d3f7d5
Author: riefive
Date: Wed Oct 1 15:17:31 2025 +0700
fix: includes for medicine list
commit 4908f167704f72ca7e6d5112c9c2826a5164f7aa
Author: riefive
Date: Wed Oct 1 14:56:11 2025 +0700
fix: search on list file
commit 41405ae113028e36c20f6997bf5e24da455ee53d
Author: riefive
Date: Wed Oct 1 14:36:48 2025 +0700
fix: resolve list organization source
commit 6b69e48bd64a937e1e7cf76e7a370f2d2639aeb5
Author: riefive
Date: Wed Oct 1 13:05:36 2025 +0700
feat(installation): add encounter list
commit 59847dce34b9cb230cdfe19151a2f7f31760282c
Author: riefive
Date: Wed Oct 1 13:01:24 2025 +0700
chore: add shared handlers
commit e78342829e4b3d047c93d4be06d7852e77569c78
Author: riefive
Date: Wed Oct 1 12:38:04 2025 +0700
feat(installation): integrate api installation
commit 55559a4683f0e7781ca3db5b05bfb18dcfbd6d1b
Author: riefive
Date: Fri Oct 3 15:00:10 2025 +0700
feat(division): change parent id to number before integrate
commit 2d8c751788a0364469a921e663aad34d2c0d6c1a
Author: riefive
Date: Fri Oct 3 14:47:02 2025 +0700
feat(division): parent id to default null
commit f374f9ef5b1d4d0094e658d83271508f26a5ea71
Author: riefive
Date: Fri Oct 3 12:45:05 2025 +0700
feat(division): change form attribute
commit 1837afce6cc7799d64e568bc56afea97698ee308
Author: riefive
Date: Fri Oct 3 11:03:19 2025 +0700
feat(division): change compoent combobox to tree select
commit 539a1cefb00ec66eb5db722f01515aa658bc9fa8
Author: riefive
Date: Fri Oct 3 10:54:35 2025 +0700
feat(division): create tree item converter for division
commit 32c69af4e1c01ef4cef71cea9418fd7e8ec4eec8
Merge: 0752855 10bbee9
Author: Andrian Roshandy
Date: Fri Oct 3 06:05:35 2025 +0700
Merge branch 'feat/layout-cleaning' into fe-prescription-56
commit 757b8c044430082bdadc2ebc9a76c6a80fa1cbd3
Author: riefive
Date: Thu Oct 2 15:31:27 2025 +0700
test: call division position
commit 378e6773b8009b3a203ad2c2618353d9004a58d1
Author: riefive
Date: Thu Oct 2 14:49:55 2025 +0700
fix: handler reset state
commit 0e115eed5ecc49c55af8820d0080dd5d1d5f5c04
Author: riefive
Date: Thu Oct 2 14:37:17 2025 +0700
fix: list unit
commit d544d031c3829195fda94eaaa60a6598a729adce
Author: riefive
Date: Thu Oct 2 14:34:19 2025 +0700
fix: list with params error
commit 693d8225bf34a2f2a1ef458940de6c2623708c2d
Author: riefive
Date: Thu Oct 2 14:12:10 2025 +0700
fix: list integration
commit 0752855808492e93e1ff3107a3be52c8037a3faf
Merge: f83dbfe c0557cc
Author: Andrian Roshandy
Date: Thu Oct 2 12:46:54 2025 +0700
Merge branch 'dev' into fe-prescription-56
commit fc3bda14f43bd012215a69916c77f2704cd4d237
Author: riefive
Date: Thu Oct 2 11:16:23 2025 +0700
fix: change get encounter class to constants
commit 9603915fd7cd57bfc23baf5af1127621b8b98d18
Author: riefive
Date: Thu Oct 2 11:00:05 2025 +0700
remove previous list + form from any features
commit 546423bdfb665a0b78ce9a15115fc309aecce274
Author: riefive
Date: Wed Oct 1 15:24:54 2025 +0700
fix: includes for unit
commit db48233f6c9d7c4652e4892af72529a9551040f3
Author: riefive
Date: Wed Oct 1 15:17:31 2025 +0700
fix: includes for medicine list
commit 54a5aaa78ff653c1ba0ba73fa76cf6dcf88004c9
Author: riefive
Date: Wed Oct 1 14:56:11 2025 +0700
fix: search on list file
commit cc41118570c5602f79385b5f07d0e9d51ff60cb5
Author: riefive
Date: Wed Oct 1 14:36:48 2025 +0700
fix: resolve list organization source
commit 6a7a9cda80943cc8e8d4159b65f36d38e1193838
Author: riefive
Date: Wed Oct 1 13:05:36 2025 +0700
feat(installation): add encounter list
commit c96d7383793c1de8775badf861df39758d878cef
Author: riefive
Date: Wed Oct 1 13:01:24 2025 +0700
chore: add shared handlers
commit a48f375018b0a48615b4aa321b434c660ac07291
Author: riefive
Date: Wed Oct 1 12:38:04 2025 +0700
feat(installation): integrate api installation
commit f83dbfeae3f449c40d7eadea34c74e64f7a0e35c
Merge: ba77ed1 f29eb38
Author: Andrian Roshandy
Date: Wed Oct 1 04:02:05 2025 +0700
Merge branch 'feat/layout-cleaning' into fe-prescription-56
commit ba77ed1bb560730be50848950379242d85839020
Merge: 4fbd8ee 97d36f1
Author: Andrian Roshandy
Date: Mon Sep 29 08:27:01 2025 +0700
Merge branch 'dev' into fe-prescription-56
commit 4fbd8ee75715073afe58d5f33611b464c458a387
Author: Andrian Roshandy
Date: Sun Sep 28 07:10:32 2025 +0700
feat/prescription-56: merapikan models
---
.../_common/dropdown-action.vue | 90 ++++++
.../control-letter/_common/history-dialog.vue | 49 +++
.../_common/select-date-range.vue | 104 ++++++
.../_common/select-destination-polyclinic.vue | 70 ++++
.../_common/select-origin-polyclinic.vue | 70 ++++
.../app/bpjs/control-letter/filter.vue | 128 ++++++++
.../app/bpjs/control-letter/list.cfg.ts | 108 +++++++
.../app/bpjs/control-letter/list.vue | 31 ++
.../app/chemotherapy/action-proses.vue | 30 ++
.../app/chemotherapy/dialog-verification.vue | 164 ++++++++++
.../chemotherapy/dropdown-action-process.vue | 63 ++++
.../app/chemotherapy/entry-form.vue | 302 ++++++++++++++++++
.../app/chemotherapy/list-admin.vue | 37 +++
.../app/chemotherapy/list-cfg.admin.ts | 80 +++++
.../app/chemotherapy/list-cfg.medicine.ts | 69 ++++
.../app/chemotherapy/list-cfg.protocol.ts | 62 ++++
app/components/app/chemotherapy/list-cfg.ts | 80 +++++
.../app/chemotherapy/list-cfg.verification.ts | 78 +++++
.../app/chemotherapy/list-cfg.visit.ts | 99 ++++++
.../app/chemotherapy/list-verification.vue | 37 +++
.../app/chemotherapy/list.medicine.vue | 76 +++++
.../app/chemotherapy/list.protocol.vue | 75 +++++
.../app/chemotherapy/list.register.vue | 71 ++++
.../app/chemotherapy/list.visit.vue | 45 +++
app/components/app/chemotherapy/list.vue | 36 +++
app/components/app/chemotherapy/sample.ts | 49 +++
.../app/chemotherapy/status-badge.vue | 28 ++
.../app/chemotherapy/verify-button.vue | 31 ++
.../control-letter/_common/select-date.vue | 116 +++++++
.../control-letter/_common/select-dpjp.vue | 98 ++++++
.../_common/select-specialist.vue | 98 ++++++
.../_common/select-subspecialist.vue | 97 ++++++
.../control-letter/_common/select-unit.vue | 85 +++++
.../app/control-letter/entry-form.vue | 94 ++++++
app/components/app/control-letter/list.cfg.ts | 64 ++++
app/components/app/control-letter/list.vue | 31 ++
app/components/app/control-letter/preview.vue | 54 ++++
.../app/mcu-order-item/list-entry.cfg.ts | 43 +++
.../app/mcu-order-item/list-entry.vue | 26 ++
app/components/app/mcu-order-item/list.cfg.ts | 18 ++
app/components/app/mcu-order-item/list.vue | 20 ++
app/components/app/mcu-order/detail.vue | 32 ++
app/components/app/mcu-order/entry.vue | 0
app/components/app/mcu-order/list-pk.vue | 64 ++++
app/components/app/mcu-order/list.vue | 64 ++++
.../app/mcu-src-category/switcher.vue | 35 ++
.../app/mcu-src/picker-accordion.vue | 49 +++
app/components/app/medicine-mix/list-entry.ts | 50 +++
.../app/medicine-mix/list-entry.vue | 35 ++
.../app/prescription-item/list-entry.vue | 20 +-
.../app/prescription-item/list.cfg.ts | 41 +++
app/components/app/prescription-item/list.vue | 20 ++
.../app/prescription-item/mix-entry.vue | 113 +++++++
.../app/prescription-item/non-mix-entry.vue | 90 ++++++
app/components/app/prescription/detail.vue | 32 ++
app/components/app/prescription/entry.vue | 62 ++--
.../app/prescription/list-entry.vue | 88 +++++
.../app/prescription/list-with-sub.vue | 56 ++++
app/components/app/prescription/list.vue | 94 ++++--
.../content/bpjs/control-letter/list.vue | 220 +++++++++++++
.../content/chemotherapy/admin-list.vue | 150 +++++++++
app/components/content/chemotherapy/list.vue | 75 +++++
.../content/chemotherapy/process.vue | 7 +
.../content/chemotherapy/protocol.vue | 106 ++++++
.../content/chemotherapy/verification.vue | 241 ++++++++++++++
app/components/content/control-letter/add.vue | 133 ++++++++
.../content/control-letter/detail.vue | 79 +++++
.../content/control-letter/edit.vue | 162 ++++++++++
.../content/control-letter/list.vue | 176 ++++++++++
app/components/content/cp-lab-order/entry.vue | 155 +++++++++
app/components/content/cp-lab-order/list.vue | 169 ++++++++++
app/components/content/cp-lab-order/main.vue | 16 +
app/components/content/encounter/home.vue | 190 +++++++++++
app/components/content/encounter/process.vue | 13 +-
app/components/content/prescription/entry.vue | 132 ++++++++
app/components/content/prescription/list.vue | 184 ++++++++---
app/components/content/prescription/main.vue | 16 +
.../content/radiology-order/entry.vue | 155 +++++++++
.../content/radiology-order/list.vue | 169 ++++++++++
.../content/radiology-order/main.vue | 16 +
app/components/layout/AppSidebar.vue | 46 ++-
app/components/layout/SidebarNavFooter.vue | 41 +--
.../pub/my-ui/alert/warning-alert.vue | 27 ++
.../pub/my-ui/badge/status-badge.vue | 26 ++
app/components/pub/my-ui/combobox/index.ts | 13 +
app/components/pub/my-ui/comp-tab/type.ts | 1 +
.../pub/my-ui/confirmation/confirmation.vue | 2 +-
.../pub/my-ui/data-table/data-table.vue | 4 +-
app/components/pub/my-ui/data/types.ts | 9 +-
app/components/pub/my-ui/form/input-base.vue | 6 +-
.../pub/my-ui/nav-footer/ba-dr-su.vue | 4 +-
.../pub/my-ui/nav-header/filter-dialog.vue | 85 +++++
.../pub/my-ui/nav-header/filter.vue | 30 +-
app/components/pub/my-ui/nav-header/prep.vue | 15 +-
.../pub/my-ui/toggle/provided-toggle.vue | 34 ++
app/components/pub/ui/button/index.ts | 2 +-
app/components/pub/ui/toggle/index.ts | 6 +-
app/handlers/control-letter.handler.ts | 24 ++
app/handlers/mcu-order-item.handler.ts | 17 +
app/handlers/mcu-order.handler.ts | 17 +
app/handlers/mcu-src-category.handler.ts | 24 ++
app/handlers/prescription-item.handler.ts | 17 +
app/handlers/prescription.handler.ts | 17 +
app/lib/date.ts | 8 +
app/lib/page-permission.ts | 96 +++---
app/models/consultation.ts | 3 +-
app/models/control-letter.ts | 37 +++
app/models/doctor.ts | 13 +-
app/models/mcu-order.ts | 8 +-
app/models/prescription.ts | 6 +-
.../integration/bpjs/control-letter/index.vue | 40 +++
.../(features)/integration/bpjs/sep/add.vue | 12 +-
.../(features)/integration/bpjs/sep/index.vue | 6 +-
.../outpatient/encounter/[id]/index.vue | 41 +++
.../outpation-action/cemotherapy/index.vue | 10 -
.../chemotherapy/[mode]/[id]/verification.vue | 47 +++
.../chemotherapy/[mode]/index.vue | 55 ++++
.../outpation-action/chemotherapy/index.vue | 9 +
.../outpation-action/chemotherapy/list.vue | 40 +++
.../index.vue | 0
.../[control_letter_id]/edit.vue | 41 +++
.../[control_letter_id]/index.vue | 41 +++
.../encounter/[id]/control-letter/add.vue | 42 +++
.../rehab/encounter/[id]/process.vue | 14 +-
.../(features)/rehab/encounter/index.vue | 6 +-
.../(features)/rehab/examination/index.vue | 3 -
app/schemas/chemotherapy.schema.ts | 73 +++++
app/schemas/control-letter.schema.ts | 47 +++
app/schemas/prescription-item.schema.ts | 10 +
app/schemas/prescription.schema.ts | 11 +
app/services/control-letter.service.ts | 28 ++
app/services/doctor.service.ts | 10 +-
app/services/mcu-order-item.service.ts | 24 ++
app/services/mcu-order.service.ts | 24 ++
app/services/mcu-src-category.service.ts | 25 ++
app/services/mcu-src.service.ts | 25 ++
app/services/prescription-item.service.ts | 23 ++
app/services/prescription.service.ts | 24 ++
app/services/specialist.service.ts | 2 +-
app/services/unit.service.ts | 2 +-
app/stores/user.ts | 29 +-
public/side-menu-items/blank.json | 12 +
public/side-menu-items/div-crd.json | 12 +
.../{doc.json => emp-doc.json} | 4 +-
.../{lab.json => emp-lab.json} | 0
.../{miw.json => emp-mid.json} | 2 +-
.../{nur.json => emp-nur.json} | 10 +-
.../{nut.json => emp-nut.json} | 4 +-
.../{pha.json => emp-pha.json} | 0
.../{reg.json => emp-reg.json} | 0
.../side-menu-items/{sys.json => system.json} | 11 +-
151 files changed, 7702 insertions(+), 270 deletions(-)
create mode 100644 app/components/app/bpjs/control-letter/_common/dropdown-action.vue
create mode 100644 app/components/app/bpjs/control-letter/_common/history-dialog.vue
create mode 100644 app/components/app/bpjs/control-letter/_common/select-date-range.vue
create mode 100644 app/components/app/bpjs/control-letter/_common/select-destination-polyclinic.vue
create mode 100644 app/components/app/bpjs/control-letter/_common/select-origin-polyclinic.vue
create mode 100644 app/components/app/bpjs/control-letter/filter.vue
create mode 100644 app/components/app/bpjs/control-letter/list.cfg.ts
create mode 100644 app/components/app/bpjs/control-letter/list.vue
create mode 100644 app/components/app/chemotherapy/action-proses.vue
create mode 100644 app/components/app/chemotherapy/dialog-verification.vue
create mode 100644 app/components/app/chemotherapy/dropdown-action-process.vue
create mode 100644 app/components/app/chemotherapy/entry-form.vue
create mode 100644 app/components/app/chemotherapy/list-admin.vue
create mode 100644 app/components/app/chemotherapy/list-cfg.admin.ts
create mode 100644 app/components/app/chemotherapy/list-cfg.medicine.ts
create mode 100644 app/components/app/chemotherapy/list-cfg.protocol.ts
create mode 100644 app/components/app/chemotherapy/list-cfg.ts
create mode 100644 app/components/app/chemotherapy/list-cfg.verification.ts
create mode 100644 app/components/app/chemotherapy/list-cfg.visit.ts
create mode 100644 app/components/app/chemotherapy/list-verification.vue
create mode 100644 app/components/app/chemotherapy/list.medicine.vue
create mode 100644 app/components/app/chemotherapy/list.protocol.vue
create mode 100644 app/components/app/chemotherapy/list.register.vue
create mode 100644 app/components/app/chemotherapy/list.visit.vue
create mode 100644 app/components/app/chemotherapy/list.vue
create mode 100644 app/components/app/chemotherapy/sample.ts
create mode 100644 app/components/app/chemotherapy/status-badge.vue
create mode 100644 app/components/app/chemotherapy/verify-button.vue
create mode 100644 app/components/app/control-letter/_common/select-date.vue
create mode 100644 app/components/app/control-letter/_common/select-dpjp.vue
create mode 100644 app/components/app/control-letter/_common/select-specialist.vue
create mode 100644 app/components/app/control-letter/_common/select-subspecialist.vue
create mode 100644 app/components/app/control-letter/_common/select-unit.vue
create mode 100644 app/components/app/control-letter/entry-form.vue
create mode 100644 app/components/app/control-letter/list.cfg.ts
create mode 100644 app/components/app/control-letter/list.vue
create mode 100644 app/components/app/control-letter/preview.vue
create mode 100644 app/components/app/mcu-order-item/list-entry.cfg.ts
create mode 100644 app/components/app/mcu-order-item/list-entry.vue
create mode 100644 app/components/app/mcu-order-item/list.cfg.ts
create mode 100644 app/components/app/mcu-order-item/list.vue
create mode 100644 app/components/app/mcu-order/detail.vue
create mode 100644 app/components/app/mcu-order/entry.vue
create mode 100644 app/components/app/mcu-order/list-pk.vue
create mode 100644 app/components/app/mcu-order/list.vue
create mode 100644 app/components/app/mcu-src-category/switcher.vue
create mode 100644 app/components/app/mcu-src/picker-accordion.vue
create mode 100644 app/components/app/medicine-mix/list-entry.ts
create mode 100644 app/components/app/medicine-mix/list-entry.vue
create mode 100644 app/components/app/prescription-item/list.cfg.ts
create mode 100644 app/components/app/prescription-item/list.vue
create mode 100644 app/components/app/prescription-item/mix-entry.vue
create mode 100644 app/components/app/prescription-item/non-mix-entry.vue
create mode 100644 app/components/app/prescription/detail.vue
create mode 100644 app/components/app/prescription/list-entry.vue
create mode 100644 app/components/app/prescription/list-with-sub.vue
create mode 100644 app/components/content/bpjs/control-letter/list.vue
create mode 100644 app/components/content/chemotherapy/admin-list.vue
create mode 100644 app/components/content/chemotherapy/list.vue
create mode 100644 app/components/content/chemotherapy/process.vue
create mode 100644 app/components/content/chemotherapy/protocol.vue
create mode 100644 app/components/content/chemotherapy/verification.vue
create mode 100644 app/components/content/control-letter/add.vue
create mode 100644 app/components/content/control-letter/detail.vue
create mode 100644 app/components/content/control-letter/edit.vue
create mode 100644 app/components/content/control-letter/list.vue
create mode 100644 app/components/content/cp-lab-order/entry.vue
create mode 100644 app/components/content/cp-lab-order/list.vue
create mode 100644 app/components/content/cp-lab-order/main.vue
create mode 100644 app/components/content/encounter/home.vue
create mode 100644 app/components/content/prescription/entry.vue
create mode 100644 app/components/content/prescription/main.vue
create mode 100644 app/components/content/radiology-order/entry.vue
create mode 100644 app/components/content/radiology-order/list.vue
create mode 100644 app/components/content/radiology-order/main.vue
create mode 100644 app/components/pub/my-ui/alert/warning-alert.vue
create mode 100644 app/components/pub/my-ui/badge/status-badge.vue
create mode 100644 app/components/pub/my-ui/nav-header/filter-dialog.vue
create mode 100644 app/components/pub/my-ui/toggle/provided-toggle.vue
create mode 100644 app/handlers/control-letter.handler.ts
create mode 100644 app/handlers/mcu-order-item.handler.ts
create mode 100644 app/handlers/mcu-order.handler.ts
create mode 100644 app/handlers/mcu-src-category.handler.ts
create mode 100644 app/handlers/prescription-item.handler.ts
create mode 100644 app/handlers/prescription.handler.ts
create mode 100644 app/models/control-letter.ts
create mode 100644 app/pages/(features)/integration/bpjs/control-letter/index.vue
create mode 100644 app/pages/(features)/outpatient/encounter/[id]/index.vue
delete mode 100644 app/pages/(features)/outpation-action/cemotherapy/index.vue
create mode 100644 app/pages/(features)/outpation-action/chemotherapy/[mode]/[id]/verification.vue
create mode 100644 app/pages/(features)/outpation-action/chemotherapy/[mode]/index.vue
create mode 100644 app/pages/(features)/outpation-action/chemotherapy/index.vue
create mode 100644 app/pages/(features)/outpation-action/chemotherapy/list.vue
rename app/pages/(features)/rehab/{examination-queue => encounter-queue}/index.vue (100%)
create mode 100644 app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/edit.vue
create mode 100644 app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/index.vue
create mode 100644 app/pages/(features)/rehab/encounter/[id]/control-letter/add.vue
delete mode 100644 app/pages/(features)/rehab/examination/index.vue
create mode 100644 app/schemas/chemotherapy.schema.ts
create mode 100644 app/schemas/control-letter.schema.ts
create mode 100644 app/schemas/prescription-item.schema.ts
create mode 100644 app/schemas/prescription.schema.ts
create mode 100644 app/services/control-letter.service.ts
create mode 100644 app/services/mcu-order-item.service.ts
create mode 100644 app/services/mcu-order.service.ts
create mode 100644 app/services/mcu-src-category.service.ts
create mode 100644 app/services/mcu-src.service.ts
create mode 100644 app/services/prescription-item.service.ts
create mode 100644 app/services/prescription.service.ts
create mode 100644 public/side-menu-items/blank.json
create mode 100644 public/side-menu-items/div-crd.json
rename public/side-menu-items/{doc.json => emp-doc.json} (96%)
rename public/side-menu-items/{lab.json => emp-lab.json} (100%)
rename public/side-menu-items/{miw.json => emp-mid.json} (93%)
rename public/side-menu-items/{nur.json => emp-nur.json} (89%)
rename public/side-menu-items/{nut.json => emp-nut.json} (93%)
rename public/side-menu-items/{pha.json => emp-pha.json} (100%)
rename public/side-menu-items/{reg.json => emp-reg.json} (100%)
rename public/side-menu-items/{sys.json => system.json} (96%)
diff --git a/app/components/app/bpjs/control-letter/_common/dropdown-action.vue b/app/components/app/bpjs/control-letter/_common/dropdown-action.vue
new file mode 100644
index 00000000..9086c883
--- /dev/null
+++ b/app/components/app/bpjs/control-letter/_common/dropdown-action.vue
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/app/bpjs/control-letter/_common/history-dialog.vue b/app/components/app/bpjs/control-letter/_common/history-dialog.vue
new file mode 100644
index 00000000..00d7b32f
--- /dev/null
+++ b/app/components/app/bpjs/control-letter/_common/history-dialog.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ item?.createdAt.toLocaleDateString('id-ID') }}
+
+
{{ item.description }}
+
+
+
+
+
\ No newline at end of file
diff --git a/app/components/app/bpjs/control-letter/_common/select-date-range.vue b/app/components/app/bpjs/control-letter/_common/select-date-range.vue
new file mode 100644
index 00000000..114f8542
--- /dev/null
+++ b/app/components/app/bpjs/control-letter/_common/select-date-range.vue
@@ -0,0 +1,104 @@
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ df.format(value.start.toDate(getLocalTimeZone())) }} -
+ {{ df.format(value.end.toDate(getLocalTimeZone())) }}
+
+
+
+ {{ df.format(value.start.toDate(getLocalTimeZone())) }}
+
+
+ Pick a date
+
+
+
+ (value.start = startDate)"
+ />
+
+
+
+
+
+
+
+
+
diff --git a/app/components/app/bpjs/control-letter/_common/select-destination-polyclinic.vue b/app/components/app/bpjs/control-letter/_common/select-destination-polyclinic.vue
new file mode 100644
index 00000000..0852195b
--- /dev/null
+++ b/app/components/app/bpjs/control-letter/_common/select-destination-polyclinic.vue
@@ -0,0 +1,70 @@
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/app/bpjs/control-letter/_common/select-origin-polyclinic.vue b/app/components/app/bpjs/control-letter/_common/select-origin-polyclinic.vue
new file mode 100644
index 00000000..0852195b
--- /dev/null
+++ b/app/components/app/bpjs/control-letter/_common/select-origin-polyclinic.vue
@@ -0,0 +1,70 @@
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/app/bpjs/control-letter/filter.vue b/app/components/app/bpjs/control-letter/filter.vue
new file mode 100644
index 00000000..50005069
--- /dev/null
+++ b/app/components/app/bpjs/control-letter/filter.vue
@@ -0,0 +1,128 @@
+
+
+
+
+
+
diff --git a/app/components/app/bpjs/control-letter/list.cfg.ts b/app/components/app/bpjs/control-letter/list.cfg.ts
new file mode 100644
index 00000000..8eb7e5f4
--- /dev/null
+++ b/app/components/app/bpjs/control-letter/list.cfg.ts
@@ -0,0 +1,108 @@
+import type { Config } from '~/components/pub/my-ui/data-table'
+import type { Patient } from '~/models/patient'
+import { defineAsyncComponent } from 'vue'
+import { educationCodes, genderCodes } from '~/lib/constants'
+import { calculateAge } from '~/lib/utils'
+
+const action = defineAsyncComponent(() => import('./_common/dropdown-action.vue'))
+const statusBadge = defineAsyncComponent(() => import('~/components/pub/my-ui/badge/status-badge.vue'))
+
+export const config: Config = {
+ cols: [{}, {}, {}, {},{}, {}, {}, {}, {}, {width: 90},{width: 10},],
+
+ headers: [
+ [
+ { label: 'No Surat' },
+ { label: 'No MR' },
+ { label: 'Nama' },
+ { label: 'Tgl Rencana Kontrol' },
+ { label: 'Tgl Penerbitan' },
+ { label: 'Klinik Asal' },
+ { label: 'Klinik Tujuan' },
+ { label: 'DPJP' },
+ { label: 'No SEP Asal' },
+ { label: 'Status' },
+ { label: 'Action' },
+ ],
+ ],
+
+ keys: ['birth_date', 'number', 'person.name', 'birth_date', 'birth_date',
+ 'birth_date', 'number', 'person.name', 'birth_date', 'status', 'action'],
+
+ delKeyNames: [
+ { key: 'code', label: 'Kode' },
+ { key: 'name', label: 'Nama' },
+ ],
+
+ parses: {
+ patientId: (rec: unknown): unknown => {
+ const patient = rec as Patient
+ return patient.number
+ },
+ identity_number: (rec: unknown): unknown => {
+ const { person } = rec as Patient
+
+ if (person.nationality == 'WNA') {
+ return person.passportNumber
+ }
+
+ return person.residentIdentityNumber || '-'
+ },
+ birth_date: (rec: unknown): unknown => {
+ const { person } = rec as Patient
+
+ if (typeof person.birthDate == 'object' && person.birthDate) {
+ return (person.birthDate as Date).toLocaleDateString('id-ID')
+ } else if (typeof person.birthDate == 'string') {
+ return (person.birthDate as string).substring(0, 10)
+ }
+ return person.birthDate
+ },
+ patient_age: (rec: unknown): unknown => {
+ const { person } = rec as Patient
+ return calculateAge(person.birthDate)
+ },
+ gender: (rec: unknown): unknown => {
+ const { person } = rec as Patient
+
+ if (typeof person.gender_code == 'number' && person.gender_code >= 0) {
+ return person.gender_code
+ } else if (typeof person.gender_code === 'string' && person.gender_code) {
+ return genderCodes[person.gender_code] || '-'
+ }
+ return '-'
+ },
+ education: (rec: unknown): unknown => {
+ const { person } = rec as Patient
+ if (typeof person.education_code == 'number' && person.education_code >= 0) {
+ return person.education_code
+ } else if (typeof person.education_code === 'string' && person.education_code) {
+ return educationCodes[person.education_code] || '-'
+ }
+ return '-'
+ },
+ },
+
+ components: {
+ action(rec, idx) {
+ return {
+ idx,
+ rec: rec as object,
+ component: action,
+ }
+ },
+ status(rec, idx) {
+ return {
+ idx,
+ rec: rec as object,
+ component: statusBadge,
+ }
+ },
+ },
+
+ htmls: {
+ patient_address(_rec) {
+ return '-'
+ },
+ },
+}
diff --git a/app/components/app/bpjs/control-letter/list.vue b/app/components/app/bpjs/control-letter/list.vue
new file mode 100644
index 00000000..8274e752
--- /dev/null
+++ b/app/components/app/bpjs/control-letter/list.vue
@@ -0,0 +1,31 @@
+
+
+
+
+
diff --git a/app/components/app/chemotherapy/action-proses.vue b/app/components/app/chemotherapy/action-proses.vue
new file mode 100644
index 00000000..4e2efeb3
--- /dev/null
+++ b/app/components/app/chemotherapy/action-proses.vue
@@ -0,0 +1,30 @@
+
+
+
+
+
+ Proses
+
+
+
+
diff --git a/app/components/app/chemotherapy/dialog-verification.vue b/app/components/app/chemotherapy/dialog-verification.vue
new file mode 100644
index 00000000..2d617445
--- /dev/null
+++ b/app/components/app/chemotherapy/dialog-verification.vue
@@ -0,0 +1,164 @@
+
+
+
+
+
+
+
+
Jadwal Ruang Tindakan
+
+
+
+
+ NO
+ NAMA JENIS
+ JENIS PEMERIKSAAN
+
+
+
+
+ {{ row.no }}
+ {{ row.namaJenis }}
+ {{ row.jenisPemeriksaan }}
+
+
+
+
+
+
+
+
+ Tanggal Pemeriksaan
+
+
+
+
+
+
+ Jadwal Tanggal Pemeriksaan
+ *
+
+
+
+
+
+
+
+
+ Simpan Jadwal
+
+
+
+
+
+
diff --git a/app/components/app/chemotherapy/dropdown-action-process.vue b/app/components/app/chemotherapy/dropdown-action-process.vue
new file mode 100644
index 00000000..56e14886
--- /dev/null
+++ b/app/components/app/chemotherapy/dropdown-action-process.vue
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/app/chemotherapy/entry-form.vue b/app/components/app/chemotherapy/entry-form.vue
new file mode 100644
index 00000000..39113d63
--- /dev/null
+++ b/app/components/app/chemotherapy/entry-form.vue
@@ -0,0 +1,302 @@
+
+
+
+
+
diff --git a/app/components/app/chemotherapy/list-admin.vue b/app/components/app/chemotherapy/list-admin.vue
new file mode 100644
index 00000000..a201f2a1
--- /dev/null
+++ b/app/components/app/chemotherapy/list-admin.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
+
diff --git a/app/components/app/chemotherapy/list-cfg.admin.ts b/app/components/app/chemotherapy/list-cfg.admin.ts
new file mode 100644
index 00000000..38d77121
--- /dev/null
+++ b/app/components/app/chemotherapy/list-cfg.admin.ts
@@ -0,0 +1,80 @@
+import type { Config, RecComponent } from '~/components/pub/my-ui/data-table'
+import { defineAsyncComponent } from 'vue'
+
+type SmallDetailDto = any
+
+const action = defineAsyncComponent(() => import('./dropdown-action-process.vue'))
+
+export const config: Config = {
+ cols: [
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 50 },
+ ],
+
+ headers: [
+ [
+ { label: 'TANGGAL' },
+ { label: 'NO. RM' },
+ { label: 'NO. BILL' },
+ { label: 'JK' },
+ { label: 'ALAMAT' },
+ { label: 'KLINIK ASAL' },
+ { label: 'NAMA DOKTER' },
+ { label: 'CARA BAYAR' },
+ { label: 'RUJUKAN' },
+ { label: 'KET. RUJUKAN' },
+ { label: 'ASAL' },
+ { label: '' },
+ ],
+ ],
+
+ keys: [
+ 'tanggal',
+ 'noRm',
+ 'noBill',
+ 'jk',
+ 'alamat',
+ 'klinik',
+ 'dokter',
+ 'caraBayar',
+ 'rujukan',
+ 'ketRujukan',
+ 'asal',
+ 'action',
+ ],
+
+ delKeyNames: [
+ { key: 'code', label: 'Kode' },
+ { key: 'name', label: 'Nama' },
+ ],
+
+ parses: {
+ parent: (rec: unknown): unknown => {
+ const recX = rec as SmallDetailDto
+ return recX.parent?.name || '-'
+ },
+ },
+
+ components: {
+ action(rec, idx) {
+ const res: RecComponent = {
+ idx,
+ rec: rec as object,
+ component: action,
+ }
+ return res
+ },
+ },
+
+ htmls: {},
+}
diff --git a/app/components/app/chemotherapy/list-cfg.medicine.ts b/app/components/app/chemotherapy/list-cfg.medicine.ts
new file mode 100644
index 00000000..103452f5
--- /dev/null
+++ b/app/components/app/chemotherapy/list-cfg.medicine.ts
@@ -0,0 +1,69 @@
+import type { Config, RecComponent } from '~/components/pub/my-ui/data-table'
+import { defineAsyncComponent } from 'vue'
+
+type SmallDetailDto = any
+
+const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-dud.vue'))
+
+export const config: Config = {
+ cols: [
+ { width: 60 },
+ { width: 200 },
+ { width: 100 },
+ { width: 100 },
+ { width: 150 },
+ { width: 80 },
+ { width: 200 },
+ { width: 120 },
+ ],
+
+ headers: [
+ [
+ { label: 'NO.' },
+ { label: 'NAMA OBAT' },
+ { label: 'DOSIS' },
+ { label: 'SATUAN' },
+ { label: 'RUTE PEMBERIAN' },
+ { label: 'HARI' },
+ { label: 'CATATAN' },
+ { label: '' },
+ ],
+ ],
+
+ keys: [
+ 'number',
+ 'namaObat',
+ 'dosis',
+ 'satuan',
+ 'rute',
+ 'hari',
+ 'catatan',
+ 'action',
+ ],
+
+ delKeyNames: [
+ { key: 'code', label: 'Kode' },
+ { key: 'name', label: 'Nama' },
+ ],
+
+ parses: {
+ parent: (rec: unknown): unknown => {
+ const recX = rec as SmallDetailDto
+ return recX.parent?.name || '-'
+ },
+ },
+
+ components: {
+ action(rec, idx) {
+ const res: RecComponent = {
+ idx,
+ rec: rec as object,
+ component: action,
+ }
+ return res
+ },
+ },
+
+ htmls: {},
+}
+
diff --git a/app/components/app/chemotherapy/list-cfg.protocol.ts b/app/components/app/chemotherapy/list-cfg.protocol.ts
new file mode 100644
index 00000000..da678c0f
--- /dev/null
+++ b/app/components/app/chemotherapy/list-cfg.protocol.ts
@@ -0,0 +1,62 @@
+import type { Config, RecComponent } from '~/components/pub/my-ui/data-table'
+import { defineAsyncComponent } from 'vue'
+
+type SmallDetailDto = any
+
+const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-dud.vue'))
+
+export const config: Config = {
+ cols: [
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 50 },
+ ],
+
+ headers: [
+ [
+ { label: 'NO.' },
+ { label: 'TANGGAL' },
+ { label: 'SIKLUS' },
+ { label: 'PERIODE KEMOTERAPI' },
+ { label: 'KEHADIRAN' },
+ { label: '' },
+ ],
+ ],
+
+ keys: [
+ 'number',
+ 'tanggal',
+ 'siklus',
+ 'periode',
+ 'kehadiran',
+ 'action',
+ ],
+
+ delKeyNames: [
+ { key: 'code', label: 'Kode' },
+ { key: 'name', label: 'Nama' },
+ ],
+
+ parses: {
+ parent: (rec: unknown): unknown => {
+ const recX = rec as SmallDetailDto
+ return recX.parent?.name || '-'
+ },
+ },
+
+ components: {
+ action(rec, idx) {
+ const res: RecComponent = {
+ idx,
+ rec: rec as object,
+ component: action,
+ }
+ return res
+ },
+ },
+
+ htmls: {},
+}
diff --git a/app/components/app/chemotherapy/list-cfg.ts b/app/components/app/chemotherapy/list-cfg.ts
new file mode 100644
index 00000000..29c24e6f
--- /dev/null
+++ b/app/components/app/chemotherapy/list-cfg.ts
@@ -0,0 +1,80 @@
+import type { Config, RecComponent } from '~/components/pub/my-ui/data-table'
+import { defineAsyncComponent } from 'vue'
+
+type SmallDetailDto = any
+
+const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-dud.vue'))
+
+export const config: Config = {
+ cols: [
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 120 },
+ { width: 50 },
+ ],
+
+ headers: [
+ [
+ { label: 'TANGGAL' },
+ { label: 'NO. RM' },
+ { label: 'NO. BILL' },
+ { label: 'JK' },
+ { label: 'ALAMAT' },
+ { label: 'KLINIK ASAL' },
+ { label: 'NAMA DOKTER' },
+ { label: 'CARA BAYAR' },
+ { label: 'RUJUKAN' },
+ { label: 'KET. RUJUKAN' },
+ { label: 'ASAL' },
+ { label: '' },
+ ],
+ ],
+
+ keys: [
+ 'tanggal',
+ 'noRm',
+ 'noBill',
+ 'jk',
+ 'alamat',
+ 'klinik',
+ 'dokter',
+ 'caraBayar',
+ 'rujukan',
+ 'ketRujukan',
+ 'asal',
+ 'action',
+ ],
+
+ delKeyNames: [
+ { key: 'code', label: 'Kode' },
+ { key: 'name', label: 'Nama' },
+ ],
+
+ parses: {
+ parent: (rec: unknown): unknown => {
+ const recX = rec as SmallDetailDto
+ return recX.parent?.name || '-'
+ },
+ },
+
+ components: {
+ action(rec, idx) {
+ const res: RecComponent = {
+ idx,
+ rec: rec as object,
+ component: action,
+ }
+ return res
+ },
+ },
+
+ htmls: {},
+}
diff --git a/app/components/app/chemotherapy/list-cfg.verification.ts b/app/components/app/chemotherapy/list-cfg.verification.ts
new file mode 100644
index 00000000..e75aa615
--- /dev/null
+++ b/app/components/app/chemotherapy/list-cfg.verification.ts
@@ -0,0 +1,78 @@
+import type { Config, RecComponent } from '~/components/pub/my-ui/data-table'
+import { defineAsyncComponent } from 'vue'
+
+type SmallDetailDto = any
+
+const statusBadge = defineAsyncComponent(() => import('./status-badge.vue'))
+const verifyButton = defineAsyncComponent(() => import('./verify-button.vue'))
+
+export const config: Config = {
+ cols: [
+ { width: 120 },
+ { width: 150 },
+ { width: 150 },
+ { width: 150 },
+ { width: 150 },
+ { width: 180 },
+ { width: 150 },
+ { width: 100 },
+ ],
+
+ headers: [
+ [
+ { label: 'TANGGAL MASUK' },
+ { label: 'PJ BERKAS RM' },
+ { label: 'DOKTER' },
+ { label: 'JENIS RUANGAN' },
+ { label: 'JENIS TINDAKAN' },
+ { label: 'TANGGAL JADWAL TINDAKAN' },
+ { label: 'STATUS' },
+ { label: 'AKSI' },
+ ],
+ ],
+
+ keys: [
+ 'tanggalMasuk',
+ 'pjBerkasRm',
+ 'dokter',
+ 'jenisRuangan',
+ 'jenisTindakan',
+ 'tanggalJadwalTindakan',
+ 'status',
+ 'action',
+ ],
+
+ delKeyNames: [
+ { key: 'code', label: 'Kode' },
+ { key: 'name', label: 'Nama' },
+ ],
+
+ parses: {
+ parent: (rec: unknown): unknown => {
+ const recX = rec as SmallDetailDto
+ return recX.parent?.name || '-'
+ },
+ },
+
+ components: {
+ status(rec, idx) {
+ const res: RecComponent = {
+ idx,
+ rec: rec as object,
+ component: statusBadge,
+ }
+ return res
+ },
+ action(rec, idx) {
+ const res: RecComponent = {
+ idx,
+ rec: rec as object,
+ component: verifyButton,
+ }
+ return res
+ },
+ },
+
+ htmls: {},
+}
+
diff --git a/app/components/app/chemotherapy/list-cfg.visit.ts b/app/components/app/chemotherapy/list-cfg.visit.ts
new file mode 100644
index 00000000..cb242d62
--- /dev/null
+++ b/app/components/app/chemotherapy/list-cfg.visit.ts
@@ -0,0 +1,99 @@
+import type { Config, RecComponent } from '~/components/pub/my-ui/data-table'
+import { defineAsyncComponent } from 'vue'
+import { format, parseISO } from 'date-fns'
+import { id as localeID } from 'date-fns/locale'
+
+type VisitDto = any
+
+const statusBadge = defineAsyncComponent(() => import('./status-badge.vue'))
+const verifyButton = defineAsyncComponent(() => import('./verify-button.vue'))
+
+export const config: Config = {
+ cols: [
+ { width: 150 }, // TANGGAL MASUK
+ { width: 180 }, // PJ BERKAS RM
+ { width: 200 }, // DOKTER
+ { width: 150 }, // JENIS RUANGAN
+ { width: 150 }, // JENIS TINDAKAN
+ { width: 180 }, // TANGGAL JADWAL TINDAKAN
+ { width: 150 }, // STATUS
+ { width: 120 }, // AKSI
+ ],
+
+ headers: [
+ [
+ { label: 'TANGGAL MASUK' },
+ { label: 'PJ BERKAS RM' },
+ { label: 'DOKTER' },
+ { label: 'JENIS RUANGAN' },
+ { label: 'JENIS TINDAKAN' },
+ { label: 'TANGGAL JADWAL TINDAKAN' },
+ { label: 'STATUS' },
+ { label: 'AKSI' },
+ ],
+ ],
+
+ keys: [
+ 'tanggal_masuk',
+ 'pj_berkas_rm',
+ 'dokter',
+ 'jenis_ruangan',
+ 'jenis_tindakan',
+ 'tanggal_jadwal_tindakan',
+ 'status',
+ 'action',
+ ],
+
+ delKeyNames: [
+ { key: 'id', label: 'ID' },
+ { key: 'nama', label: 'Nama' },
+ ],
+
+ parses: {
+ tanggal_masuk: (rec: unknown): string => {
+ const recX = rec as VisitDto
+ if (!recX.tanggal_masuk) return '-'
+ try {
+ const date = typeof recX.tanggal_masuk === 'string' ? parseISO(recX.tanggal_masuk) : recX.tanggal_masuk
+ return format(date, 'dd MMMM yyyy', { locale: localeID })
+ } catch {
+ return recX.tanggal_masuk.toString()
+ }
+ },
+ tanggal_jadwal_tindakan: (rec: unknown): string => {
+ const recX = rec as VisitDto
+ if (!recX.tanggal_jadwal_tindakan) return '-'
+ try {
+ const date =
+ typeof recX.tanggal_jadwal_tindakan === 'string'
+ ? parseISO(recX.tanggal_jadwal_tindakan)
+ : recX.tanggal_jadwal_tindakan
+ return format(date, 'dd MMMM yyyy', { locale: localeID })
+ } catch {
+ return recX.tanggal_jadwal_tindakan.toString()
+ }
+ },
+ },
+
+ components: {
+ status(rec, idx) {
+ const res: RecComponent = {
+ idx,
+ rec: rec as object,
+ component: statusBadge,
+ }
+ return res
+ },
+ action(rec, idx) {
+ const res: RecComponent = {
+ idx,
+ rec: rec as object,
+ component: verifyButton,
+ }
+ return res
+ },
+ },
+
+ htmls: {},
+}
+
diff --git a/app/components/app/chemotherapy/list-verification.vue b/app/components/app/chemotherapy/list-verification.vue
new file mode 100644
index 00000000..93120f69
--- /dev/null
+++ b/app/components/app/chemotherapy/list-verification.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
+
diff --git a/app/components/app/chemotherapy/list.medicine.vue b/app/components/app/chemotherapy/list.medicine.vue
new file mode 100644
index 00000000..748c8cb9
--- /dev/null
+++ b/app/components/app/chemotherapy/list.medicine.vue
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
Protokol Obat Kemoterapi
+
Daftar obat-obatan yang digunakan dalam protokol kemoterapi.
+
+
+
+ Tambah Obat Kemoterapi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/app/chemotherapy/list.protocol.vue b/app/components/app/chemotherapy/list.protocol.vue
new file mode 100644
index 00000000..7b5c3234
--- /dev/null
+++ b/app/components/app/chemotherapy/list.protocol.vue
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
Protokol Kemoterapi
+
Rangkaian prosedur kemoterapi yang terintegrasi dan konsisten.
+
+
+
+ Tambah Protokol Kemoterapi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/app/chemotherapy/list.register.vue b/app/components/app/chemotherapy/list.register.vue
new file mode 100644
index 00000000..131afc04
--- /dev/null
+++ b/app/components/app/chemotherapy/list.register.vue
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
Daftar Kunjungan Rawat Jalan Kemoterapi
+
Manajemen pendaftaran serta monitoring terapi pasien tindakan rawat jalan.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/app/chemotherapy/list.visit.vue b/app/components/app/chemotherapy/list.visit.vue
new file mode 100644
index 00000000..de451f31
--- /dev/null
+++ b/app/components/app/chemotherapy/list.visit.vue
@@ -0,0 +1,45 @@
+
+
+
+
+
+
diff --git a/app/components/app/chemotherapy/list.vue b/app/components/app/chemotherapy/list.vue
new file mode 100644
index 00000000..19642581
--- /dev/null
+++ b/app/components/app/chemotherapy/list.vue
@@ -0,0 +1,36 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/components/app/chemotherapy/sample.ts b/app/components/app/chemotherapy/sample.ts
new file mode 100644
index 00000000..082cde66
--- /dev/null
+++ b/app/components/app/chemotherapy/sample.ts
@@ -0,0 +1,49 @@
+export type ChemotherapyData = {
+ id: number
+ tanggal: string
+ noRm: string
+ noBill: string
+ nama: string
+ jk: string
+ alamat: string
+ klinik: string
+ dokter: string
+ caraBayar: string
+ rujukan: string
+ ketRujukan: string
+ asal: string
+}
+
+export const sampleRows: ChemotherapyData[] = [
+ {
+ id: 1,
+ tanggal: '12 Agustus 2025',
+ noRm: 'RM23311224',
+ noBill: '-',
+ nama: 'Ahmad Baidowi',
+ jk: 'L',
+ alamat: 'Jl Jaksa Agung S. No. 9',
+ klinik: 'Penyakit dalam',
+ dokter: 'Dr. Andreas Sutaji',
+ caraBayar: 'JKN',
+ rujukan: 'Faskes BPJS',
+ ketRujukan: 'RUMAH SAKIT - RS Lawang Medika - Malang',
+ asal: 'Rawat Jalan Reguler',
+ },
+ {
+ id: 2,
+ tanggal: '11 Agustus 2025',
+ noRm: 'RM23455667',
+ noBill: '-',
+ nama: 'Abraham Sulaiman',
+ jk: 'L',
+ alamat: 'Purwantoro, Blimbing',
+ klinik: 'Penyakit dalam',
+ dokter: 'Dr. Andreas Sutaji',
+ caraBayar: 'JKN',
+ rujukan: 'Faskes BPJS',
+ ketRujukan: 'RUMAH SAKIT - RS Lawang Medika - Malang',
+ asal: 'Rawat Jalan Reguler',
+ },
+ // tambahkan lebih banyak baris contoh jika perlu
+]
diff --git a/app/components/app/chemotherapy/status-badge.vue b/app/components/app/chemotherapy/status-badge.vue
new file mode 100644
index 00000000..1a7d94ca
--- /dev/null
+++ b/app/components/app/chemotherapy/status-badge.vue
@@ -0,0 +1,28 @@
+
+
+
+
+
+ {{ statusInfo.text }}
+
+
+
+
diff --git a/app/components/app/chemotherapy/verify-button.vue b/app/components/app/chemotherapy/verify-button.vue
new file mode 100644
index 00000000..1d9c2d3a
--- /dev/null
+++ b/app/components/app/chemotherapy/verify-button.vue
@@ -0,0 +1,31 @@
+
+
+
+
+
+ Verifikasi
+
+
+
+
diff --git a/app/components/app/control-letter/_common/select-date.vue b/app/components/app/control-letter/_common/select-date.vue
new file mode 100644
index 00000000..057d0a63
--- /dev/null
+++ b/app/components/app/control-letter/_common/select-date.vue
@@ -0,0 +1,116 @@
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+ {
+ const dateStr = typeof value === 'number' ? String(value) : value
+ patientAge = calculateAge(dateStr)
+ }
+ "
+ />
+
+
+
+
+
+
+
diff --git a/app/components/app/control-letter/_common/select-dpjp.vue b/app/components/app/control-letter/_common/select-dpjp.vue
new file mode 100644
index 00000000..2053ebdb
--- /dev/null
+++ b/app/components/app/control-letter/_common/select-dpjp.vue
@@ -0,0 +1,98 @@
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/app/control-letter/_common/select-specialist.vue b/app/components/app/control-letter/_common/select-specialist.vue
new file mode 100644
index 00000000..cd5ee923
--- /dev/null
+++ b/app/components/app/control-letter/_common/select-specialist.vue
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+ Spesialis
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/app/control-letter/_common/select-subspecialist.vue b/app/components/app/control-letter/_common/select-subspecialist.vue
new file mode 100644
index 00000000..61567c0c
--- /dev/null
+++ b/app/components/app/control-letter/_common/select-subspecialist.vue
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+ Sub Spesialis
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/app/control-letter/_common/select-unit.vue b/app/components/app/control-letter/_common/select-unit.vue
new file mode 100644
index 00000000..afe0ca0a
--- /dev/null
+++ b/app/components/app/control-letter/_common/select-unit.vue
@@ -0,0 +1,85 @@
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/app/control-letter/entry-form.vue b/app/components/app/control-letter/entry-form.vue
new file mode 100644
index 00000000..2517e8b1
--- /dev/null
+++ b/app/components/app/control-letter/entry-form.vue
@@ -0,0 +1,94 @@
+
+
+
+
+
diff --git a/app/components/app/control-letter/list.cfg.ts b/app/components/app/control-letter/list.cfg.ts
new file mode 100644
index 00000000..3eb7bd84
--- /dev/null
+++ b/app/components/app/control-letter/list.cfg.ts
@@ -0,0 +1,64 @@
+import type { Config } from '~/components/pub/my-ui/data-table'
+import type { Patient } from '~/models/patient'
+import { defineAsyncComponent } from 'vue'
+import { educationCodes, genderCodes } from '~/lib/constants'
+import { calculateAge } from '~/lib/utils'
+
+const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-dud.vue'))
+
+export const config: Config = {
+ cols: [{width: 180}, {}, {}, {}, {}, {width: 30},],
+
+ headers: [
+ [
+ { label: 'Tgl Rencana Kontrol' },
+ { label: 'Spesialis' },
+ { label: 'Sub Spesialis' },
+ { label: 'DPJP' },
+ { label: 'Status SEP' },
+ { label: 'Action' },
+ ],
+ ],
+
+ keys: ['date', 'specialist.name', 'subspecialist.name', 'doctor.employee.person.name', 'sep_status', 'action'],
+
+ delKeyNames: [
+ { key: 'code', label: 'Kode' },
+ { key: 'name', label: 'Nama' },
+ ],
+
+ parses: {
+ date: (rec: unknown): unknown => {
+ const date = (rec as any).date
+ if (typeof date == 'object' && date) {
+ return (date as Date).toLocaleDateString('id-ID')
+ } else if (typeof date == 'string') {
+ return (date as string).substring(0, 10)
+ }
+ return date
+ },
+ specialist_subspecialist: (rec: unknown): unknown => {
+ return '-'
+ },
+ dpjp: (rec: unknown): unknown => {
+ // const { person } = rec as Patient
+ return '-'
+ },
+ },
+
+ components: {
+ action(rec, idx) {
+ return {
+ idx,
+ rec: rec as object,
+ component: action,
+ }
+ },
+ },
+
+ htmls: {
+ sep_status(_rec) {
+ return 'SEP Internal'
+ },
+ },
+}
diff --git a/app/components/app/control-letter/list.vue b/app/components/app/control-letter/list.vue
new file mode 100644
index 00000000..8274e752
--- /dev/null
+++ b/app/components/app/control-letter/list.vue
@@ -0,0 +1,31 @@
+
+
+
+
+
diff --git a/app/components/app/control-letter/preview.vue b/app/components/app/control-letter/preview.vue
new file mode 100644
index 00000000..e10a2b91
--- /dev/null
+++ b/app/components/app/control-letter/preview.vue
@@ -0,0 +1,54 @@
+
+
+
+
+ {{ props.instance?.date ? new Date(props.instance?.date).toLocaleDateString('id-ID') : '-' }}
+ {{ props.instance?.unit.name || '-' }}
+ {{ props.instance?.specialist.name || '-' }}
+ {{ props.instance?.subspecialist.name || '-' }}
+ {{ props.instance?.doctor.employee.person.name || '-' }}
+ {{ 'SEP INTERNAL' }}
+
+
+
+
+
diff --git a/app/components/app/mcu-order-item/list-entry.cfg.ts b/app/components/app/mcu-order-item/list-entry.cfg.ts
new file mode 100644
index 00000000..89d85dce
--- /dev/null
+++ b/app/components/app/mcu-order-item/list-entry.cfg.ts
@@ -0,0 +1,43 @@
+import type { Config } from '~/components/pub/my-ui/data-table'
+import { defineAsyncComponent } from 'vue'
+
+const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-dud.vue'))
+const input = defineAsyncComponent(() => import('~/components/pub/ui/input/Input.vue'))
+
+export const config: Config = {
+ cols: [{}, {}, { classVal: '!p-0.5' }, { width: 50 }],
+
+ headers: [
+ [
+ { label: 'Nama' },
+ { label: 'Jenis' },
+ { label: 'Catatan' },
+ { label: '' },
+ ],
+ ],
+
+ keys: ['mcuSrc.name', 'mcuSrc.mcuSrcCategory.name', 'note'],
+
+ delKeyNames: [
+ { key: 'mcuSrc.name', label: 'Nama' },
+ ],
+
+ components: {
+ note(rec, idx) {
+ return {
+ idx,
+ rec: rec as object,
+ component: input,
+ }
+ },
+ action(rec, idx) {
+ return {
+ idx,
+ rec: rec as object,
+ component: action,
+ }
+ },
+ },
+
+ htmls: {},
+}
diff --git a/app/components/app/mcu-order-item/list-entry.vue b/app/components/app/mcu-order-item/list-entry.vue
new file mode 100644
index 00000000..6c93c5ac
--- /dev/null
+++ b/app/components/app/mcu-order-item/list-entry.vue
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+ Pilih Item
+
+
+
diff --git a/app/components/app/mcu-order-item/list.cfg.ts b/app/components/app/mcu-order-item/list.cfg.ts
new file mode 100644
index 00000000..2b054379
--- /dev/null
+++ b/app/components/app/mcu-order-item/list.cfg.ts
@@ -0,0 +1,18 @@
+import type { Config } from '~/components/pub/my-ui/data-table'
+
+export const config: Config = {
+ cols: [{}, {}],
+
+ headers: [
+ [
+ { label: 'Nama' },
+ { label: 'Jenis' },
+ ],
+ ],
+
+ keys: ['mcuSrc.name', 'mcuSrcCategory.name'],
+
+ delKeyNames: [
+ { key: 'mcuSrc.name', label: 'Nama' },
+ ],
+}
diff --git a/app/components/app/mcu-order-item/list.vue b/app/components/app/mcu-order-item/list.vue
new file mode 100644
index 00000000..ef7438c6
--- /dev/null
+++ b/app/components/app/mcu-order-item/list.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
diff --git a/app/components/app/mcu-order/detail.vue b/app/components/app/mcu-order/detail.vue
new file mode 100644
index 00000000..fe161595
--- /dev/null
+++ b/app/components/app/mcu-order/detail.vue
@@ -0,0 +1,32 @@
+
+
+
+
+ Order {{ data?.createdAt?.substring(0, 10) }} - {{ data.status_code }}
+
+
+
+
+ DPJP
+
+ {{ data?.doctor?.employee?.person?.name || '.........' }}
+
+
+
+
+ PPDS
+
+ ...........
+
+
+
+
+
\ No newline at end of file
diff --git a/app/components/app/mcu-order/entry.vue b/app/components/app/mcu-order/entry.vue
new file mode 100644
index 00000000..e69de29b
diff --git a/app/components/app/mcu-order/list-pk.vue b/app/components/app/mcu-order/list-pk.vue
new file mode 100644
index 00000000..df296419
--- /dev/null
+++ b/app/components/app/mcu-order/list-pk.vue
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+ Order #{{ data.length - idx }} - {{ item.createdAt?.substring(0, 10) }} - {{ item.status_code }}
+
+
+
+ DPJP
+
+ {{ item.doctor?.employee?.person?.name || '........' }}
+
+
+
+ PPDS
+
+ ...........
+
+
+
+ { navClick(type, item) }"
+ />
+
+
+
+
+
diff --git a/app/components/app/mcu-order/list.vue b/app/components/app/mcu-order/list.vue
new file mode 100644
index 00000000..df296419
--- /dev/null
+++ b/app/components/app/mcu-order/list.vue
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+ Order #{{ data.length - idx }} - {{ item.createdAt?.substring(0, 10) }} - {{ item.status_code }}
+
+
+
+ DPJP
+
+ {{ item.doctor?.employee?.person?.name || '........' }}
+
+
+
+ PPDS
+
+ ...........
+
+
+
+ { navClick(type, item) }"
+ />
+
+
+
+
+
diff --git a/app/components/app/mcu-src-category/switcher.vue b/app/components/app/mcu-src-category/switcher.vue
new file mode 100644
index 00000000..78c54acb
--- /dev/null
+++ b/app/components/app/mcu-src-category/switcher.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+ Kategori
+
+
+
+ {{ item.name }}
+
+
+
+
diff --git a/app/components/app/mcu-src/picker-accordion.vue b/app/components/app/mcu-src/picker-accordion.vue
new file mode 100644
index 00000000..a42834f9
--- /dev/null
+++ b/app/components/app/mcu-src/picker-accordion.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
diff --git a/app/components/app/medicine-mix/list-entry.ts b/app/components/app/medicine-mix/list-entry.ts
new file mode 100644
index 00000000..03202670
--- /dev/null
+++ b/app/components/app/medicine-mix/list-entry.ts
@@ -0,0 +1,50 @@
+import type {
+ Col,
+ KeyLabel,
+ RecComponent,
+ RecStrFuncComponent,
+ RecStrFuncUnknown,
+ Th,
+} from '~/components/pub/my-ui/data/types'
+import { defineAsyncComponent } from 'vue'
+
+type SmallDetailDto = any
+
+const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-dud.vue'))
+
+export const cols: Col[] = [{}, {}, {}, {}, {}, {}, { width: 50 }]
+
+export const header: Th[][] = [
+ [
+ { label: 'Nama' },
+ { label: "Dosis" },
+ { label: 'Satuan' },
+ { label: '' },
+ ],
+]
+
+export const keys = ['name', 'dose', 'uom.name', 'action']
+
+export const delKeyNames: KeyLabel[] = [
+ { key: 'code', label: 'Kode' },
+ { key: 'name', label: 'Nama' },
+]
+
+export const funcParsed: RecStrFuncUnknown = {
+ group: (rec: unknown): unknown => {
+ return (rec as SmallDetailDto).medicineGroup_code || '-'
+ },
+}
+
+export const funcComponent: RecStrFuncComponent = {
+ action: (rec: unknown, idx: number): RecComponent => {
+ const res: RecComponent = {
+ idx,
+ rec: rec as object,
+ component: action,
+ }
+ return res
+ },
+}
+
+export const funcHtml: RecStrFuncUnknown = {}
diff --git a/app/components/app/medicine-mix/list-entry.vue b/app/components/app/medicine-mix/list-entry.vue
new file mode 100644
index 00000000..ba0fa689
--- /dev/null
+++ b/app/components/app/medicine-mix/list-entry.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
diff --git a/app/components/app/prescription-item/list-entry.vue b/app/components/app/prescription-item/list-entry.vue
index 5b496b2b..422ebba7 100644
--- a/app/components/app/prescription-item/list-entry.vue
+++ b/app/components/app/prescription-item/list-entry.vue
@@ -1,14 +1,30 @@
-
+
+
+
+ Tambah Racikan
+
+
+
+ Tambah Non Racikan
+
+
diff --git a/app/components/app/prescription-item/list.cfg.ts b/app/components/app/prescription-item/list.cfg.ts
new file mode 100644
index 00000000..fd980bb1
--- /dev/null
+++ b/app/components/app/prescription-item/list.cfg.ts
@@ -0,0 +1,41 @@
+import type { Config } from '~/components/pub/my-ui/data-table'
+import { defineAsyncComponent } from 'vue'
+
+type SmallDetailDto = any
+
+export const config: Config = {
+ cols: [{}, {}, {}, {}, {}, {}],
+
+ headers: [
+ [
+ { label: 'Nama' },
+ { label: 'Bentuk' },
+ { label: 'Freq' },
+ { label: 'Dosis' },
+ { label: 'Interval' },
+ { label: 'Total' },
+ ],
+ ],
+
+ keys: ['name', 'uom_code', 'frequency', 'multiplier', 'interval', 'total'],
+
+ delKeyNames: [
+ { key: 'code', label: 'Kode' },
+ { key: 'name', label: 'Nama' },
+ ],
+
+ parses: {
+ cateogry: (rec: unknown): unknown => {
+ return (rec as SmallDetailDto).medicineCategory?.name || '-'
+ },
+ group: (rec: unknown): unknown => {
+ return (rec as SmallDetailDto).medicineGroup?.name || '-'
+ },
+ method: (rec: unknown): unknown => {
+ return (rec as SmallDetailDto).medicineMethod?.name || '-'
+ },
+ unit: (rec: unknown): unknown => {
+ return (rec as SmallDetailDto).medicineUnit?.name || '-'
+ },
+ },
+}
diff --git a/app/components/app/prescription-item/list.vue b/app/components/app/prescription-item/list.vue
new file mode 100644
index 00000000..ed64b09e
--- /dev/null
+++ b/app/components/app/prescription-item/list.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
diff --git a/app/components/app/prescription-item/mix-entry.vue b/app/components/app/prescription-item/mix-entry.vue
new file mode 100644
index 00000000..d9b4881e
--- /dev/null
+++ b/app/components/app/prescription-item/mix-entry.vue
@@ -0,0 +1,113 @@
+
+
+
+
+
+ Nama
+
+
+
+ Frequensi
+
+
+
+ Dosis
+
+
+
+ Sediaan
+
+
+
+ Total
+
+
+
+ Cara Pakai
+
+
+
+ Daftar Obat
+
+
+
+ Nama
+ Dosis
+ Satuan
+ ..
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Belum ada data
+
+
+
+
+
+
+
+ Tambah
+
+
+
+
+
+
+
diff --git a/app/components/app/prescription-item/non-mix-entry.vue b/app/components/app/prescription-item/non-mix-entry.vue
new file mode 100644
index 00000000..25970646
--- /dev/null
+++ b/app/components/app/prescription-item/non-mix-entry.vue
@@ -0,0 +1,90 @@
+
+
+
+
+
+ Nama
+
+
+
+ Frequensi
+
+
+
+ Dosis
+
+
+
+ Sediaan
+
+
+
+ Interval
+
+
+
+
+
+ Total
+
+
+
+
+
+ Cara Pakai
+
+
+
+
+
+
+
+
diff --git a/app/components/app/prescription/detail.vue b/app/components/app/prescription/detail.vue
new file mode 100644
index 00000000..694eb9a1
--- /dev/null
+++ b/app/components/app/prescription/detail.vue
@@ -0,0 +1,32 @@
+
+
+
+
+ Order {{ data.issuedAt?.substring(0, 10) || data.createdAt?.substring(0, 10) }} - {{ data.status_code }}
+
+
+
+
+ DPJP
+
+ {{ data.doctor?.employee?.person?.name || '.........' }}
+
+
+
+
+ PPDS
+
+ ...........
+
+
+
+
+
\ No newline at end of file
diff --git a/app/components/app/prescription/entry.vue b/app/components/app/prescription/entry.vue
index 3b4acf28..ef8756e8 100644
--- a/app/components/app/prescription/entry.vue
+++ b/app/components/app/prescription/entry.vue
@@ -1,32 +1,36 @@
-
-
-
- DPJP
-
-
-
-
-
-
- Tgl Order
-
-
-
-
-
- DPJP
-
-
-
-
-
-
- Status
-
-
-
-
-
+
diff --git a/app/components/app/prescription/list-entry.vue b/app/components/app/prescription/list-entry.vue
new file mode 100644
index 00000000..aa768000
--- /dev/null
+++ b/app/components/app/prescription/list-entry.vue
@@ -0,0 +1,88 @@
+
+
+
+
+ Memuat data..
+
+
+
+
+
+
+
+
+ Order #{{ data.length - idx }}
+
+ 2025-01-01
+
+
+
+ Status
+
+ {{ item.status_code }}
+
+
+
+
+
+
+
+ DPJP
+
+ {{ item.doctor?.employee?.person.name }}
+
+
+
+ PPDS
+
+ {{ item.specialistIntern?.person.name }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/app/prescription/list-with-sub.vue b/app/components/app/prescription/list-with-sub.vue
new file mode 100644
index 00000000..14bc1785
--- /dev/null
+++ b/app/components/app/prescription/list-with-sub.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
Belum Ada Data
+
+
+
+ Tambah Order
+
+
+
+
+
+
+
+
+ Order #1
+
+
+ 2025-01-01
+
+
+
+ Status
+
+
+ Status
+
+
+
+
+
+
+
+ DPJP
+
+
+ Nama Dokter
+
+
+
+ PPDS
+
+
+ Nama PPDS
+
+
+
+
+
+
diff --git a/app/components/app/prescription/list.vue b/app/components/app/prescription/list.vue
index 6fe27d39..ae5126ca 100644
--- a/app/components/app/prescription/list.vue
+++ b/app/components/app/prescription/list.vue
@@ -1,5 +1,37 @@
+
+
-
+
Belum Ada Data
@@ -8,35 +40,33 @@
-
-
+
+
+ Order #{{ data.length - idx }} - {{ item.issuedAt?.substring(0, 10) || item.createdAt?.substring(0, 10) }} - {{ item.status_code }}
+
+
+
+ DPJP
+
+ {{ item.doctor?.employee?.person?.name || '-' }}
+
+
+
+ PPDS
+
+ ...........
+
+
+
+ { navClick(type, item) }"
+ />
+
+
+
+
+
diff --git a/app/components/content/bpjs/control-letter/list.vue b/app/components/content/bpjs/control-letter/list.vue
new file mode 100644
index 00000000..66ed00a5
--- /dev/null
+++ b/app/components/content/bpjs/control-letter/list.vue
@@ -0,0 +1,220 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ID:
+ {{ record?.id }}
+
+
+ Nama:
+ {{ record.firstName }}
+
+
+ Kode:
+ {{ record.cellphone }}
+
+
+
+
+
diff --git a/app/components/content/chemotherapy/admin-list.vue b/app/components/content/chemotherapy/admin-list.vue
new file mode 100644
index 00000000..be6d5810
--- /dev/null
+++ b/app/components/content/chemotherapy/admin-list.vue
@@ -0,0 +1,150 @@
+
+
+
+
+
+
+
Administrasi Pasien Rawat Jalan Kemoterapi
+
+ Manajemen pendaftaran serta monitoring terapi pasien tindakan rawat jalan
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ dateRangeDisplay }}
+
+
+
+
+
+
+
+
+
+
+ Filter
+
+
+
+
+
+
+
+
diff --git a/app/components/content/chemotherapy/list.vue b/app/components/content/chemotherapy/list.vue
new file mode 100644
index 00000000..d4104f03
--- /dev/null
+++ b/app/components/content/chemotherapy/list.vue
@@ -0,0 +1,75 @@
+
+
+
+
+
+
Daftar Kunjungan Rawat Jalan Kemoterapi
+
+ Manajemen pendaftaran serta monitoring terapi pasien tindakan rawat jalan
+
+
+
+
+
+
+
+
diff --git a/app/components/content/chemotherapy/process.vue b/app/components/content/chemotherapy/process.vue
new file mode 100644
index 00000000..7f355b4b
--- /dev/null
+++ b/app/components/content/chemotherapy/process.vue
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/app/components/content/chemotherapy/protocol.vue b/app/components/content/chemotherapy/protocol.vue
new file mode 100644
index 00000000..82050d79
--- /dev/null
+++ b/app/components/content/chemotherapy/protocol.vue
@@ -0,0 +1,106 @@
+
+
+
+
+
diff --git a/app/components/content/chemotherapy/verification.vue b/app/components/content/chemotherapy/verification.vue
new file mode 100644
index 00000000..3243547a
--- /dev/null
+++ b/app/components/content/chemotherapy/verification.vue
@@ -0,0 +1,241 @@
+
+
+
+
+
+
+
+
+
+
+ Kembali ke Administrasi Kunjungan
+
+
+
+
+
+
Data Pasien:
+
+
+
+
+ No. RM:
+ {{ patientData.noRm }}
+
+
+ Nama:
+ {{ patientData.nama }}
+
+
+ Jenis Pembayaran:
+ {{ patientData.jenisPembayaran }}
+
+
+ No Billing:
+ {{ patientData.noBilling }}
+
+
+
+
+
+ Tanggal Lahir / Usia:
+ {{ patientData.tanggalLahir }} / {{ patientData.usia }}
+
+
+ Jenis Kelamin:
+ {{ patientData.jenisKelamin }}
+
+
+ Diagnosis:
+ {{ patientData.diagnosis }}
+
+
+ Klinik:
+ {{ patientData.klinik }}
+
+
+
+
+
+
+
+
Verifikasi Jadwal Pasien
+
+ Pantau riwayat masuk, dokter penanggung jawab, dan status pasien secara real-time.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ dateRangeDisplay }}
+
+
+
+
+
+
+
+
+
+
+ Filter
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/content/control-letter/add.vue b/app/components/content/control-letter/add.vue
new file mode 100644
index 00000000..44f03a2f
--- /dev/null
+++ b/app/components/content/control-letter/add.vue
@@ -0,0 +1,133 @@
+
+
+
+ Tambah Surat Kontrol
+
+
+
+
+
+
+
+
diff --git a/app/components/content/control-letter/detail.vue b/app/components/content/control-letter/detail.vue
new file mode 100644
index 00000000..d9019d57
--- /dev/null
+++ b/app/components/content/control-letter/detail.vue
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
diff --git a/app/components/content/control-letter/edit.vue b/app/components/content/control-letter/edit.vue
new file mode 100644
index 00000000..99a5c282
--- /dev/null
+++ b/app/components/content/control-letter/edit.vue
@@ -0,0 +1,162 @@
+
+
+
+ Update Surat Kontrol
+
+
+
+
+
+
+
+
diff --git a/app/components/content/control-letter/list.vue b/app/components/content/control-letter/list.vue
new file mode 100644
index 00000000..c9353057
--- /dev/null
+++ b/app/components/content/control-letter/list.vue
@@ -0,0 +1,176 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ID:
+ {{ record?.id }}
+
+
+ Nama:
+ {{ record.firstName }}
+
+
+ Kode:
+ {{ record.cellphone }}
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pickerDialogOpen = false" class="justify-center" />
+
+
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/encounter/home.vue b/app/components/content/encounter/home.vue
new file mode 100644
index 00000000..1f2c2943
--- /dev/null
+++ b/app/components/content/encounter/home.vue
@@ -0,0 +1,190 @@
+
+
+
+
+
diff --git a/app/components/content/encounter/process.vue b/app/components/content/encounter/process.vue
index ad93387d..23640af7 100644
--- a/app/components/content/encounter/process.vue
+++ b/app/components/content/encounter/process.vue
@@ -14,8 +14,11 @@ import Status from '~/components/content/encounter/status.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'
+import ControlLetterList from '~/components/content/control-letter/list.vue'
const route = useRoute()
const router = useRouter()
@@ -60,17 +63,17 @@ const tabs: TabItem[] = [
{ 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' },
{ value: 'mcu-result', label: 'Hasil Penunjang' },
{ value: 'consultation', label: 'Konsultasi', component: Consultation, props: { encounter: data } },
{ value: 'resume', label: 'Resume' },
- { value: 'control', label: 'Surat Kontrol' },
+ { value: 'control', label: 'Surat Kontrol', component: ControlLetterList, props: { encounter: data } },
{ value: 'screening', label: 'Skrinning MPP' },
{ value: 'supporting-document', label: 'Upload Dokumen Pendukung' },
]
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 @@
-
+
+
-
-
-
-
-
-
-
- Tambah
-
-
+ 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/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/alert/warning-alert.vue b/app/components/pub/my-ui/alert/warning-alert.vue
new file mode 100644
index 00000000..afdbe7ae
--- /dev/null
+++ b/app/components/pub/my-ui/alert/warning-alert.vue
@@ -0,0 +1,27 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/components/pub/my-ui/badge/status-badge.vue b/app/components/pub/my-ui/badge/status-badge.vue
new file mode 100644
index 00000000..ba8a7ea6
--- /dev/null
+++ b/app/components/pub/my-ui/badge/status-badge.vue
@@ -0,0 +1,26 @@
+
+
+
+
+
+ {{ statusText }}
+
+
+
diff --git a/app/components/pub/my-ui/combobox/index.ts b/app/components/pub/my-ui/combobox/index.ts
index 82a3b3cd..e4864f7f 100644
--- a/app/components/pub/my-ui/combobox/index.ts
+++ b/app/components/pub/my-ui/combobox/index.ts
@@ -20,4 +20,17 @@ export function recStrToItem(input: Record): Item[] {
return items
}
+export function objectsToItems(input: object[], key = 'id', label = 'name'): Item[] {
+ const items: Item[] = []
+ for (const item of input) {
+ if (item.hasOwnProperty(key) && item.hasOwnProperty(label)) {
+ items.push({
+ value: item[key as keyof typeof item], // the hasOwnProperty check should be enough
+ label: item[label as keyof typeof item], // the hasOwnProperty check should be enough
+ })
+ }
+ }
+ return items
+}
+
export { default as Combobox } from './combobox.vue'
diff --git a/app/components/pub/my-ui/comp-tab/type.ts b/app/components/pub/my-ui/comp-tab/type.ts
index e6faacce..ba21d0b7 100644
--- a/app/components/pub/my-ui/comp-tab/type.ts
+++ b/app/components/pub/my-ui/comp-tab/type.ts
@@ -2,5 +2,6 @@ export interface TabItem {
value: string
label: string
component?: any
+ groups?: string[]
props?: Record
}
diff --git a/app/components/pub/my-ui/confirmation/confirmation.vue b/app/components/pub/my-ui/confirmation/confirmation.vue
index 590f328d..b5c328aa 100644
--- a/app/components/pub/my-ui/confirmation/confirmation.vue
+++ b/app/components/pub/my-ui/confirmation/confirmation.vue
@@ -71,7 +71,7 @@ function handleCancel() {
-
+
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 f3e2ef43..431df276 100644
--- a/app/components/pub/my-ui/data-table/data-table.vue
+++ b/app/components/pub/my-ui/data-table/data-table.vue
@@ -22,7 +22,7 @@ const selected = ref([])
function toggleSelection(row: any, event?: Event) {
if (event) event.stopPropagation() // cegah event bubble ke TableRow
- const isMultiple = props.selectMode === 'multi' || props.selectMode === 'multiple'
+ const isMultiple = props.selectMode === 'multiple' // props.selectMode === 'multi' ||
// gunakan pembanding berdasarkan id atau stringify data
const findIndex = selected.value.findIndex((r) => JSON.stringify(r) === JSON.stringify(row))
@@ -128,7 +128,7 @@ function handleActionCellClick(event: Event, _cellRef: string) {
'bg-green-50':
props.selectMode === 'single' && selected.some((r) => JSON.stringify(r) === JSON.stringify(row)),
'bg-blue-50':
- (props.selectMode === 'multi' || props.selectMode === 'multiple') &&
+ (props.selectMode === 'multiple') && // props.selectMode === 'multi' ||
selected.some((r) => JSON.stringify(r) === JSON.stringify(row)),
}"
@click="toggleSelection(row)"
diff --git a/app/components/pub/my-ui/data/types.ts b/app/components/pub/my-ui/data/types.ts
index c0d283de..f27a5578 100644
--- a/app/components/pub/my-ui/data/types.ts
+++ b/app/components/pub/my-ui/data/types.ts
@@ -8,6 +8,7 @@ export interface ListItemDto {
}
export type ComponentType = Component
+export type ComponentWithProps = { component: Component, props: Record }
export interface ButtonNav {
variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link'
@@ -41,17 +42,23 @@ export interface RefSearchNav {
onClear: () => void
}
+export interface RefExportNav {
+ onExportPdf?: () => void
+ onExportCsv?: () => void
+ onExportExcel?: () => void
+}
+
// prepared header for relatively common usage
export interface HeaderPrep {
title?: string
icon?: string
+ components?: ComponentWithProps[]
refSearchNav?: RefSearchNav
quickSearchNav?: QuickSearchNav
filterNav?: ButtonNav
addNav?: ButtonNav
printNav?: ButtonNav
}
-
export interface KeyLabel {
key: string
label: string
diff --git a/app/components/pub/my-ui/form/input-base.vue b/app/components/pub/my-ui/form/input-base.vue
index aeb4a4af..a3743734 100644
--- a/app/components/pub/my-ui/form/input-base.vue
+++ b/app/components/pub/my-ui/form/input-base.vue
@@ -19,6 +19,8 @@ const props = defineProps<{
maxLength?: number
isRequired?: boolean
isDisabled?: boolean
+ rightLabel?: string
+ bottomLabel?: string
}>()
function handleInput(event: Event) {
@@ -61,7 +63,7 @@ function handleInput(event: Event) {
v-slot="{ componentField }"
:name="fieldName"
>
-
+
+ {{ rightLabel }}
+ {{ bottomLabel }}
diff --git a/app/components/pub/my-ui/nav-footer/ba-dr-su.vue b/app/components/pub/my-ui/nav-footer/ba-dr-su.vue
index 4598817b..8c292758 100644
--- a/app/components/pub/my-ui/nav-footer/ba-dr-su.vue
+++ b/app/components/pub/my-ui/nav-footer/ba-dr-su.vue
@@ -1,10 +1,12 @@
+
+
+
+
diff --git a/app/components/pub/my-ui/nav-header/filter.vue b/app/components/pub/my-ui/nav-header/filter.vue
index ab28620b..74f6d8dc 100644
--- a/app/components/pub/my-ui/nav-header/filter.vue
+++ b/app/components/pub/my-ui/nav-header/filter.vue
@@ -5,11 +5,13 @@ import type { Ref } from 'vue'
import type { DateRange } from 'radix-vue'
import { CalendarDate, DateFormatter, getLocalTimeZone } from '@internationalized/date'
import { cn } from '~/lib/utils'
-import type { HeaderPrep, RefSearchNav } from '~/components/pub/my-ui/data/types'
+import type { HeaderPrep, RefExportNav, RefSearchNav } from '~/components/pub/my-ui/data/types'
const props = defineProps<{
prep: HeaderPrep
refSearchNav?: RefSearchNav
+ enableExport?: boolean
+ refExportNav?: RefExportNav
}>()
// function emitSearchNavClick() {
@@ -57,7 +59,7 @@ function onFilterClick() {
-
+
@@ -97,6 +99,30 @@ function onFilterClick() {
Filter
+
+
+
+
+
+ Ekspor
+
+
+
+
+ Ekspor PDF
+
+
+ Ekspor CSV
+
+
+ Ekspor Excel
+
+
+
+
diff --git a/app/components/pub/my-ui/nav-header/prep.vue b/app/components/pub/my-ui/nav-header/prep.vue
index 63535847..7aa5e4f2 100644
--- a/app/components/pub/my-ui/nav-header/prep.vue
+++ b/app/components/pub/my-ui/nav-header/prep.vue
@@ -30,15 +30,24 @@ function btnClick() {
- {{ props.prep.title }}
+ {{ prep.title }}
+
+
+
+
+
+import { ref, inject } from "vue"
+// import Toggle from '~/components/pub/ui/toggle/Toggle.vue'
+
+const props = defineProps<{
+ label: string,
+ providedKey?: string,
+ variant?: 'default' | 'outline' | null | undefined
+}>()
+
+const model = defineModel
()
+const provideKey = props.providedKey || 'toggle-provide'
+const { updateProvidedVal } = inject(provideKey)
+
+watch(model, (newVal) => {
+ updateProvidedVal(newVal)
+})
+
+
+
+ model = !model"
+ :variant="model ? 'default' : 'outline'"
+ >
+ {{ label }}
+
+
+
+
diff --git a/app/components/pub/ui/button/index.ts b/app/components/pub/ui/button/index.ts
index c4063089..43c75876 100644
--- a/app/components/pub/ui/button/index.ts
+++ b/app/components/pub/ui/button/index.ts
@@ -19,7 +19,7 @@ export const buttonVariants = cva(
link: 'text-primary underline-offset-4 hover:underline',
},
size: {
- default: 'md:h8 2xl:h-9 px-4 py-2',
+ default: 'md:h-8 2xl:h-9 px-4 py-2',
xs: 'h-7 rounded px-2',
sm: 'h-8 rounded-md px-3 text-xs',
lg: 'h-10 rounded-md px-8',
diff --git a/app/components/pub/ui/toggle/index.ts b/app/components/pub/ui/toggle/index.ts
index 07acae50..9486e903 100644
--- a/app/components/pub/ui/toggle/index.ts
+++ b/app/components/pub/ui/toggle/index.ts
@@ -4,16 +4,16 @@ import { cva } from 'class-variance-authority'
export { default as Toggle } from './Toggle.vue'
export const toggleVariants = cva(
- 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground',
+ 'inline-flex items-center justify-center rounded-md text-xs 2xl:text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground',
{
variants: {
variant: {
default: 'bg-transparent',
outline:
- 'border border-input bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground',
+ 'border border-slate-300 bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground',
},
size: {
- default: 'h-9 px-3',
+ default: 'md:h-8 2xl:h-9 px-3',
sm: 'h-8 px-2',
lg: 'h-10 px-3',
},
diff --git a/app/handlers/control-letter.handler.ts b/app/handlers/control-letter.handler.ts
new file mode 100644
index 00000000..b096a178
--- /dev/null
+++ b/app/handlers/control-letter.handler.ts
@@ -0,0 +1,24 @@
+// Handlers
+import { genCrudHandler } from '~/handlers/_handler'
+
+// Services
+import { create, update, remove } from '~/services/control-letter.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({
+ create,
+ update,
+ remove,
+})
diff --git a/app/handlers/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/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/lib/date.ts b/app/lib/date.ts
index 502a6cfb..2c7b92cf 100644
--- a/app/lib/date.ts
+++ b/app/lib/date.ts
@@ -41,4 +41,12 @@ export function getAge(dateString: string, comparedDate?: string): { idFormat: s
idFormat,
extFormat
};
+}
+
+export function formatDateYyyyMmDd(isoDateString: string): string {
+ const date = new Date(isoDateString);
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, '0');
+ const day = String(date.getDate()).padStart(2, '0');
+ return `${year}-${month}-${day}`;
}
\ No newline at end of file
diff --git a/app/lib/page-permission.ts b/app/lib/page-permission.ts
index 1b70af31..ab7b5550 100644
--- a/app/lib/page-permission.ts
+++ b/app/lib/page-permission.ts
@@ -2,67 +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': {
- doctor: ['C', 'R', 'U', 'D'],
- nurse: ['C', 'R', 'U', 'D'],
- admisi: ['R'],
- pharmacy: ['R'],
- billing: ['R'],
- management: ['R'],
+ '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': {
- doctor: ['C', 'R', 'U', 'D'],
- nurse: ['C', 'R', 'U', 'D'],
- admisi: ['R'],
- pharmacy: ['R'],
- billing: ['R'],
- management: ['R'],
+ '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': {
- doctor: ['C', 'R', 'U', 'D'],
- nurse: ['C', 'R', 'U', 'D'],
- admisi: ['R'],
- pharmacy: ['R'],
- billing: ['R'],
- management: ['R'],
+ 'emp|doc': ['C', 'R', 'U', 'D'],
+ 'emp|nur': ['C', 'R', 'U', 'D'],
+ 'emp|reg': ['R'],
+ 'emp|pha': ['R'],
+ 'emp|pay': ['R'],
+ 'emp|mng': ['R'],
},
'/rehab/encounter': {
- doctor: ['C', 'R', 'U', 'D'],
- nurse: ['R'],
- admisi: ['R'],
- pharmacy: ['R'],
- billing: ['R'],
- management: ['R'],
+ 'emp|doc': ['C', 'R', 'U', 'D'],
+ 'emp|nur': ['R'],
+ 'emp|reg': ['R'],
+ 'emp|pha': ['R'],
+ 'emp|pay': ['R'],
+ 'emp|mng': ['R'],
},
'/rehab/registration': {
- doctor: ['C', 'R', 'U', 'D'],
- nurse: ['R'],
- admisi: ['R'],
- pharmacy: ['R'],
- billing: ['R'],
- management: ['R'],
+ 'emp|doc': ['C', 'R', 'U', 'D'],
+ 'emp|nur': ['R'],
+ 'emp|reg': ['R'],
+ 'emp|pha': ['R'],
+ 'emp|pay': ['R'],
+ 'emp|mng': ['R'],
},
} as const satisfies Record
diff --git a/app/models/consultation.ts b/app/models/consultation.ts
index 09d050a8..595d628e 100644
--- a/app/models/consultation.ts
+++ b/app/models/consultation.ts
@@ -28,9 +28,10 @@ export interface DeleteDto {
export function genCreateDto(): CreateDto {
return {
+ date: '',
encounter_id: 0,
problem: '',
- unit_id: 0,
+ dstUnit_id: 0,
}
}
diff --git a/app/models/control-letter.ts b/app/models/control-letter.ts
new file mode 100644
index 00000000..8f520212
--- /dev/null
+++ b/app/models/control-letter.ts
@@ -0,0 +1,37 @@
+import { type Base, genBase } from "./_base"
+import { genDoctor, type Doctor } from "./doctor"
+import { genEncounter, type Encounter } from "./encounter"
+import { genSpecialist, type Specialist } from "./specialist"
+import { genSubspecialist, type Subspecialist } from "./subspecialist"
+import { genUnit, type Unit } from "./unit"
+
+export interface ControlLetter extends Base {
+ encounter_id: number
+ encounter: Encounter
+ unit_id: number
+ unit: Unit
+ specialist_id: number
+ specialist: Specialist
+ subspecialist_id: number
+ subspecialist: Subspecialist
+ doctor_id: number
+ doctor: Doctor
+ date: ''
+}
+
+export function genControlLetter(): ControlLetter {
+ return {
+ ...genBase(),
+ encounter_id: 0,
+ encounter: genEncounter(),
+ unit_id: 0,
+ unit: genUnit(),
+ specialist_id: 0,
+ specialist: genSpecialist(),
+ subspecialist_id: 0,
+ subspecialist: genSubspecialist(),
+ doctor_id: 0,
+ doctor: genDoctor(),
+ date: ''
+ }
+}
diff --git a/app/models/doctor.ts b/app/models/doctor.ts
index 3f517476..1b631907 100644
--- a/app/models/doctor.ts
+++ b/app/models/doctor.ts
@@ -8,10 +8,11 @@ export interface Doctor extends Base {
employee: Employee
ihs_number: string
sip_number: string
- unit_id?: number
- specialist_id?: number
+ code?: string
+ unit_icode?: number
+ specialist_icode?: number
specialist?: Specialist
- subspecialist_id?: number
+ subspecialist_icode?: number
subspecialist?: Subspecialist
bpjs_code?: string
}
@@ -21,9 +22,9 @@ export interface CreateDto {
employee_id: number
ihs_number: string
sip_number: string
- unit_id?: number
- specialist_id?: number
- subspecialist_id?: number
+ unit_code?: number
+ specialist_code?: number
+ subspecialist_code?: number
bpjs_code: string
}
diff --git a/app/models/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/pages/(features)/integration/bpjs/control-letter/index.vue b/app/pages/(features)/integration/bpjs/control-letter/index.vue
new file mode 100644
index 00000000..8dcb9006
--- /dev/null
+++ b/app/pages/(features)/integration/bpjs/control-letter/index.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
diff --git a/app/pages/(features)/integration/bpjs/sep/add.vue b/app/pages/(features)/integration/bpjs/sep/add.vue
index 5db12aac..0658780b 100644
--- a/app/pages/(features)/integration/bpjs/sep/add.vue
+++ b/app/pages/(features)/integration/bpjs/sep/add.vue
@@ -22,12 +22,12 @@ const { checkRole, hasCreateAccess } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
-if (!hasAccess) {
- throw createError({
- statusCode: 403,
- statusMessage: 'Access denied',
- })
-}
+// if (!hasAccess) {
+// throw createError({
+// statusCode: 403,
+// statusMessage: 'Access denied',
+// })
+// }
// Define permission-based computed properties
const canCreate = true // hasCreateAccess(roleAccess)
diff --git a/app/pages/(features)/integration/bpjs/sep/index.vue b/app/pages/(features)/integration/bpjs/sep/index.vue
index b8ec57c4..d99dbb5d 100644
--- a/app/pages/(features)/integration/bpjs/sep/index.vue
+++ b/app/pages/(features)/integration/bpjs/sep/index.vue
@@ -22,9 +22,9 @@ const { checkRole, hasReadAccess } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
-if (!hasAccess) {
- navigateTo('/403')
-}
+// if (!hasAccess) {
+// navigateTo('/403')
+// }
// Define permission-based computed properties
const canRead = true // hasReadAccess(roleAccess)
diff --git a/app/pages/(features)/outpatient/encounter/[id]/index.vue b/app/pages/(features)/outpatient/encounter/[id]/index.vue
new file mode 100644
index 00000000..1864cf2c
--- /dev/null
+++ b/app/pages/(features)/outpatient/encounter/[id]/index.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
diff --git a/app/pages/(features)/outpation-action/cemotherapy/index.vue b/app/pages/(features)/outpation-action/cemotherapy/index.vue
deleted file mode 100644
index 50485cec..00000000
--- a/app/pages/(features)/outpation-action/cemotherapy/index.vue
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
Hello world!!
-
You are accessing "{{ route.fullPath }}"
-
-
diff --git a/app/pages/(features)/outpation-action/chemotherapy/[mode]/[id]/verification.vue b/app/pages/(features)/outpation-action/chemotherapy/[mode]/[id]/verification.vue
new file mode 100644
index 00000000..ef936ff2
--- /dev/null
+++ b/app/pages/(features)/outpation-action/chemotherapy/[mode]/[id]/verification.vue
@@ -0,0 +1,47 @@
+
+
+
+
+
diff --git a/app/pages/(features)/outpation-action/chemotherapy/[mode]/index.vue b/app/pages/(features)/outpation-action/chemotherapy/[mode]/index.vue
new file mode 100644
index 00000000..cf33691a
--- /dev/null
+++ b/app/pages/(features)/outpation-action/chemotherapy/[mode]/index.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
+
diff --git a/app/pages/(features)/outpation-action/chemotherapy/index.vue b/app/pages/(features)/outpation-action/chemotherapy/index.vue
new file mode 100644
index 00000000..a2dfdea5
--- /dev/null
+++ b/app/pages/(features)/outpation-action/chemotherapy/index.vue
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/app/pages/(features)/outpation-action/chemotherapy/list.vue b/app/pages/(features)/outpation-action/chemotherapy/list.vue
new file mode 100644
index 00000000..a141baaa
--- /dev/null
+++ b/app/pages/(features)/outpation-action/chemotherapy/list.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
diff --git a/app/pages/(features)/rehab/examination-queue/index.vue b/app/pages/(features)/rehab/encounter-queue/index.vue
similarity index 100%
rename from app/pages/(features)/rehab/examination-queue/index.vue
rename to app/pages/(features)/rehab/encounter-queue/index.vue
diff --git a/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/edit.vue b/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/edit.vue
new file mode 100644
index 00000000..cc5d182f
--- /dev/null
+++ b/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/edit.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
diff --git a/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/index.vue b/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/index.vue
new file mode 100644
index 00000000..612315ad
--- /dev/null
+++ b/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/index.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
diff --git a/app/pages/(features)/rehab/encounter/[id]/control-letter/add.vue b/app/pages/(features)/rehab/encounter/[id]/control-letter/add.vue
new file mode 100644
index 00000000..1070a29f
--- /dev/null
+++ b/app/pages/(features)/rehab/encounter/[id]/control-letter/add.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
diff --git a/app/pages/(features)/rehab/encounter/[id]/process.vue b/app/pages/(features)/rehab/encounter/[id]/process.vue
index 3fa7525a..abd0efa7 100644
--- a/app/pages/(features)/rehab/encounter/[id]/process.vue
+++ b/app/pages/(features)/rehab/encounter/[id]/process.vue
@@ -22,15 +22,15 @@ const { checkRole, hasCreateAccess } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
-if (!hasAccess) {
- throw createError({
- statusCode: 403,
- statusMessage: 'Access denied',
- })
-}
+// if (!hasAccess) {
+// throw createError({
+// statusCode: 403,
+// statusMessage: 'Access denied',
+// })
+// }
// Define permission-based computed properties
-const canCreate = hasCreateAccess(roleAccess)
+const canCreate = true // hasCreateAccess(roleAccess)
diff --git a/app/pages/(features)/rehab/encounter/index.vue b/app/pages/(features)/rehab/encounter/index.vue
index 6bbec942..f50ad954 100644
--- a/app/pages/(features)/rehab/encounter/index.vue
+++ b/app/pages/(features)/rehab/encounter/index.vue
@@ -5,7 +5,7 @@ import { PAGE_PERMISSIONS } from '~/lib/page-permission'
definePageMeta({
middleware: ['rbac'],
- roles: ['system', 'doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
+ roles: ['system', 'emp-doc', 'emp-nur', 'emp-reg', 'emp-pha', 'emp-pay', 'emp-mng'],
title: 'Daftar Kunjungan',
contentFrame: 'cf-full-width',
})
@@ -23,11 +23,11 @@ const { checkRole, hasReadAccess } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
if (!hasAccess) {
- navigateTo('/403')
+ // navigateTo('/403')
}
// Define permission-based computed properties
-const canRead = hasReadAccess(roleAccess)
+const canRead = true // hasReadAccess(roleAccess)
diff --git a/app/pages/(features)/rehab/examination/index.vue b/app/pages/(features)/rehab/examination/index.vue
deleted file mode 100644
index 806b2650..00000000
--- a/app/pages/(features)/rehab/examination/index.vue
+++ /dev/null
@@ -1,3 +0,0 @@
-
- Examination
-
diff --git a/app/schemas/chemotherapy.schema.ts b/app/schemas/chemotherapy.schema.ts
new file mode 100644
index 00000000..212e5358
--- /dev/null
+++ b/app/schemas/chemotherapy.schema.ts
@@ -0,0 +1,73 @@
+import { z } from 'zod'
+
+const dateStringSchema = z.string().min(1)
+
+export const chemotherapySchema = z.object({
+ // Data Pasien
+ namaPasien: z.string({
+ required_error: 'Nama pasien harus diisi',
+ }).min(1, 'Nama pasien harus diisi'),
+
+ tanggalLahir: z.string({
+ required_error: 'Tanggal lahir harus diisi',
+ }).min(1, 'Tanggal lahir harus diisi'),
+
+ noRM: z.string({
+ required_error: 'Nomor RM harus diisi',
+ }).min(1, 'Nomor RM harus diisi'),
+
+ alamat: z.string({
+ required_error: 'Alamat harus diisi',
+ }).min(1, 'Alamat harus diisi'),
+
+ beratBadan: z.union([
+ z.string(),
+ z.number()
+ ]).transform(val => val === '' ? null : Number(val))
+ .refine(val => val === null || (val >= 0 && val <= 500), {
+ message: 'Berat badan harus di antara 0-500 kg',
+ }),
+
+ tinggiBadan: z.union([
+ z.string(),
+ z.number()
+ ]).transform(val => val === '' ? null : Number(val))
+ .refine(val => val === null || (val >= 0 && val <= 300), {
+ message: 'Tinggi badan harus di antara 0-300 cm',
+ }),
+
+ diagnosa: z.string({
+ required_error: 'Diagnosa harus dipilih',
+ }).min(1, 'Diagnosa harus dipilih'),
+
+ // Protokol Kemoterapi
+ siklus: z.string({
+ required_error: 'Siklus harus diisi',
+ }).min(1, 'Siklus harus diisi'),
+
+ periodeAwal: z.string({
+ required_error: 'Periode awal harus diisi',
+ }).min(1, 'Periode awal harus diisi'),
+
+ periodeAkhir: dateStringSchema.refine((val) => {
+ if (!val) return false
+ const date = new Date(val)
+ return !isNaN(date.getTime())
+ }, {
+ message: 'Format tanggal tidak valid'
+ }),
+
+ tanggalKemoterapi: dateStringSchema.refine((val) => {
+ if (!val) return false
+ const date = new Date(val)
+ return !isNaN(date.getTime())
+ }, {
+ message: 'Format tanggal tidak valid'
+ }),
+
+ dokterKRJ: z.string({
+ required_error: 'Dokter harus dipilih',
+ }).refine(val => val !== '', {
+ message: 'Dokter harus dipilih',
+ }),
+})
\ No newline at end of file
diff --git a/app/schemas/control-letter.schema.ts b/app/schemas/control-letter.schema.ts
new file mode 100644
index 00000000..c82ffaac
--- /dev/null
+++ b/app/schemas/control-letter.schema.ts
@@ -0,0 +1,47 @@
+import { z } from 'zod'
+
+const ControlLetterSchema = z.object({
+ sepStatus: z.string({
+ required_error: 'Mohon isi status SEP',
+ }).default('SEP Internal'),
+ unit_code: z.string({
+ required_error: 'Mohon isi Unit',
+ }),
+ specialist_code: z.string({
+ required_error: 'Mohon isi Spesialis',
+ }),
+ subspecialist_code: z.string({
+ required_error: 'Mohon isi Sub Spesialis',
+ }),
+ doctor_code: z.string({
+ required_error: 'Mohon isi DPJP',
+ }),
+ encounter_code: z.string().optional(),
+ date: z.string({
+ required_error: 'Mohon lengkapi Tanggal Kontrol',
+ })
+ .refine(
+ (date) => {
+ // Jika kosong, return false untuk required validation
+ if (!date || date.trim() === '') return false
+
+ // Jika ada isi, validasi format tanggal
+ try {
+ const dateObj = new Date(date)
+ // Cek apakah tanggal valid dan tahun >= 1900
+ return !isNaN(dateObj.getTime()) && dateObj.getFullYear() >= 1900
+ } catch {
+ return false
+ }
+ },
+ {
+ message: 'Mohon lengkapi Tanggal Kontrol dengan format yang valid',
+ },
+ )
+ .transform((dateStr) => new Date(dateStr).toISOString()),
+})
+
+type ControlLetterFormData = z.infer
+
+export { ControlLetterSchema }
+export type { ControlLetterFormData }
diff --git a/app/schemas/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/services/control-letter.service.ts b/app/services/control-letter.service.ts
new file mode 100644
index 00000000..29b3722b
--- /dev/null
+++ b/app/services/control-letter.service.ts
@@ -0,0 +1,28 @@
+// Base
+import * as base from './_crud-base'
+
+// Constants
+import { encounterClassCodes } from '~/lib/constants'
+
+const path = '/api/v1/control-letter'
+const name = 'control-letter'
+
+export function create(data: any) {
+ return base.create(path, data, name)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export function getDetail(id: number | string, params?: any) {
+ return base.getDetail(path, id, name, params)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data, name)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id, name)
+}
\ No newline at end of file
diff --git a/app/services/doctor.service.ts b/app/services/doctor.service.ts
index 74104c2c..e6ae0051 100644
--- a/app/services/doctor.service.ts
+++ b/app/services/doctor.service.ts
@@ -1,8 +1,6 @@
// Base
import * as base from './_crud-base'
-
-// Types
-import type { Doctor } from '~/models/doctor'
+import type { Doctor } from "~/models/doctor";
const path = '/api/v1/doctor'
const name = 'doctor'
@@ -27,13 +25,15 @@ export function remove(id: number | string) {
return base.remove(path, id, name)
}
-export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+export async function getValueLabelList(params: any = null, useCodeAsValue = false): Promise<{ value: string; label: string }[]> {
let data: { value: string; label: string }[] = []
const result = await getList(params)
if (result.success) {
const resultData = result.body?.data || []
data = resultData.map((item: Doctor) => ({
- value: item.id ? String(item.id) : '',
+ value: useCodeAsValue ? item.code
+ : item.id ? Number(item.id)
+ : item.id,
label: item.employee?.person?.name || '',
}))
}
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/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.service.ts b/app/services/specialist.service.ts
index 8221cd67..7786fcc2 100644
--- a/app/services/specialist.service.ts
+++ b/app/services/specialist.service.ts
@@ -34,7 +34,7 @@ export async function getValueLabelList(params: any = null, useCodeAsValue = fal
if (result.success) {
const resultData = result.body?.data || []
data = resultData.map((item: Specialist) => ({
- value: useCodeAsValue ? item.code
+ value: useCodeAsValue ? item.code
: item.id ? Number(item.id)
: item.code,
label: item.name,
diff --git a/app/services/unit.service.ts b/app/services/unit.service.ts
index 40968a69..948ac6b6 100644
--- a/app/services/unit.service.ts
+++ b/app/services/unit.service.ts
@@ -33,7 +33,7 @@ export async function getValueLabelList(params: any = null, useCodeAsValue = fal
if (result.success) {
const resultData = result.body?.data || []
data = resultData.map((item: Unit) => ({
- value: useCodeAsValue ? item.code
+ value: useCodeAsValue ? item.code
: item.id ? Number(item.id)
: item.code,
label: item.name,
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/public/side-menu-items/blank.json b/public/side-menu-items/blank.json
new file mode 100644
index 00000000..9d7a78b3
--- /dev/null
+++ b/public/side-menu-items/blank.json
@@ -0,0 +1,12 @@
+[
+ {
+ "heading": "Menu Utama",
+ "items": [
+ {
+ "title": "Dashboard",
+ "icon": "i-lucide-home",
+ "link": "/"
+ }
+ ]
+ }
+]
diff --git a/public/side-menu-items/div-crd.json b/public/side-menu-items/div-crd.json
new file mode 100644
index 00000000..9d7a78b3
--- /dev/null
+++ b/public/side-menu-items/div-crd.json
@@ -0,0 +1,12 @@
+[
+ {
+ "heading": "Menu Utama",
+ "items": [
+ {
+ "title": "Dashboard",
+ "icon": "i-lucide-home",
+ "link": "/"
+ }
+ ]
+ }
+]
diff --git a/public/side-menu-items/doc.json b/public/side-menu-items/emp-doc.json
similarity index 96%
rename from public/side-menu-items/doc.json
rename to public/side-menu-items/emp-doc.json
index e3ab2cdf..b7ecb430 100644
--- a/public/side-menu-items/doc.json
+++ b/public/side-menu-items/emp-doc.json
@@ -84,12 +84,12 @@
{
"title": "Kemoterapi",
"icon": "i-lucide-droplets",
- "link": "/outpatient-action/cemotherapy"
+ "link": "/outpation-action/chemotherapy"
},
{
"title": "Hemofilia",
"icon": "i-lucide-droplet-off",
- "link": "/outpatient-action/hemophilia/encounter"
+ "link": "/outpation-action/hemophilia"
}
]
},
diff --git a/public/side-menu-items/lab.json b/public/side-menu-items/emp-lab.json
similarity index 100%
rename from public/side-menu-items/lab.json
rename to public/side-menu-items/emp-lab.json
diff --git a/public/side-menu-items/miw.json b/public/side-menu-items/emp-mid.json
similarity index 93%
rename from public/side-menu-items/miw.json
rename to public/side-menu-items/emp-mid.json
index ebb43da6..80eeee7c 100644
--- a/public/side-menu-items/miw.json
+++ b/public/side-menu-items/emp-mid.json
@@ -20,7 +20,7 @@
{
"title": "Rehabilitasi Medik",
"icon": "i-lucide-bike",
- "link": "/rehab/polyclinic-queue"
+ "link": "/rehab/encounter-queue"
},
{
"title": "Rawat Inap",
diff --git a/public/side-menu-items/nur.json b/public/side-menu-items/emp-nur.json
similarity index 89%
rename from public/side-menu-items/nur.json
rename to public/side-menu-items/emp-nur.json
index 8185456c..1c993144 100644
--- a/public/side-menu-items/nur.json
+++ b/public/side-menu-items/emp-nur.json
@@ -13,10 +13,10 @@
"children": [
{
"title": "Antrian Poliklinik",
- "link": "/outpatient/polyclinic-queue"
+ "link": "/outpatient/encounter-queue"
},
{
- "title": "Pendaftaran",
+ "title": "Kunjungan",
"link": "/outpatient/encounter"
}
]
@@ -30,7 +30,7 @@
"link": "/emergency/triage"
},
{
- "title": "Pemeriksaan",
+ "title": "Kunjungan",
"link": "/emergency/encounter"
}
]
@@ -42,7 +42,7 @@
"children": [
{
"title": "Antrean Poliklinik",
- "link": "/rehab/polyclinic-queue"
+ "link": "/rehab/encounter-queue"
},
{
"title": "Kunjungan",
@@ -63,7 +63,7 @@
{
"title": "Kemoterapi",
"icon": "i-lucide-droplets",
- "link": "/outpation-action/cemotherapy"
+ "link": "/outpation-action/chemotherapy"
},
{
"title": "Hemofilia",
diff --git a/public/side-menu-items/nut.json b/public/side-menu-items/emp-nut.json
similarity index 93%
rename from public/side-menu-items/nut.json
rename to public/side-menu-items/emp-nut.json
index 4368b22e..ef71282a 100644
--- a/public/side-menu-items/nut.json
+++ b/public/side-menu-items/emp-nut.json
@@ -35,12 +35,12 @@
{
"title": "Kemoterapi",
"icon": "i-lucide-droplets",
- "link": "/outpatient-action/cemotherapy"
+ "link": "/outpation-action/chemotherapy"
},
{
"title": "Hemofilia",
"icon": "i-lucide-droplet-off",
- "link": "/outpatient-action/hemophilia"
+ "link": "/outpation-action/hemophilia"
}
]
},
diff --git a/public/side-menu-items/pha.json b/public/side-menu-items/emp-pha.json
similarity index 100%
rename from public/side-menu-items/pha.json
rename to public/side-menu-items/emp-pha.json
diff --git a/public/side-menu-items/reg.json b/public/side-menu-items/emp-reg.json
similarity index 100%
rename from public/side-menu-items/reg.json
rename to public/side-menu-items/emp-reg.json
diff --git a/public/side-menu-items/sys.json b/public/side-menu-items/system.json
similarity index 96%
rename from public/side-menu-items/sys.json
rename to public/side-menu-items/system.json
index b69127e7..5bf62f36 100644
--- a/public/side-menu-items/sys.json
+++ b/public/side-menu-items/system.json
@@ -17,7 +17,7 @@
},
{
"title": "Antrian Poliklinik",
- "link": "/outpatient/polyclinic-queue"
+ "link": "/outpatient/encounter-queue"
},
{
"title": "Kunjungan",
@@ -57,7 +57,7 @@
},
{
"title": "Antrean Poliklinik",
- "link": "/rehab/polyclinic-queue"
+ "link": "/rehab/encounter-queue"
},
{
"title": "Kunjungan",
@@ -139,7 +139,7 @@
{
"title": "Kemoterapi",
"icon": "i-lucide-droplets",
- "link": "/outpation-action/cemotherapy"
+ "link": "/outpation-action/chemotherapy"
},
{
"title": "Hemofilia",
@@ -199,6 +199,11 @@
"title": "Peserta",
"icon": "i-lucide-circuit-board",
"link": "/integration/bpjs/member"
+ },
+ {
+ "title": "Surat Kontrol",
+ "icon": "i-lucide-circuit-board",
+ "link": "/integration/bpjs/control-letter"
}
]
},
From 0a68dbf3a625fec9580310aca1d34ccf74ba2a31 Mon Sep 17 00:00:00 2001
From: hasyim_kai
Date: Tue, 18 Nov 2025 15:31:04 +0700
Subject: [PATCH 28/40] Fix: debug after reset
---
.../_common/select-doc-type.vue | 71 ++++
.../app/document-upload/entry-form.vue | 73 ++++
.../app/document-upload/list.cfg.ts | 43 ++
app/components/app/document-upload/list.vue | 31 ++
.../content/document-upload/add.vue | 128 ++++++
.../content/document-upload/edit.vue | 134 +++++++
.../content/document-upload/list.vue | 170 ++++++++
app/components/content/encounter/process.vue | 28 +-
.../pub/my-ui/data/dropdown-action-dd.vue | 80 ++++
.../pub/my-ui/data/dropdown-action-dud.vue | 11 +-
app/components/pub/my-ui/form/file-field.vue | 2 +-
.../pub/my-ui/modal/doc-preview-dialog.vue | 29 ++
.../pub/my-ui/nav-footer/ba-dr-su.vue | 2 +-
app/composables/useRBAC.ts | 15 +
app/handlers/supporting-document.handler.ts | 24 ++
app/lib/constants.ts | 42 ++
app/lib/utils.ts | 57 +++
app/models/encounter-document.ts | 29 ++
app/models/encounter.ts | 5 +-
.../encounter/[id]/control-letter/add.vue | 9 +-
.../document-upload/[document_id]/edit.vue} | 15 +-
.../encounter/[id]/document-upload/add.vue} | 27 +-
.../rehab/encounter/[id]/process.vue | 6 +-
app/schemas/document-upload.schema.ts | 24 ++
app/services/supporting-document.service.ts | 56 +++
public/side-menu-items/sys.json | 368 ++++++++++++++++++
26 files changed, 1427 insertions(+), 52 deletions(-)
create mode 100644 app/components/app/document-upload/_common/select-doc-type.vue
create mode 100644 app/components/app/document-upload/entry-form.vue
create mode 100644 app/components/app/document-upload/list.cfg.ts
create mode 100644 app/components/app/document-upload/list.vue
create mode 100644 app/components/content/document-upload/add.vue
create mode 100644 app/components/content/document-upload/edit.vue
create mode 100644 app/components/content/document-upload/list.vue
create mode 100644 app/components/pub/my-ui/data/dropdown-action-dd.vue
create mode 100644 app/components/pub/my-ui/modal/doc-preview-dialog.vue
create mode 100644 app/handlers/supporting-document.handler.ts
create mode 100644 app/models/encounter-document.ts
rename app/pages/(features)/{outpation-action/chemotherapy/list.vue => rehab/encounter/[id]/document-upload/[document_id]/edit.vue} (74%)
rename app/pages/(features)/{outpation-action/chemotherapy/[mode]/[id]/verification.vue => rehab/encounter/[id]/document-upload/add.vue} (53%)
create mode 100644 app/schemas/document-upload.schema.ts
create mode 100644 app/services/supporting-document.service.ts
create mode 100644 public/side-menu-items/sys.json
diff --git a/app/components/app/document-upload/_common/select-doc-type.vue b/app/components/app/document-upload/_common/select-doc-type.vue
new file mode 100644
index 00000000..70f78a7b
--- /dev/null
+++ b/app/components/app/document-upload/_common/select-doc-type.vue
@@ -0,0 +1,71 @@
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/app/document-upload/entry-form.vue b/app/components/app/document-upload/entry-form.vue
new file mode 100644
index 00000000..f97a5161
--- /dev/null
+++ b/app/components/app/document-upload/entry-form.vue
@@ -0,0 +1,73 @@
+
+
+
+
+
diff --git a/app/components/app/document-upload/list.cfg.ts b/app/components/app/document-upload/list.cfg.ts
new file mode 100644
index 00000000..979c916d
--- /dev/null
+++ b/app/components/app/document-upload/list.cfg.ts
@@ -0,0 +1,43 @@
+import type { Config } from '~/components/pub/my-ui/data-table'
+import { defineAsyncComponent } from 'vue'
+import { docTypeCode, docTypeLabel, type docTypeCodeKey } from '~/lib/constants'
+
+const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-dd.vue'))
+
+export const config: Config = {
+ cols: [{}, {}, {}, {width: 50},],
+
+ headers: [
+ [
+ { label: 'Nama Dokumen' },
+ { label: 'Tipe Dokumen' },
+ { label: 'Petugas Upload' },
+ { label: 'Action' },
+ ],
+ ],
+
+ keys: ['fileName', 'type_code', 'employee.name', 'action'],
+
+ delKeyNames: [
+
+ ],
+
+ parses: {
+ type_code: (v: unknown) => {
+ return docTypeLabel[v?.type_code as docTypeCodeKey]
+ },
+ },
+
+ components: {
+ action(rec, idx) {
+ return {
+ idx,
+ rec: rec as object,
+ component: action,
+ }
+ },
+ },
+
+ htmls: {
+ },
+}
diff --git a/app/components/app/document-upload/list.vue b/app/components/app/document-upload/list.vue
new file mode 100644
index 00000000..8274e752
--- /dev/null
+++ b/app/components/app/document-upload/list.vue
@@ -0,0 +1,31 @@
+
+
+
+
+
diff --git a/app/components/content/document-upload/add.vue b/app/components/content/document-upload/add.vue
new file mode 100644
index 00000000..7d42f4f6
--- /dev/null
+++ b/app/components/content/document-upload/add.vue
@@ -0,0 +1,128 @@
+
+
+
+
+
Upload Dokumen
+
+
+
+
+
+
+
+
+
diff --git a/app/components/content/document-upload/edit.vue b/app/components/content/document-upload/edit.vue
new file mode 100644
index 00000000..c4033fb2
--- /dev/null
+++ b/app/components/content/document-upload/edit.vue
@@ -0,0 +1,134 @@
+
+
+
+
+
Upload Dokumen
+
+
+
+
+
+
+
+
+
diff --git a/app/components/content/document-upload/list.vue b/app/components/content/document-upload/list.vue
new file mode 100644
index 00000000..4fc55bc4
--- /dev/null
+++ b/app/components/content/document-upload/list.vue
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+ ID:
+ {{ record?.id }}
+
+
+ Nama:
+ {{ record?.name }}
+
+
+
+
+
+
+
+
+
diff --git a/app/components/content/encounter/process.vue b/app/components/content/encounter/process.vue
index 23640af7..ecf44507 100644
--- a/app/components/content/encounter/process.vue
+++ b/app/components/content/encounter/process.vue
@@ -19,6 +19,8 @@ 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'
import ControlLetterList from '~/components/content/control-letter/list.vue'
+import DocUploadList from '~/components/content/document-upload/list.vue'
+import { genEncounter } from '~/models/encounter'
const route = useRoute()
const router = useRouter()
@@ -32,12 +34,18 @@ const activeTab = computed({
})
const id = typeof route.params.id == 'string' ? parseInt(route.params.id) : 0
-const dataRes = await getDetail(id, {
- includes:
- 'patient,patient-person,patient-person-addresses,unit,Appointment_Doctor,Appointment_Doctor-employee,Appointment_Doctor-employee-person',
+const data = ref(genEncounter())
+
+async function fetchDetail() {
+ const res = await getDetail(id, {
+ includes: 'patient,patient-person,patient-person-addresses,unit,Appointment_Doctor,Appointment_Doctor-employee,Appointment_Doctor-employee-person,EncounterDocuments',
+ })
+ if(res.body?.data) data.value = res.body?.data
+}
+
+onMounted(() => {
+ fetchDetail()
})
-const dataResBody = dataRes.body ?? null
-const data = dataResBody?.data ?? null
const tabs: TabItem[] = [
{ value: 'status', label: 'Status Masuk/Keluar', component: Status, props: { encounter: data } },
@@ -63,10 +71,10 @@ const tabs: TabItem[] = [
{ value: 'education-assessment', label: 'Asesmen Kebutuhan Edukasi' },
{ value: 'consent', label: 'General Consent' },
{ value: 'patient-note', label: 'CPRJ' },
- { value: 'prescription', label: 'Order Obat', component: Prescription, props: { encounter_id: data.id } },
+ { value: 'prescription', label: 'Order Obat', component: Prescription, props: { encounter_id: data.value.id } },
{ value: 'device', label: 'Order Alkes' },
- { 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-radiology', label: 'Order Radiologi', component: Radiology, props: { encounter_id: data.value.id } },
+ { value: 'mcu-lab-cp', label: 'Order Lab PK', component: CpLabOrder, props: { encounter_id: data.value.id } },
{ value: 'mcu-lab-micro', label: 'Order Lab Mikro' },
{ value: 'mcu-lab-pa', label: 'Order Lab PA' },
{ value: 'medical-action', label: 'Order Ruang Tindakan' },
@@ -75,7 +83,7 @@ const tabs: TabItem[] = [
{ value: 'resume', label: 'Resume' },
{ value: 'control', label: 'Surat Kontrol', component: ControlLetterList, props: { encounter: data } },
{ value: 'screening', label: 'Skrinning MPP' },
- { value: 'supporting-document', label: 'Upload Dokumen Pendukung' },
+ { value: 'supporting-document', label: 'Upload Dokumen Pendukung', component: DocUploadList, props: { encounter: data, }, },
]
@@ -91,4 +99,4 @@ const tabs: TabItem[] = [
@change-tab="activeTab = $event"
/>
-
+
\ No newline at end of file
diff --git a/app/components/pub/my-ui/data/dropdown-action-dd.vue b/app/components/pub/my-ui/data/dropdown-action-dd.vue
new file mode 100644
index 00000000..a6a99c9a
--- /dev/null
+++ b/app/components/pub/my-ui/data/dropdown-action-dd.vue
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/pub/my-ui/data/dropdown-action-dud.vue b/app/components/pub/my-ui/data/dropdown-action-dud.vue
index dfcf1ada..71979c7c 100644
--- a/app/components/pub/my-ui/data/dropdown-action-dud.vue
+++ b/app/components/pub/my-ui/data/dropdown-action-dud.vue
@@ -2,14 +2,9 @@
import type { LinkItem, ListItemDto } from './types'
import { ActionEvents } from './types'
-interface Props {
+const props = defineProps<{
rec: ListItemDto
- size?: 'default' | 'sm' | 'lg'
-}
-
-const props = withDefaults(defineProps
(), {
- size: 'lg',
-})
+}>()
const recId = inject[>('rec_id')!
const recAction = inject][>('rec_action')!
@@ -63,7 +58,7 @@ function del() {
]
-
+
\ No newline at end of file
diff --git a/app/composables/useRBAC.ts b/app/composables/useRBAC.ts
index ced57e3e..6cc01d72 100644
--- a/app/composables/useRBAC.ts
+++ b/app/composables/useRBAC.ts
@@ -1,5 +1,12 @@
import type { Permission, RoleAccess } from '~/models/role'
+export interface PageOperationPermission {
+ canRead: boolean
+ canCreate: boolean
+ canUpdate: boolean
+ canDelete: boolean
+}
+
/**
* Check if user has access to a page
*/
@@ -36,6 +43,13 @@ export function useRBAC() {
const hasUpdateAccess = (roleAccess: RoleAccess) => checkPermission(roleAccess, 'U')
const hasDeleteAccess = (roleAccess: RoleAccess) => checkPermission(roleAccess, 'D')
+ const getPagePermissions = (roleAccess: RoleAccess): PageOperationPermission => ({
+ canRead : hasReadAccess(roleAccess),
+ canCreate: hasCreateAccess(roleAccess),
+ canUpdate: hasUpdateAccess(roleAccess),
+ canDelete: hasDeleteAccess(roleAccess),
+ })
+
return {
checkRole,
checkPermission,
@@ -44,5 +58,6 @@ export function useRBAC() {
hasReadAccess,
hasUpdateAccess,
hasDeleteAccess,
+ getPagePermissions,
}
}
diff --git a/app/handlers/supporting-document.handler.ts b/app/handlers/supporting-document.handler.ts
new file mode 100644
index 00000000..70b29612
--- /dev/null
+++ b/app/handlers/supporting-document.handler.ts
@@ -0,0 +1,24 @@
+// Handlers
+import { genCrudHandler } from '~/handlers/_handler'
+
+// Services
+import { create, update, remove } from '~/services/supporting-document.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.ts b/app/lib/constants.ts
index 3a52b22e..48fb5c8c 100644
--- a/app/lib/constants.ts
+++ b/app/lib/constants.ts
@@ -383,3 +383,45 @@ export const medicalActionTypeCode: Record
= {
} as const
export type medicalActionTypeCodeKey = keyof typeof medicalActionTypeCode
+
+export const encounterDocTypeCode: Record = {
+ "person-resident-number": 'person-resident-number',
+ "person-driving-license": 'person-driving-license',
+ "person-passport": 'person-passport',
+ "person-family-card": 'person-family-card',
+ "mcu-item-result": 'mcu-item-result',
+ "vclaim-sep": 'vclaim-sep',
+ "vclaim-sipp": 'vclaim-sipp',
+} as const
+export type encounterDocTypeCodeKey = keyof typeof encounterDocTypeCode
+export const encounterDocOpt: { label: string; value: encounterDocTypeCodeKey }[] = [
+ { label: 'KTP', value: 'person-resident-number' },
+ { label: 'SIM', value: 'person-driving-license' },
+ { label: 'Passport', value: 'person-passport' },
+ { label: 'Kartu Keluarga', value: 'person-family-card' },
+ { label: 'Hasil MCU', value: 'mcu-item-result' },
+ { label: 'Klaim SEP', value: 'vclaim-sep' },
+ { label: 'Klaim SIPP', value: 'vclaim-sipp' },
+]
+
+
+export const docTypeCode = {
+ "encounter-patient": 'encounter-patient',
+ "encounter-support": 'encounter-support',
+ "encounter-other": 'encounter-other',
+ "vclaim-sep": 'vclaim-sep',
+ "vclaim-sipp": 'vclaim-sipp',
+} as const
+export const docTypeLabel = {
+ "encounter-patient": 'Data Pasien',
+ "encounter-support": 'Data Penunjang',
+ "encounter-other": 'Lain - Lain',
+ "vclaim-sep": 'SEP',
+ "vclaim-sipp": 'SIPP',
+} as const
+export type docTypeCodeKey = keyof typeof docTypeCode
+export const supportingDocOpt = [
+ { label: 'Data Pasien', value: 'encounter-patient' },
+ { label: 'Data Penunjang', value: 'encounter-support' },
+ { label: 'Lain - Lain', value: 'encounter-other' },
+]
diff --git a/app/lib/utils.ts b/app/lib/utils.ts
index 357d8700..e201a439 100644
--- a/app/lib/utils.ts
+++ b/app/lib/utils.ts
@@ -1,6 +1,7 @@
import type { ClassValue } from 'clsx'
import { clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'
+import { toast } from '~/components/pub/ui/toast'
export interface SelectOptionType<_T = string> {
value: string
@@ -104,3 +105,59 @@ export function calculateAge(birthDate: Date | string | null | undefined): strin
return `${years} tahun ${months} bulan`
}
}
+
+
+/**
+ * Converts a plain JavaScript object (including File objects) into a FormData instance.
+ * @param {object} data - The object to convert (e.g., form values).
+ * @returns {FormData} The new FormData object suitable for API submission.
+ */
+export function toFormData(data: Record): FormData {
+ const formData = new FormData();
+
+ for (const key in data) {
+ if (Object.prototype.hasOwnProperty.call(data, key)) {
+ const value = data[key];
+
+ // Handle File objects, Blobs, or standard JSON values
+ if (value !== null && value !== undefined) {
+ // Check if the value is a File/Blob instance
+ if (value instanceof File || value instanceof Blob) {
+ // Append the file directly
+ formData.append(key, value);
+ } else if (typeof value === 'object') {
+ // Handle nested objects/arrays by stringifying them (optional, depends on API)
+ // Note: Most APIs expect nested data to be handled separately or passed as JSON string
+ // For simplicity, we stringify non-File objects.
+ formData.append(key, JSON.stringify(value));
+ } else {
+ // Append standard string, number, or boolean values
+ formData.append(key, value);
+ }
+ }
+ }
+ }
+
+ return formData;
+}
+
+export function printFormData(formData: FormData) {
+ console.log("--- FormData Contents ---");
+ // Use the entries() iterator to loop through key/value pairs
+ for (const [key, value] of formData.entries()) {
+ if (value instanceof File) {
+ console.log(`Key: ${key}, Value: [File: ${value.name}, Type: ${value.type}, Size: ${value.size} bytes]`);
+ } else {
+ console.log(`Key: ${key}, Value: "${value}"`);
+ }
+ }
+ console.log("-------------------------");
+}
+
+export function unauthorizedToast() {
+ toast({
+ title: 'Unauthorized',
+ description: 'You are not authorized to perform this action.',
+ variant: 'destructive',
+ })
+}
\ No newline at end of file
diff --git a/app/models/encounter-document.ts b/app/models/encounter-document.ts
new file mode 100644
index 00000000..5a98ccd5
--- /dev/null
+++ b/app/models/encounter-document.ts
@@ -0,0 +1,29 @@
+import { type Base, genBase } from "./_base"
+import { docTypeLabel, } from '~/lib/constants'
+import { genEmployee, type Employee } from "./employee"
+import { genEncounter, type Encounter } from "./encounter"
+
+export interface EncounterDocument extends Base {
+ encounter_id: number
+ encounter?: Encounter
+ upload_employee_id: number
+ employee?: Employee
+ type_code: string
+ name: string
+ filePath: string
+ fileName: string
+}
+
+export function genEncounterDocument(): EncounterDocument {
+ return {
+ ...genBase(),
+ encounter_id: 2,
+ encounter: genEncounter(),
+ upload_employee_id: 0,
+ employee: genEmployee(),
+ type_code: docTypeLabel["encounter-patient"],
+ name: 'example',
+ filePath: 'https://bing.com',
+ fileName: 'example',
+ }
+}
diff --git a/app/models/encounter.ts b/app/models/encounter.ts
index fb2c0b04..55fbdfa4 100644
--- a/app/models/encounter.ts
+++ b/app/models/encounter.ts
@@ -1,6 +1,7 @@
import type { DeathCause } from "./death-cause"
import { type Doctor, genDoctor } from "./doctor"
import { genEmployee, type Employee } from "./employee"
+import type { EncounterDocument } from "./encounter-document"
import type { InternalReference } from "./internal-reference"
import { type Patient, genPatient } from "./patient"
import type { Specialist } from "./specialist"
@@ -37,6 +38,7 @@ export interface Encounter {
internalReferences?: InternalReference[]
deathCause?: DeathCause
status_code: string
+ encounterDocuments: EncounterDocument[]
}
export function genEncounter(): Encounter {
@@ -54,7 +56,8 @@ export function genEncounter(): Encounter {
appointment_doctor_id: 0,
appointment_doctor: genDoctor(),
medicalDischargeEducation: '',
- status_code: ''
+ status_code: '',
+ encounterDocuments: [],
}
}
diff --git a/app/pages/(features)/rehab/encounter/[id]/control-letter/add.vue b/app/pages/(features)/rehab/encounter/[id]/control-letter/add.vue
index 1070a29f..fa0b386b 100644
--- a/app/pages/(features)/rehab/encounter/[id]/control-letter/add.vue
+++ b/app/pages/(features)/rehab/encounter/[id]/control-letter/add.vue
@@ -16,9 +16,9 @@ useHead({
title: () => route.meta.title as string,
})
-const roleAccess: PagePermission = PAGE_PERMISSIONS['/patient']
+const roleAccess: PagePermission = PAGE_PERMISSIONS['/rehab/encounter']
-const { checkRole, hasReadAccess } = useRBAC()
+const { checkRole, getPagePermissions } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
@@ -27,14 +27,13 @@ const hasAccess = checkRole(roleAccess)
// }
// Define permission-based computed properties
-// const canRead = hasReadAccess(roleAccess)
-const canRead = true
+const pagePermission = getPagePermissions(roleAccess)
const callbackUrl = route.query['return-path'] as string | undefined
-
+
diff --git a/app/pages/(features)/outpation-action/chemotherapy/list.vue b/app/pages/(features)/rehab/encounter/[id]/document-upload/[document_id]/edit.vue
similarity index 74%
rename from app/pages/(features)/outpation-action/chemotherapy/list.vue
rename to app/pages/(features)/rehab/encounter/[id]/document-upload/[document_id]/edit.vue
index a141baaa..1cf5cc7c 100644
--- a/app/pages/(features)/outpation-action/chemotherapy/list.vue
+++ b/app/pages/(features)/rehab/encounter/[id]/document-upload/[document_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: 'Daftar Kempterapi',
+ title: 'Update Dokumen Pendukung',
contentFrame: 'cf-full-width',
})
@@ -16,24 +16,25 @@ useHead({
title: () => route.meta.title as string,
})
-const roleAccess: PagePermission = PAGE_PERMISSIONS['/doctor']
+const roleAccess: PagePermission = PAGE_PERMISSIONS['/patient']
const { checkRole, hasReadAccess } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
-if (!hasAccess) {
- navigateTo('/403')
-}
+// if (!hasAccess) {
+// navigateTo('/403')
+// }
// Define permission-based computed properties
-const canRead = true // hasReadAccess(roleAccess)
+// const canRead = hasReadAccess(roleAccess)
+const canRead = true
diff --git a/app/pages/(features)/outpation-action/chemotherapy/[mode]/[id]/verification.vue b/app/pages/(features)/rehab/encounter/[id]/document-upload/add.vue
similarity index 53%
rename from app/pages/(features)/outpation-action/chemotherapy/[mode]/[id]/verification.vue
rename to app/pages/(features)/rehab/encounter/[id]/document-upload/add.vue
index ef936ff2..e04220f3 100644
--- a/app/pages/(features)/outpation-action/chemotherapy/[mode]/[id]/verification.vue
+++ b/app/pages/(features)/rehab/encounter/[id]/document-upload/add.vue
@@ -2,46 +2,41 @@
import type { PagePermission } from '~/models/role'
import Error from '~/components/pub/my-ui/error/error.vue'
import { PAGE_PERMISSIONS } from '~/lib/page-permission'
-import ContentChemotherapyAdminList from '~/components/content/chemotherapy/admin-list.vue'
-import ContentChemotherapyVerification from '~/components/content/chemotherapy/verification.vue'
definePageMeta({
middleware: ['rbac'],
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
- title: 'Kemoterapi Admin',
+ title: 'Tambah Dokumen Pendukung',
contentFrame: 'cf-full-width',
})
const route = useRoute()
useHead({
- title: () => 'Verifikasi Jadwal Pasien',
+ title: () => route.meta.title as string,
})
-const roleAccess: PagePermission = PAGE_PERMISSIONS['/doctor'] || {}
+const roleAccess: PagePermission = PAGE_PERMISSIONS['/patient']
const { checkRole, hasReadAccess } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
-if (!hasAccess) {
- navigateTo('/403')
-}
+// if (!hasAccess) {
+// navigateTo('/403')
+// }
// Define permission-based computed properties
-const canRead = true // hasReadAccess(roleAccess)
-
-const mode = computed(() => route.params.mode as string)
+// const canRead = hasReadAccess(roleAccess)
+const canRead = true
+const callbackUrl = route.query['return-path'] as string | undefined
diff --git a/app/pages/(features)/rehab/encounter/[id]/process.vue b/app/pages/(features)/rehab/encounter/[id]/process.vue
index abd0efa7..e25b0e77 100644
--- a/app/pages/(features)/rehab/encounter/[id]/process.vue
+++ b/app/pages/(features)/rehab/encounter/[id]/process.vue
@@ -18,7 +18,7 @@ useHead({
const roleAccess: PagePermission = PAGE_PERMISSIONS['/rehab/encounter']
-const { checkRole, hasCreateAccess } = useRBAC()
+const { checkRole, hasCreateAccess, getPagePermissions } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
@@ -30,11 +30,11 @@ const hasAccess = checkRole(roleAccess)
// }
// Define permission-based computed properties
-const canCreate = true // hasCreateAccess(roleAccess)
+const pagePermission = getPagePermissions(roleAccess)
-
+
diff --git a/app/schemas/document-upload.schema.ts b/app/schemas/document-upload.schema.ts
new file mode 100644
index 00000000..1cfaeee2
--- /dev/null
+++ b/app/schemas/document-upload.schema.ts
@@ -0,0 +1,24 @@
+import { z } from 'zod'
+
+const ACCEPTED_UPLOAD_TYPES = ['image/jpeg', 'image/png', 'application/pdf']
+const MAX_SIZE_BYTES = 1 * 1024 * 1024 // 1MB
+
+const DocumentUploadSchema = z.object({
+ entityType_code: z.string().default('encounter'),
+ ref_id: z.number(),
+ upload_employee_id: z.number().optional(),
+ name: z.string({ required_error: 'Mohon isi', }),
+ type_code: z.string({ required_error: 'Mohon isi', }),
+ content: z.custom
()
+ .refine((f) => f, { message: 'File tidak boleh kosong' })
+ .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 <= MAX_SIZE_BYTES, { message: 'Maksimal 1MB' }),
+})
+
+type DocumentUploadFormData = z.infer
+
+export { DocumentUploadSchema }
+export type { DocumentUploadFormData }
diff --git a/app/services/supporting-document.service.ts b/app/services/supporting-document.service.ts
new file mode 100644
index 00000000..46eaffa9
--- /dev/null
+++ b/app/services/supporting-document.service.ts
@@ -0,0 +1,56 @@
+// Base
+import * as base from './_crud-base'
+
+// Constants
+import { encounterClassCodes, uploadCode, type UploadCodeKey } from '~/lib/constants'
+
+const path = '/api/v1/encounter-document'
+const create_path = '/api/v1/upload'
+const name = 'encounter-document'
+
+export function create(data: any) {
+ return base.create(create_path, data, name)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export function getDetail(id: number | string, params?: any) {
+ return base.getDetail(path, id, name, params)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data, name)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id, name)
+}
+
+export async function uploadAttachment(file: File, userId: number, key: UploadCodeKey) {
+ try {
+ const resolvedKey = uploadCode[key]
+ if (!resolvedKey) {
+ throw new Error(`Invalid upload code key: ${key}`)
+ }
+
+ // siapkan form-data body
+ const formData = new FormData()
+ formData.append('code', resolvedKey)
+ formData.append('content', file)
+
+ // kirim via xfetch
+ const resp = await xfetch(`${path}/${userId}/upload`, 'POST', formData)
+
+ // struktur hasil sama seperti patchPatient
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+
+ return result
+ } catch (error) {
+ console.error('Error uploading attachment:', error)
+ throw new Error('Failed to upload attachment')
+ }
+}
\ No newline at end of file
diff --git a/public/side-menu-items/sys.json b/public/side-menu-items/sys.json
new file mode 100644
index 00000000..c26d85aa
--- /dev/null
+++ b/public/side-menu-items/sys.json
@@ -0,0 +1,368 @@
+[
+ {
+ "heading": "Menu Utama",
+ "items": [
+ {
+ "title": "Dashboard",
+ "icon": "i-lucide-home",
+ "link": "/"
+ },
+ {
+ "title": "Rawat Jalan",
+ "icon": "i-lucide-stethoscope",
+ "children": [
+ {
+ "title": "Antrian Pendaftaran",
+ "link": "/outpatient/registration-queue"
+ },
+ {
+ "title": "Antrian Poliklinik",
+ "link": "/outpatient/polyclinic-queue"
+ },
+ {
+ "title": "Kunjungan",
+ "link": "/outpatient/encounter"
+ },
+ {
+ "title": "Konsultasi",
+ "link": "/outpatient/consultation"
+ }
+ ]
+ },
+ {
+ "title": "IGD",
+ "icon": "i-lucide-zap",
+ "children": [
+ {
+ "title": "Triase",
+ "link": "/emergency/triage"
+ },
+ {
+ "title": "Kunjungan",
+ "link": "/emergency/encounter"
+ },
+ {
+ "title": "Konsultasi",
+ "link": "/emergency/consultation"
+ }
+ ]
+ },
+ {
+ "title": "Rehab Medik",
+ "icon": "i-lucide-bike",
+ "children": [
+ {
+ "title": "Antrean Pendaftaran",
+ "link": "/rehab/registration-queue"
+ },
+ {
+ "title": "Antrean Poliklinik",
+ "link": "/rehab/polyclinic-queue"
+ },
+ {
+ "title": "Kunjungan",
+ "link": "/rehab/encounter"
+ },
+ {
+ "title": "Konsultasi",
+ "link": "/rehab/consultation"
+ }
+ ]
+ },
+ {
+ "title": "Rawat Inap",
+ "icon": "i-lucide-building-2",
+ "children": [
+ {
+ "title": "Permintaan",
+ "link": "/inpatient/request"
+ },
+ {
+ "title": "Kunjungan",
+ "link": "/inpatient/encounter"
+ },
+ {
+ "title": "Konsultasi",
+ "link": "/inpatient/consultation"
+ }
+ ]
+ },
+ {
+ "title": "Obat - Order",
+ "icon": "i-lucide-briefcase-medical",
+ "children": [
+ {
+ "title": "Permintaan",
+ "link": "/medication/order"
+ },
+ {
+ "title": "Standing Order",
+ "link": "/medication/standing-order"
+ }
+ ]
+ },
+ {
+ "title": "Lab - Order",
+ "icon": "i-lucide-microscope",
+ "link": "/pc-lab-order"
+ },
+ {
+ "title": "Lab Mikro - Order",
+ "icon": "i-lucide-microscope",
+ "link": "/micro-lab-order"
+ },
+ {
+ "title": "Lab PA - Order",
+ "icon": "i-lucide-microscope",
+ "link": "/pa-lab-order"
+ },
+ {
+ "title": "Radiologi - Order",
+ "icon": "i-lucide-radio",
+ "link": "/radiology-order"
+ },
+ {
+ "title": "Gizi",
+ "icon": "i-lucide-egg-fried",
+ "link": "/nutrition-order"
+ },
+ {
+ "title": "Pembayaran",
+ "icon": "i-lucide-banknote-arrow-up",
+ "link": "/payment"
+ }
+ ]
+ },
+ {
+ "heading": "Ruang Tindakan Rajal",
+ "items": [
+ {
+ "title": "Kemoterapi",
+ "icon": "i-lucide-droplets",
+ "link": "/outpation-action/cemotherapy"
+ },
+ {
+ "title": "Hemofilia",
+ "icon": "i-lucide-droplet-off",
+ "link": "/outpation-action/hemophilia"
+ }
+ ]
+ },
+ {
+ "heading": "Ruang Tindakan Anak",
+ "items": [
+ {
+ "title": "Thalasemi",
+ "icon": "i-lucide-baby",
+ "link": "/children-action/thalasemia"
+ },
+ {
+ "title": "Echocardiography",
+ "icon": "i-lucide-baby",
+ "link": "/children-action/echocardiography"
+ },
+ {
+ "title": "Spirometri",
+ "icon": "i-lucide-baby",
+ "link": "/children-action/spirometry"
+ }
+ ]
+ },
+ {
+ "heading": "Client",
+ "items": [
+ {
+ "title": "Pasien",
+ "icon": "i-lucide-users",
+ "link": "/client/patient"
+ },
+ {
+ "title": "Rekam Medis",
+ "icon": "i-lucide-file-text",
+ "link": "/client/medical-record"
+ }
+ ]
+ },
+ {
+ "heading": "Integrasi",
+ "items": [
+ {
+ "title": "BPJS",
+ "icon": "i-lucide-circuit-board",
+ "children": [
+ {
+ "title": "SEP",
+ "icon": "i-lucide-circuit-board",
+ "link": "/integration/bpjs/sep"
+ },
+ {
+ "title": "Peserta",
+ "icon": "i-lucide-circuit-board",
+ "link": "/integration/bpjs/member"
+ },
+ {
+ "title": "Surat Kontrol",
+ "icon": "i-lucide-circuit-board",
+ "link": "/integration/bpjs/control-letter"
+ }
+ ]
+ },
+ {
+ "title": "SATUSEHAT",
+ "icon": "i-lucide-database",
+ "link": "/integration/satusehat"
+ }
+ ]
+ },
+ {
+ "heading": "Source",
+ "items": [
+ {
+ "title": "Peralatan dan Perlengkapan",
+ "icon": "i-lucide-layout-dashboard",
+ "children": [
+ {
+ "title": "Obat",
+ "link": "/tools-equipment-src/medicine"
+ },
+ {
+ "title": "Peralatan",
+ "link": "/tools-equipment-src/tools"
+ },
+ {
+ "title": "Perlengkapan (BMHP)",
+ "link": "/tools-equipment-src/equipment"
+ },
+ {
+ "title": "Metode Obat",
+ "link": "/tools-equipment-src/medicine-method"
+ },
+ {
+ "title": "Jenis Obat",
+ "link": "/tools-equipment-src/medicine-type"
+ }
+ ]
+ },
+ {
+ "title": "Pengguna",
+ "icon": "i-lucide-user",
+ "children": [
+ {
+ "title": "Pegawai",
+ "link": "/human-src/employee"
+ },
+ {
+ "title": "PPDS",
+ "link": "/human-src/specialist-intern"
+ }
+ ]
+ },
+ {
+ "title": "Pemeriksaan Penunjang",
+ "icon": "i-lucide-layout-list",
+ "children": [
+ {
+ "title": "Checkup",
+ "link": "/mcu-src/mcu"
+ },
+ {
+ "title": "Prosedur",
+ "link": "/mcu-src/procedure"
+ },
+ {
+ "title": "Diagnosis",
+ "link": "/mcu-src/diagnose"
+ },
+ {
+ "title": "Medical Action",
+ "link": "/mcu-src/medical-action"
+ }
+ ]
+ },
+ {
+ "title": "Layanan",
+ "icon": "i-lucide-layout-list",
+ "children": [
+ {
+ "title": "Counter",
+ "link": "/service-src/counter"
+ },
+ {
+ "title": "Public Screen (Big Screen)",
+ "link": "/service-src/public-screen"
+ },
+ {
+ "title": "Kasur",
+ "link": "/service-src/bed"
+ },
+ {
+ "title": "Kamar",
+ "link": "/service-src/chamber"
+ },
+ {
+ "title": "Ruang",
+ "link": "/service-src/room"
+ },
+ {
+ "title": "Depo",
+ "link": "/service-src/warehouse"
+ },
+ {
+ "title": "Lantai",
+ "link": "/service-src/floor"
+ },
+ {
+ "title": "Gedung",
+ "link": "/service-src/building"
+ }
+ ]
+ },
+ {
+ "title": "Organisasi",
+ "icon": "i-lucide-network",
+ "children": [
+ {
+ "title": "Divisi",
+ "link": "/org-src/division"
+ },
+ {
+ "title": "Instalasi",
+ "link": "/org-src/installation"
+ },
+ {
+ "title": "Unit",
+ "link": "/org-src/unit"
+ },
+ {
+ "title": "Spesialis",
+ "link": "/org-src/specialist"
+ },
+ {
+ "title": "Sub Spesialis",
+ "link": "/org-src/subspecialist"
+ }
+ ]
+ },
+ {
+ "title": "Umum",
+ "icon": "i-lucide-airplay",
+ "children": [
+ {
+ "title": "Uom",
+ "link": "/common/uom"
+ }
+ ]
+ },
+ {
+ "title": "Keuangan",
+ "icon": "i-lucide-airplay",
+ "children": [
+ {
+ "title": "Item & Pricing",
+ "link": "/common/item"
+ }
+ ]
+ }
+ ]
+ }
+]
From bfbe72be94a6a20301ad88c50fc9fa6078bb5087 Mon Sep 17 00:00:00 2001
From: Andrian Roshandy
Date: Wed, 19 Nov 2025 03:36:24 +0700
Subject: [PATCH 29/40] feat/device-order: final
---
.../app/device-order-item/entry-form.vue | 73 ++++++
.../device-order-item/list-entry.config.ts | 35 ++-
.../app/device-order-item/list-entry.vue | 16 +-
.../app/device-order/confirmation-info.vue | 26 ++
.../app/device-order/entry-form.vue | 21 +-
.../app/device-order/list.config.ts | 50 ++--
app/components/content/device-order/entry.vue | 239 +++++++++++++++++-
app/components/content/device-order/list.vue | 201 ++++++---------
app/components/content/device-order/main.vue | 10 +-
app/components/content/encounter/process.vue | 4 +-
app/models/device-order-item.ts | 11 +-
app/models/device-order.ts | 7 +-
app/services/device-order.service.ts | 17 +-
13 files changed, 527 insertions(+), 183 deletions(-)
create mode 100644 app/components/app/device-order-item/entry-form.vue
create mode 100644 app/components/app/device-order/confirmation-info.vue
diff --git a/app/components/app/device-order-item/entry-form.vue b/app/components/app/device-order-item/entry-form.vue
new file mode 100644
index 00000000..3ae2d200
--- /dev/null
+++ b/app/components/app/device-order-item/entry-form.vue
@@ -0,0 +1,73 @@
+
+
+
+
+
+ Nama
+
+
+
+
+
+ Jumlah
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/components/app/device-order-item/list-entry.config.ts b/app/components/app/device-order-item/list-entry.config.ts
index f2f3ef86..d47c4368 100644
--- a/app/components/app/device-order-item/list-entry.config.ts
+++ b/app/components/app/device-order-item/list-entry.config.ts
@@ -1,36 +1,35 @@
import { defineAsyncComponent } from 'vue'
-import type { Config } from '~/components/pub/my-ui/data-table'
-
+import type { Config, RecComponent } from '~/components/pub/my-ui/data-table'
const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-ud.vue'))
export const config: Config = {
- cols: [{}, {}, { width: 50 }],
+ cols: [{}, { width: 200 }, { width: 100 }],
headers: [[{ label: 'Nama' }, { label: 'Jumlah' }, { label: '' }]],
- keys: ['name', 'count', 'action'],
+ keys: ['device.name', 'quantity', 'action'],
delKeyNames: [
{ key: 'name', label: 'Nama' },
{ key: 'count', label: 'Jumlah' },
],
- skeletonSize: 10
+ skeletonSize: 10,
// funcParsed: {
// parent: (rec: unknown): unknown => {
// const recX = rec as SmallDetailDto
// return recX.parent?.name || '-'
// },
// },
- // funcComponent: {
- // action(rec: object, idx: any) {
- // const res: RecComponent = {
- // idx,
- // rec: rec as object,
- // component: action,
- // props: {
- // size: 'sm',
- // },
- // }
- // return res
- // },
- // }
+ components: {
+ action(rec, idx) {
+ const res: RecComponent = {
+ idx,
+ rec: rec as object,
+ component: action,
+ props: {
+ size: 'sm',
+ },
+ }
+ return res
+ },
+ }
}
diff --git a/app/components/app/device-order-item/list-entry.vue b/app/components/app/device-order-item/list-entry.vue
index 26f6691d..b6031228 100644
--- a/app/components/app/device-order-item/list-entry.vue
+++ b/app/components/app/device-order-item/list-entry.vue
@@ -1,13 +1,23 @@
-
+
-
- Tambah
+
+
+ Tambah Item
diff --git a/app/components/app/device-order/confirmation-info.vue b/app/components/app/device-order/confirmation-info.vue
new file mode 100644
index 00000000..6711091f
--- /dev/null
+++ b/app/components/app/device-order/confirmation-info.vue
@@ -0,0 +1,26 @@
+
+
+
+
+ Tgl. Order
+
+
+ {{ data?.createdAt?.substring(0, 10) }}
+
+
+
+ DPJP
+
+
+ {{ data?.doctor?.employee?.person?.name }}
+
+
+
+
\ No newline at end of file
diff --git a/app/components/app/device-order/entry-form.vue b/app/components/app/device-order/entry-form.vue
index bea2b6eb..4e66c441 100644
--- a/app/components/app/device-order/entry-form.vue
+++ b/app/components/app/device-order/entry-form.vue
@@ -1,6 +1,25 @@
- Test
+
+
+ Tanggal
+
+ {{ data?.createdAt?.substring(0, 10) }}
+
+
+
+ DPJP
+
+ {{ data?.doctor?.employee?.person?.name }}
+
+
+
diff --git a/app/components/app/device-order/list.config.ts b/app/components/app/device-order/list.config.ts
index 0e0d068d..04a6c9fc 100644
--- a/app/components/app/device-order/list.config.ts
+++ b/app/components/app/device-order/list.config.ts
@@ -1,10 +1,8 @@
-import type { Config } from '~/components/pub/my-ui/data-table'
+import type { Config, RecComponent } from '~/components/pub/my-ui/data-table'
import type { DeviceOrder } from '~/models/device-order'
-// import type {} from
-// import { defineAsyncComponent } from 'vue'
-
-// const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-ud.vue'))
+import type { DeviceOrderItem } from '~/models/device-order-item'
+const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-dsd.vue'))
export const config: Config = {
cols: [{ width: 120 }, { }, { }, { }, { width: 50 }],
@@ -23,7 +21,21 @@ export const config: Config = {
htmls: {
items: (rec: unknown): unknown => {
const recX = rec as DeviceOrder
- return recX.items?.length || 0
+ if (recX.items?.length > 0) {
+ let output = ''
+ recX.items.forEach((item: DeviceOrderItem) => {
+ output += '' +
+ ''+
+ `${item.device?.name} ` +
+ ': ' +
+ `${item.quantity} ` +
+ ' '
+ })
+ output += '
'
+ return output
+ } else {
+ return '-'
+ }
},
},
parses: {
@@ -36,18 +48,18 @@ export const config: Config = {
// return recX.parent?.name || '-'
// },
},
- // funcComponent: {
- // action(rec: object, idx: any) {
- // const res: RecComponent = {
- // idx,
- // rec: rec as object,
- // component: action,
- // props: {
- // size: 'sm',
- // },
- // }
- // return res
- // },
- // }
+ components: {
+ action(rec, idx) {
+ const res: RecComponent = {
+ idx,
+ rec: rec as object,
+ component: action,
+ props: {
+ size: 'sm',
+ },
+ }
+ return res
+ },
+ }
}
diff --git a/app/components/content/device-order/entry.vue b/app/components/content/device-order/entry.vue
index 6d76d685..5d87d960 100644
--- a/app/components/content/device-order/entry.vue
+++ b/app/components/content/device-order/entry.vue
@@ -1,24 +1,177 @@
@@ -28,10 +181,74 @@ const headerPrep: HeaderPrep = {
class="mb-4 xl:mb-5"
/>
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ handleActionRemove(recId, getDeviceOrderItems, toast)"
+ @cancel=""
+ >
+
+
+ Nama
+
+
+ {{ recItem.device.name }}
+
+
+
+ Dosis
+
+
+ {{ recItem.quantity }}
+
+
+
+
diff --git a/app/components/content/device-order/list.vue b/app/components/content/device-order/list.vue
index 6c23cfc0..1ffa324d 100644
--- a/app/components/content/device-order/list.vue
+++ b/app/components/content/device-order/list.vue
@@ -1,72 +1,38 @@
@@ -175,42 +145,39 @@ function submit(data: DeviceOrder) {
:prep="headerPrep"
:ref-search-nav="headerPrep.refSearchNav"
@search="handleSearch"
- class="mb-4 xl:mb-5"
/>
+
-
+
handleActionSubmit(recId, getMyList, toast)"
+ >
+
+
+
+
+ handleActionRemove(recId, getMyList, toast)"
- @cancel=""
>
-
-
-
- ID:
- {{ record?.id }}
-
-
- Nama:
- {{ record.name }}
-
-
- Kode:
- {{ record.code }}
-
-
-
+
diff --git a/app/components/content/device-order/main.vue b/app/components/content/device-order/main.vue
index ae5a9ca8..ff8722de 100644
--- a/app/components/content/device-order/main.vue
+++ b/app/components/content/device-order/main.vue
@@ -3,10 +3,14 @@
import List from './list.vue'
import Entry from './entry.vue'
-const { mode } = useQueryMode()
+defineProps<{
+ encounter_id: number
+}>()
+
+const { mode } = useQueryCRUDMode()
-
-
+
+
diff --git a/app/components/content/encounter/process.vue b/app/components/content/encounter/process.vue
index c72f6835..7f62f5d1 100644
--- a/app/components/content/encounter/process.vue
+++ b/app/components/content/encounter/process.vue
@@ -64,9 +64,7 @@ const tabs: TabItem[] = [
{ value: 'consent', label: 'General Consent' },
{ value: 'patient-note', label: 'CPRJ' },
{ value: 'prescription', label: 'Order Obat', component: Prescription, props: { encounter_id: data.id } },
- { value: 'device-order', label: 'Order Alkes', component: DeviceOrder, props: { encounter: data } },
- { value: 'mcu-radiology', label: 'Order Radiologi' },
- { value: 'mcu-lab-pc', label: 'Order Lab PK' },
+ { value: 'device-order', label: 'Order Alkes', component: DeviceOrder, props: { encounter_id: data.id } },
{ 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' },
diff --git a/app/models/device-order-item.ts b/app/models/device-order-item.ts
index fa16638a..31b3ee47 100644
--- a/app/models/device-order-item.ts
+++ b/app/models/device-order-item.ts
@@ -1,16 +1,19 @@
import { type Base, genBase } from "./_base"
+import { genDevice, type Device } from "./device"
export interface DeviceOrderItem extends Base {
deviceOrder_id: number
- device_id: number
- count: number
+ device_code: string
+ device: Device
+ quantity: number
}
export function genDeviceOrderItem(): DeviceOrderItem {
return {
...genBase(),
deviceOrder_id: 0,
- device_id: 0,
- count: 0,
+ device_code: '',
+ device: genDevice(),
+ quantity: 0,
}
}
diff --git a/app/models/device-order.ts b/app/models/device-order.ts
index f2e88b0f..cbb682ad 100644
--- a/app/models/device-order.ts
+++ b/app/models/device-order.ts
@@ -1,9 +1,11 @@
import { type Base, genBase } from "./_base"
import type { DeviceOrderItem } from "./device-order-item"
+import { genDoctor, type Doctor } from "./doctor"
export interface DeviceOrder extends Base {
encounter_id: number
- doctor_id: number
+ doctor_code: number
+ doctor: Doctor
status_code?: string
items: DeviceOrderItem[]
}
@@ -12,7 +14,8 @@ export function genDeviceOrder(): DeviceOrder {
return {
...genBase(),
encounter_id: 0,
- doctor_id: 0,
+ doctor_code: 0,
+ doctor: genDoctor(),
items: []
}
}
diff --git a/app/services/device-order.service.ts b/app/services/device-order.service.ts
index b8d5372c..cf70420d 100644
--- a/app/services/device-order.service.ts
+++ b/app/services/device-order.service.ts
@@ -13,8 +13,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) {
@@ -24,3 +24,16 @@ export function update(id: number | string, data: any) {
export function remove(id: number | string) {
return base.remove(path, id, name)
}
+
+export async function submit(id: number) {
+ try {
+ const resp = await xfetch(`${path}/${id}/submit`, 'PATCH')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error(`Error putting ${name}:`, error)
+ throw new Error(`Failed to put ${name}`)
+ }
+}
\ No newline at end of file
From c3f1f997b3b0d7aefd2c5cddda8d1f8d87816fef Mon Sep 17 00:00:00 2001
From: hasyim_kai
Date: Wed, 19 Nov 2025 10:22:12 +0700
Subject: [PATCH 30/40] Fix: refactor upload API url
---
app/components/content/document-upload/add.vue | 3 +--
app/services/supporting-document.service.ts | 4 ++--
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/app/components/content/document-upload/add.vue b/app/components/content/document-upload/add.vue
index 7d42f4f6..23fd30e0 100644
--- a/app/components/content/document-upload/add.vue
+++ b/app/components/content/document-upload/add.vue
@@ -6,8 +6,7 @@ import { handleActionSave,} from '~/handlers/supporting-document.handler'
import { toast } from '~/components/pub/ui/toast'
import Confirmation from '~/components/pub/my-ui/confirmation/confirmation.vue'
import { DocumentUploadSchema } from '~/schemas/document-upload.schema'
-import { uploadAttachment } from '~/services/supporting-document.service'
-import { printFormData, toFormData } from '~/lib/utils'
+import { toFormData } from '~/lib/utils'
// #region Props & Emits
const props = defineProps<{
diff --git a/app/services/supporting-document.service.ts b/app/services/supporting-document.service.ts
index 46eaffa9..2d89d7f1 100644
--- a/app/services/supporting-document.service.ts
+++ b/app/services/supporting-document.service.ts
@@ -2,10 +2,10 @@
import * as base from './_crud-base'
// Constants
-import { encounterClassCodes, uploadCode, type UploadCodeKey } from '~/lib/constants'
+import { uploadCode, type UploadCodeKey } from '~/lib/constants'
const path = '/api/v1/encounter-document'
-const create_path = '/api/v1/upload'
+const create_path = '/api/v1/upload-file'
const name = 'encounter-document'
export function create(data: any) {
From f41a51d9d0e75c7ee3e13f82250c8c5df025996f Mon Sep 17 00:00:00 2001
From: Andrian Roshandy
Date: Wed, 19 Nov 2025 10:58:26 +0700
Subject: [PATCH 31/40] feat/prescription: cleaning
---
app/components/app/prescription/entry.vue | 6 ++
app/components/app/prescription/flat-list.vue | 2 -
.../app/prescription/list-with-sub.vue | 60 +++++++++----------
3 files changed, 35 insertions(+), 33 deletions(-)
diff --git a/app/components/app/prescription/entry.vue b/app/components/app/prescription/entry.vue
index af59a87d..28041eea 100644
--- a/app/components/app/prescription/entry.vue
+++ b/app/components/app/prescription/entry.vue
@@ -41,4 +41,10 @@ defineProps<{
+
diff --git a/app/components/app/prescription/flat-list.vue b/app/components/app/prescription/flat-list.vue
index cf563ef2..fe0bab9c 100644
--- a/app/components/app/prescription/flat-list.vue
+++ b/app/components/app/prescription/flat-list.vue
@@ -1,11 +1,9 @@
@@ -17,40 +15,40 @@
-
-
- Order #1
-
-
+
+
+ Order #1
+
+
2025-01-01
-
-
-
- Status
-
-
+
+
+
+ Status
+
+
Status
-
-
-
+
+
+
-
-
- DPJP
-
-
+
+
+ DPJP
+
+
Nama Dokter
-
-
-
- PPDS
-
-
+
+
+
+ PPDS
+
+
Nama PPDS
-
-
-
+
+
+
From cf4f5574d3cbe2d5af30aa55744c9c94e733b9de Mon Sep 17 00:00:00 2001
From: Abizrh
Date: Wed, 19 Nov 2025 23:46:21 +0700
Subject: [PATCH 32/40] =?UTF-8?q?=E2=9C=A8=20feat=20(generate-file):=20add?=
=?UTF-8?q?=20generate=20file=20schema?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../content/general-consent/form.vue | 32 +++++++++++++++----
app/handlers/general-consent.handler.ts | 24 ++++++++++++++
app/models/general-consent.ts | 3 +-
app/schemas/_generate-file.ts | 5 +++
app/schemas/general-consent.schema.ts | 5 +--
app/services/generate-file.service.ts | 15 +++++++++
6 files changed, 74 insertions(+), 10 deletions(-)
create mode 100644 app/handlers/general-consent.handler.ts
create mode 100644 app/schemas/_generate-file.ts
create mode 100644 app/services/generate-file.service.ts
diff --git a/app/components/content/general-consent/form.vue b/app/components/content/general-consent/form.vue
index 889e5799..d9b67fec 100644
--- a/app/components/content/general-consent/form.vue
+++ b/app/components/content/general-consent/form.vue
@@ -4,9 +4,10 @@ import Entry from '~/components/app/general-consent/entry.vue'
import Action from '~/components/pub/my-ui/nav-footer/ba-dr-su-pr.vue'
import ActionDialog from '~/components/pub/my-ui/nav-footer/ba-su.vue'
import Dialog from '~/components/pub/my-ui/modal/dialog.vue'
-import { FunctionSoapiSchema } from '~/schemas/soapi.schema'
+import { GeneralConsentSchema } from '~/schemas/general-consent.schema'
import { toast } from '~/components/pub/ui/toast'
-import { handleActionSave, handleActionEdit } from '~/handlers/soapi-early.handler'
+import { handleActionSave, handleActionEdit } from '~/handlers/general-consent.handler'
+import { create } from '~/services/generate-file.service'
const { backToList } = useQueryMode('mode')
const route = useRoute()
@@ -19,14 +20,15 @@ const fungsional = ref([])
const selectedProcedure = ref(null)
const selectedDiagnose = ref(null)
const selectedFungsional = ref(null)
-const schema = FunctionSoapiSchema
+const schema = GeneralConsentSchema
const payload = ref({
encounter_id: 0,
value: '',
})
const model = ref({
relatives: [],
- responsible: '',
+ responsibleName: '',
+ responsiblePhone: '',
informant: '',
witness1: '',
witness2: '',
@@ -81,16 +83,32 @@ async function actionHandler(type: string) {
}
const result = await entryGeneralConsent.value?.validate()
if (result?.valid) {
- console.log('data', result.data)
- handleActionSave(
+ if (result.data.relatives.length > 0) {
+ result.data.relatives = result.data.relatives.map((item: any) => {
+ return item.name
+ })
+ }
+
+ console.log('data', result)
+ const resp = await handleActionSave(
{
...payload.value,
value: JSON.stringify(result.data),
encounter_id: +route.params.id,
},
- {},
+ () => {},
+ () => {},
toast,
)
+ const data = resp.body?.data
+ if (data) {
+ const resp2 = await create({
+ entityType_code: 'encounter',
+ ref_id: +data?.id,
+ type_code: 'general-consent',
+ })
+ console.log('resp2', resp2.body?.data)
+ }
} else {
console.log('Ada error di form', result)
}
diff --git a/app/handlers/general-consent.handler.ts b/app/handlers/general-consent.handler.ts
new file mode 100644
index 00000000..2f949f3f
--- /dev/null
+++ b/app/handlers/general-consent.handler.ts
@@ -0,0 +1,24 @@
+// Handlers
+import { genCrudHandler } from '~/handlers/_handler'
+
+// Services
+import { create, update, remove } from '~/services/general-consent.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({
+ create,
+ update,
+ remove,
+})
diff --git a/app/models/general-consent.ts b/app/models/general-consent.ts
index 643230ef..fe3ac97a 100644
--- a/app/models/general-consent.ts
+++ b/app/models/general-consent.ts
@@ -6,7 +6,8 @@ export interface GeneralConsent {
export interface ValueCreateDto {
relatives: string[]
- responsible: string
+ responsibleName: string
+ responsiblePhone: string
informant: string
witness1: string
witness2: string
diff --git a/app/schemas/_generate-file.ts b/app/schemas/_generate-file.ts
new file mode 100644
index 00000000..0e0b05fc
--- /dev/null
+++ b/app/schemas/_generate-file.ts
@@ -0,0 +1,5 @@
+export interface GenerateFile {
+ entityType_code: string
+ ref_id: number
+ type_code: string
+}
diff --git a/app/schemas/general-consent.schema.ts b/app/schemas/general-consent.schema.ts
index 43014fa0..e06c7240 100644
--- a/app/schemas/general-consent.schema.ts
+++ b/app/schemas/general-consent.schema.ts
@@ -2,8 +2,9 @@ import { z } from 'zod'
import type { CreateDto } from '~/models/general-consent'
const GeneralConsentSchema = z.object({
- relatives: z.string().optional(),
- responsible_doctor: z.string().optional(),
+ relatives: z.array(z.object({ name: z.string(), phone: z.string() })),
+ responsibleName: z.string().optional(),
+ responsiblePhone: z.string().optional(),
informant: z.string().optional(),
witness1: z.string().optional(),
witness2: z.string().optional(),
diff --git a/app/services/generate-file.service.ts b/app/services/generate-file.service.ts
new file mode 100644
index 00000000..5849e3d0
--- /dev/null
+++ b/app/services/generate-file.service.ts
@@ -0,0 +1,15 @@
+import * as base from './_crud-base'
+
+const path = '/api/v1/generate-file'
+
+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)
+}
From 0d821cbe3105684af7a0db5affd228defe66f75f Mon Sep 17 00:00:00 2001
From: Abizrh
Date: Thu, 20 Nov 2025 00:13:44 +0700
Subject: [PATCH 33/40] =?UTF-8?q?=E2=9A=99=EF=B8=8F=20chore=20(general-con?=
=?UTF-8?q?sent):=20adjust=20general=20consent=20list=20and=20form=20compo?=
=?UTF-8?q?nent?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../app/general-consent/list.cfg.ts | 35 ++++++++++++++++---
.../content/general-consent/form.vue | 22 ++++++++++--
.../content/general-consent/list.vue | 33 ++++++++++-------
3 files changed, 71 insertions(+), 19 deletions(-)
diff --git a/app/components/app/general-consent/list.cfg.ts b/app/components/app/general-consent/list.cfg.ts
index 3e634d44..c2f57c54 100644
--- a/app/components/app/general-consent/list.cfg.ts
+++ b/app/components/app/general-consent/list.cfg.ts
@@ -18,12 +18,41 @@ export const config: Config = {
{ label: '' },
],
],
- keys: ['date', 'dstUnit.name', 'dstDoctor.name', 'responsible', 'problem', 'solution', 'action'],
+ keys: ['date', 'relatives', 'responsible', 'informant', 'witness1', 'witness2', 'action'],
delKeyNames: [
{ key: 'data', label: 'Tanggal' },
{ key: 'dstDoctor.name', label: 'Dokter' },
],
parses: {
+ date(rec) {
+ const recX = rec as GeneralConsent
+ return recX?.createdAt?.substring(0, 10) || '-'
+ },
+ relatives(rec) {
+ const recX = rec as GeneralConsent
+ const parsed = JSON.parse(recX?.value || '{}')
+ return parsed?.relatives?.join(', ') || '-'
+ },
+ responsible(rec) {
+ const recX = rec as GeneralConsent
+ const parsed = JSON.parse(recX?.value || '{}')
+ return parsed?.responsible || '-'
+ },
+ informant(rec) {
+ const recX = rec as GeneralConsent
+ const parsed = JSON.parse(recX?.value || '{}')
+ return parsed?.informant || '-'
+ },
+ witness1(rec) {
+ const recX = rec as GeneralConsent
+ const parsed = JSON.parse(recX?.value || '{}')
+ return parsed?.witness1 || '-'
+ },
+ witness2(rec) {
+ const recX = rec as GeneralConsent
+ const parsed = JSON.parse(recX?.value || '{}')
+ return parsed?.witness2 || '-'
+ },
action(rec, idx) {
const res: RecComponent = {
idx,
@@ -35,10 +64,6 @@ export const config: Config = {
}
return res
},
- date(rec) {
- const recX = rec as GeneralConsent
- return recX.date?.substring(0, 10) || '-'
- },
},
components: {
action(rec, idx) {
diff --git a/app/components/content/general-consent/form.vue b/app/components/content/general-consent/form.vue
index d9b67fec..8c15ceb0 100644
--- a/app/components/content/general-consent/form.vue
+++ b/app/components/content/general-consent/form.vue
@@ -8,6 +8,8 @@ import { GeneralConsentSchema } from '~/schemas/general-consent.schema'
import { toast } from '~/components/pub/ui/toast'
import { handleActionSave, handleActionEdit } from '~/handlers/general-consent.handler'
import { create } from '~/services/generate-file.service'
+// Services
+import { getDetail } from '~/services/general-consent.service'
const { backToList } = useQueryMode('mode')
const route = useRoute()
@@ -57,10 +59,26 @@ async function getProcedures() {
}
onMounted(() => {
- getProcedures()
- getDiagnoses()
+ const mode = route.query.mode
+ const recordId = route.query['record-id']
+
+ if (mode === 'entry' && recordId) {
+ loadEntryForEdit(+recordId)
+ }
})
+// TODO: mapping data detail when edit
+const loadEntryForEdit = async (id: number) => {
+ const result = await getDetail(id)
+
+ if (result?.success) {
+ const data = result.body?.data || {}
+
+ console.log('Mapping data:', data)
+ // Set state utk form
+ }
+}
+
function handleClick(type: string) {
if (type === 'prosedur') {
isOpenProcedure.value = true
diff --git a/app/components/content/general-consent/list.vue b/app/components/content/general-consent/list.vue
index 588ff849..caba7f7c 100644
--- a/app/components/content/general-consent/list.vue
+++ b/app/components/content/general-consent/list.vue
@@ -28,7 +28,7 @@ import {
handleActionEdit,
handleActionRemove,
handleCancelForm,
-} from '~/handlers/consultation.handler'
+} from '~/handlers/general-consent.handler'
// Services
import { getList, getDetail } from '~/services/general-consent.service'
@@ -42,8 +42,9 @@ interface Props {
}
const props = defineProps()
const emits = defineEmits(['add', 'edit'])
+const router = useRouter()
+const route = useRoute()
-const { recordId } = useQueryCRUDRecordId()
const { goToEntry, backToList } = useQueryCRUDMode('mode')
let units = ref<{ value: string; label: string }[]>([])
@@ -93,6 +94,17 @@ const headerPrep: HeaderPrep = {
},
}
+const goEdit = (id: string) => {
+ router.replace({
+ path: route.path,
+ query: {
+ ...route.query,
+ mode: 'entry',
+ 'record-id': id,
+ },
+ })
+}
+
const today = new Date()
provide('rec_id', recId)
@@ -110,16 +122,13 @@ const getMyDetail = async (id: number | string) => {
}
// Watch for row actions when recId or recAction changes
-watch([recId, recAction], () => {
- switch (recAction.value) {
- case ActionEvents.showDetail:
- getMyDetail(recId.value)
- title.value = 'Detail Konsultasi'
- isReadonly.value = true
- break
- case ActionEvents.showConfirmDelete:
- isRecordConfirmationOpen.value = true
- break
+watch(recId, () => {
+ console.log('recId', recId.value)
+ if (recAction.value === ActionEvents.showEdit) {
+ goEdit(recId.value)
+ return
+ } else {
+ isRecordConfirmationOpen.value = true
}
})
From f1307980ff5f83fab99418fcedf8937b11bdaa42 Mon Sep 17 00:00:00 2001
From: Abizrh
Date: Thu, 20 Nov 2025 00:35:25 +0700
Subject: [PATCH 34/40] =?UTF-8?q?=F0=9F=90=9B=20fix=20(general-consent):?=
=?UTF-8?q?=20fix=20mapping=20data=20from=20api?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/components/content/general-consent/form.vue | 15 +++++++++++----
app/components/content/general-consent/list.vue | 1 -
app/composables/useQueryCRUD.ts | 12 +++++++++++-
3 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/app/components/content/general-consent/form.vue b/app/components/content/general-consent/form.vue
index 8c15ceb0..e26dbac1 100644
--- a/app/components/content/general-consent/form.vue
+++ b/app/components/content/general-consent/form.vue
@@ -10,7 +10,8 @@ import { handleActionSave, handleActionEdit } from '~/handlers/general-consent.h
import { create } from '~/services/generate-file.service'
// Services
import { getDetail } from '~/services/general-consent.service'
-const { backToList } = useQueryMode('mode')
+const { backToList } = useQueryCRUDMode('mode')
+const { recordId } = useQueryCRUDRecordId('record-id')
const route = useRoute()
const isOpenProcedure = ref(false)
@@ -74,8 +75,15 @@ const loadEntryForEdit = async (id: number) => {
if (result?.success) {
const data = result.body?.data || {}
- console.log('Mapping data:', data)
- // Set state utk form
+ const value = JSON.parse(data.value || '{}')
+ console.log('Mapping data:', value)
+ model.value.witness1 = value?.witness1 || ''
+ model.value.witness2 = value?.witness2 || ''
+ model.value.informant = value?.informant || ''
+ model.value.responsibleName = value?.responsible || ''
+ model.value.responsiblePhone = value?.responsiblePhone || ''
+ model.value.relatives = value?.relatives || []
+ console.log('model', model.value)
}
}
@@ -95,7 +103,6 @@ async function actionHandler(type: string) {
return
}
if (type === 'print') {
- console.log('print')
isOpenDiagnose.value = true
return
}
diff --git a/app/components/content/general-consent/list.vue b/app/components/content/general-consent/list.vue
index caba7f7c..4cf269ee 100644
--- a/app/components/content/general-consent/list.vue
+++ b/app/components/content/general-consent/list.vue
@@ -89,7 +89,6 @@ const headerPrep: HeaderPrep = {
icon: 'i-lucide-plus',
onClick: () => {
goToEntry()
- emits('add')
},
},
}
diff --git a/app/composables/useQueryCRUD.ts b/app/composables/useQueryCRUD.ts
index a48e9a2b..f81649bd 100644
--- a/app/composables/useQueryCRUD.ts
+++ b/app/composables/useQueryCRUD.ts
@@ -19,7 +19,17 @@ export function useQueryCRUDMode(key: string = 'mode') {
})
const goToEntry = () => (mode.value = 'entry')
- const backToList = () =>(mode.value = 'list')
+ const backToList = () => {
+ router.push({
+ path: route.path,
+ query: {
+ ...route.query,
+ mode: 'list',
+ // HAPUS record-id
+ 'record-id': undefined,
+ },
+ })
+ }
return { mode, goToEntry, backToList }
}
From b379a9bc947cc9960c74fb745e38edc6701fe8ab Mon Sep 17 00:00:00 2001
From: Abizrh
Date: Thu, 20 Nov 2025 13:04:27 +0700
Subject: [PATCH 35/40] =?UTF-8?q?=E2=9C=A8=20feat=20(general-consent):=20d?=
=?UTF-8?q?isplay=20file=20url=20in=20diagnose=20dialog?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/components/content/general-consent/form.vue | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/app/components/content/general-consent/form.vue b/app/components/content/general-consent/form.vue
index e26dbac1..bfc21472 100644
--- a/app/components/content/general-consent/form.vue
+++ b/app/components/content/general-consent/form.vue
@@ -37,6 +37,7 @@ const model = ref({
witness2: '',
})
+const fileUrl = ref('')
const isLoading = reactive({
isTableLoading: false,
})
@@ -76,7 +77,6 @@ const loadEntryForEdit = async (id: number) => {
const data = result.body?.data || {}
const value = JSON.parse(data.value || '{}')
- console.log('Mapping data:', value)
model.value.witness1 = value?.witness1 || ''
model.value.witness2 = value?.witness2 || ''
model.value.informant = value?.informant || ''
@@ -103,6 +103,9 @@ async function actionHandler(type: string) {
return
}
if (type === 'print') {
+ const data = await getDetail(recordId.value)
+ const detail = data.body?.data
+ fileUrl.value = detail?.fileUrl
isOpenDiagnose.value = true
return
}
@@ -173,8 +176,9 @@ provide('icdPreview', icdPreview)
size="xl"
prevent-outside
>
-
+
From 1f3ca6f19bc8befa098120292fe241986ce81cef Mon Sep 17 00:00:00 2001
From: Abizrh
Date: Thu, 20 Nov 2025 13:43:19 +0700
Subject: [PATCH 36/40] =?UTF-8?q?=F0=9F=90=9B=20fix=20(general-consent):?=
=?UTF-8?q?=20fix=20type=20error=20when=20create=20encounter?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/components/content/general-consent/form.vue | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/app/components/content/general-consent/form.vue b/app/components/content/general-consent/form.vue
index bfc21472..738adca1 100644
--- a/app/components/content/general-consent/form.vue
+++ b/app/components/content/general-consent/form.vue
@@ -132,10 +132,11 @@ async function actionHandler(type: string) {
if (data) {
const resp2 = await create({
entityType_code: 'encounter',
- ref_id: +data?.id,
+ ref_id: data?.id,
type_code: 'general-consent',
})
console.log('resp2', resp2.body?.data)
+ backToList()
}
} else {
console.log('Ada error di form', result)
From e47401577fe18e54af77333a2041930c27c745af Mon Sep 17 00:00:00 2001
From: hasyim_kai
Date: Fri, 21 Nov 2025 10:04:48 +0700
Subject: [PATCH 37/40] Squashed commit of the following:
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
commit b9f910cc5f75bf8198b295a367b8a6e881ea36de
Merge: ba3e70c 064f341
Author: Munawwirul Jamal <57973347+munaja@users.noreply.github.com>
Date: Fri Nov 21 08:55:22 2025 +0700
Merge pull request #177 from dikstub-rssa/feat/prescription
Feat/prescription
commit 064f34177c89c0a1a5001610af21bd03e8f0d88a
Merge: 88d89f2 ba3e70c
Author: Munawwirul Jamal
Date: Fri Nov 21 08:52:24 2025 +0700
Merge branch 'dev' into feat/prescription
commit ba3e70c8546b7e55ae4d1b911fc3e43669f457c1
Merge: d75b32c d6c4a1e
Author: Munawwirul Jamal <57973347+munaja@users.noreply.github.com>
Date: Fri Nov 21 08:46:33 2025 +0700
Merge pull request #176 from dikstub-rssa/feat/device-order
Feat/device order
commit d6c4a1ebb43a45f558a6dd84feb525a060e2ecba
Merge: a8a71d8 d75b32c
Author: Munawwirul Jamal
Date: Fri Nov 21 08:42:09 2025 +0700
Merge branch 'dev' into feat/device-order
commit d75b32cc0858b7a9bf02b179d43932d03600ae46
Merge: 79d8bfa 2e48f11
Author: Munawwirul Jamal <57973347+munaja@users.noreply.github.com>
Date: Fri Nov 21 08:38:51 2025 +0700
Merge pull request #172 from dikstub-rssa/feat/uploads-85-after-reset
Fix: debug Uplaod Doc after reset
commit 2e48f11f9c52809424217f4238f2d79e27824074
Merge: c3f1f99 79d8bfa
Author: Munawwirul Jamal
Date: Fri Nov 21 08:38:37 2025 +0700
Merge branch 'dev' into feat/uploads-85-after-reset
commit 79d8bfa782f4ebd407dee568ed421262ba98a301
Merge: f375724 cffaa2b
Author: Munawwirul Jamal <57973347+munaja@users.noreply.github.com>
Date: Fri Nov 21 08:19:55 2025 +0700
Merge pull request #170 from dikstub-rssa/feat/medicine-form-167
Feat/medicine form 167
commit cffaa2b855e0ee6c2b0b279c3d802e18bde434ae
Merge: ac5fd26 f375724
Author: Munawwirul Jamal
Date: Fri Nov 21 08:17:43 2025 +0700
Merge branch 'dev' into feat/medicine-form-167
commit f375724be1ca76f2855a51f594c600d9343a03d2
Merge: 2c07b9c 6780a65
Author: Munawwirul Jamal <57973347+munaja@users.noreply.github.com>
Date: Fri Nov 21 07:43:22 2025 +0700
Merge pull request #152 from dikstub-rssa/feat/general-consent-145
✨ feat (encounter): implement general consent feature
commit 6780a65f04eef9c6bd90f6fda7e35376ce885134
Merge: 1f3ca6f 2c07b9c
Author: Munawwirul Jamal
Date: Fri Nov 21 07:43:08 2025 +0700
Merge branch 'dev' into feat/general-consent-145
commit 2c07b9cde8b1679fbb8e2ab11c93e8d82209e4e4
Merge: baf6ab1 dab6adc
Author: Munawwirul Jamal <57973347+munaja@users.noreply.github.com>
Date: Fri Nov 21 07:31:13 2025 +0700
Merge pull request #148 from dikstub-rssa/feat/resume-81
Feat: UI Rehab Medik - Resume
commit 1f3ca6f19bc8befa098120292fe241986ce81cef
Author: Abizrh
Date: Thu Nov 20 13:43:19 2025 +0700
🐛 fix (general-consent): fix type error when create encounter
commit b379a9bc947cc9960c74fb745e38edc6701fe8ab
Author: Abizrh
Date: Thu Nov 20 13:04:27 2025 +0700
✨ feat (general-consent): display file url in diagnose dialog
commit f1307980ff5f83fab99418fcedf8937b11bdaa42
Author: Abizrh
Date: Thu Nov 20 00:35:25 2025 +0700
🐛 fix (general-consent): fix mapping data from api
commit 0d821cbe3105684af7a0db5affd228defe66f75f
Author: Abizrh
Date: Thu Nov 20 00:13:44 2025 +0700
⚙️ chore (general-consent): adjust general consent list and form component
commit cf4f5574d3cbe2d5af30aa55744c9c94e733b9de
Author: Abizrh
Date: Wed Nov 19 23:46:21 2025 +0700
✨ feat (generate-file): add generate file schema
commit 6e34e175e79dd278e3d4f451360dec21f2516b96
Merge: e62ee1b baf6ab1
Author: Abizrh
Date: Wed Nov 19 23:12:38 2025 +0700
Merge branch 'dev' of https://github.com/dikstub-rssa/simrs-fe into feat/general-consent-145
commit a8a71d89785995b7133a71df4f6f7029667f60b6
Merge: bfbe72b baf6ab1
Author: Andrian Roshandy
Date: Wed Nov 19 22:22:03 2025 +0700
Merge branch 'dev' into feat/device-order
commit 88d89f2a2dc0ffaea09c9401189110d14df08b03
Merge: 512f8e8 391469e
Author: Andrian Roshandy
Date: Wed Nov 19 22:21:36 2025 +0700
Merge branch 'feat/prescription' of github.com:dikstub-rssa/simrs-fe into feat/prescription
commit 512f8e8c917b59ee2453cc7b3f873028c74a264b
Merge: f41a51d baf6ab1
Author: Andrian Roshandy
Date: Wed Nov 19 22:19:45 2025 +0700
Merge branch 'dev' into feat/prescription
commit baf6ab1fda61f59f966949a1886c2399ac9e7551
Author: Munawwirul Jamal
Date: Wed Nov 19 20:09:19 2025 +0700
dev: hotfix, pubs
+ my-ui/confirmation/confirmation noTrueSlot from record-confirmation
+ my-ui/confirmation/confirmation additional message
+ my-ui/confirmation/record-confirmation supplies noTrueSlot
+ my-ui/modal/modal text size
+ my-ui/doc-entry semicolon export
commit f41a51d9d0e75c7ee3e13f82250c8c5df025996f
Author: Andrian Roshandy
Date: Wed Nov 19 10:58:26 2025 +0700
feat/prescription: cleaning
commit c3f1f997b3b0d7aefd2c5cddda8d1f8d87816fef
Author: hasyim_kai
Date: Wed Nov 19 10:22:12 2025 +0700
Fix: refactor upload API url
commit bfbe72be94a6a20301ad88c50fc9fa6078bb5087
Author: Andrian Roshandy
Date: Wed Nov 19 03:36:24 2025 +0700
feat/device-order: final
commit 0a68dbf3a625fec9580310aca1d34ccf74ba2a31
Author: hasyim_kai
Date: Tue Nov 18 15:31:04 2025 +0700
Fix: debug after reset
commit ac5fd26399f9f35fe266886415d5de24a3d5b657
Merge: 94e4ead bcfb4c1
Author: Muhammad Hasyim Chaidir Ali <68959522+Hasyim-Kai@users.noreply.github.com>
Date: Tue Nov 18 13:33:09 2025 +0700
Merge branch 'dev' into feat/medicine-form-167
commit 94e4ead8fe13ad7dc518ad87d1f3f01620791d01
Author: hasyim_kai
Date: Tue Nov 18 13:13:52 2025 +0700
Fix: debug updaate medicine master
commit c98018bb4eaacbcd05763f404b40d3d4a27899dd
Author: hasyim_kai
Date: Tue Nov 18 12:58:58 2025 +0700
Squashed commit of the following:
commit bcfb4c1456b7b58c63d4969985200ceca72aee16
Merge: 1cbde57 975c87d
Author: Munawwirul Jamal <57973347+munaja@users.noreply.github.com>
Date: Mon Nov 17 11:15:14 2025 +0700
Merge pull request #147 from dikstub-rssa/feat/surat-kontrol-135
Feat: Integration Rehab Medik - Surat Kontrol
commit 975c87d99af0471f62111a455fa214abc1f2e998
Merge: f582090 1cbde57
Author: hasyim_kai