+
Belum Ada Data
-
-
+
+
+ Order #{{ data.length - idx }} - {{ item.issuedAt?.substring(0, 10) || item.createdAt?.substring(0, 10) }} - {{ item.status_code }}
+
+
+
+ DPJP
+
+ {{ item.doctor?.employee?.person?.name || '-' }}
+
+
+
+ PPDS
+
+ ...........
+
+
+
+
+
+
+
+
diff --git a/app/components/app/sep/entry-form.vue b/app/components/app/sep/entry-form.vue
index e48d23ec..35956ad7 100644
--- a/app/components/app/sep/entry-form.vue
+++ b/app/components/app/sep/entry-form.vue
@@ -1,91 +1,245 @@
-
-
diff --git a/app/components/app/sep/table-history-sep.vue b/app/components/app/sep/table-history-sep.vue
deleted file mode 100644
index bfe00e51..00000000
--- a/app/components/app/sep/table-history-sep.vue
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
-
diff --git a/app/components/app/sep/table-search-letter.vue b/app/components/app/sep/table-search-letter.vue
deleted file mode 100644
index 64e65ff6..00000000
--- a/app/components/app/sep/table-search-letter.vue
+++ /dev/null
@@ -1,104 +0,0 @@
-
-
-
-
-
diff --git a/app/components/app/sep/table-search-patient.vue b/app/components/app/sep/table-search-patient.vue
deleted file mode 100644
index 13a78651..00000000
--- a/app/components/app/sep/table-search-patient.vue
+++ /dev/null
@@ -1,100 +0,0 @@
-
-
-
-
-
diff --git a/app/components/app/sep/view-history.vue b/app/components/app/sep/view-history.vue
new file mode 100644
index 00000000..a6a6091c
--- /dev/null
+++ b/app/components/app/sep/view-history.vue
@@ -0,0 +1,46 @@
+
+
+
+
+
diff --git a/app/components/app/sep/view-letter.vue b/app/components/app/sep/view-letter.vue
new file mode 100644
index 00000000..e1c0ecf2
--- /dev/null
+++ b/app/components/app/sep/view-letter.vue
@@ -0,0 +1,128 @@
+
+
+
+
+
diff --git a/app/components/app/specialist-position/entry-detail.vue b/app/components/app/specialist-position/entry-detail.vue
new file mode 100644
index 00000000..f21ff65f
--- /dev/null
+++ b/app/components/app/specialist-position/entry-detail.vue
@@ -0,0 +1,192 @@
+
+
+
+
+
diff --git a/app/components/app/specialist-position/entry-form.vue b/app/components/app/specialist-position/entry-form.vue
new file mode 100644
index 00000000..be031219
--- /dev/null
+++ b/app/components/app/specialist-position/entry-form.vue
@@ -0,0 +1,207 @@
+
+
+
+
+
diff --git a/app/components/app/specialist-position/list.cfg.ts b/app/components/app/specialist-position/list.cfg.ts
new file mode 100644
index 00000000..35f49c20
--- /dev/null
+++ b/app/components/app/specialist-position/list.cfg.ts
@@ -0,0 +1,61 @@
+import type { Config, RecComponent } from '~/components/pub/my-ui/data-table'
+import { defineAsyncComponent } from 'vue'
+import type { DivisionPosition } from '~/models/division-position'
+
+type SmallDetailDto = any
+
+const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-ud.vue'))
+
+export const config: Config = {
+ cols: [{}, {}, {}, {}, {}, { width: 50 }],
+
+ headers: [
+ [
+ { label: 'Kode Posisi' },
+ { label: 'Nama Posisi' },
+ { label: 'Nama Spesialis ' },
+ { label: 'Karyawan' },
+ { label: 'Status Kepala' },
+ { label: '' },
+ ],
+ ],
+
+ keys: ['code', 'name', 'specialist.name', 'employee', 'head', 'action'],
+
+ delKeyNames: [
+ { key: 'code', label: 'Kode' },
+ { key: 'name', label: 'Nama' },
+ ],
+
+ parses: {
+ employee: (rec: unknown): unknown => {
+ const recX = rec as DivisionPosition
+ const fullName = [recX.employee?.person.frontTitle, recX.employee?.person.name, recX.employee?.person.endTitle]
+ .filter(Boolean)
+ .join(' ')
+ .trim()
+
+ return fullName || '-'
+ },
+ head: (rec: unknown): unknown => {
+ const recX = rec as SmallDetailDto
+ return recX.headStatus ? 'Ya' : 'Tidak'
+ },
+ },
+
+ components: {
+ action(rec, idx) {
+ const res: RecComponent = {
+ idx,
+ rec: rec as object,
+ component: action,
+ props: {
+ size: 'sm',
+ },
+ }
+ return res
+ },
+ },
+
+ htmls: {},
+}
diff --git a/app/components/app/specialist-position/list.vue b/app/components/app/specialist-position/list.vue
new file mode 100644
index 00000000..6ad7dd81
--- /dev/null
+++ b/app/components/app/specialist-position/list.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
diff --git a/app/components/app/specialist/detail/index.vue b/app/components/app/specialist/detail/index.vue
new file mode 100644
index 00000000..3f32a78f
--- /dev/null
+++ b/app/components/app/specialist/detail/index.vue
@@ -0,0 +1,37 @@
+
+
+
+ {{ specialist.code || '-' }}
+ {{ specialist.name || '-' }}
+
+ {{ [specialist.unit?.code, specialist.unit?.name].filter(Boolean).join(' / ') || '-' }}
+
+
+
+
diff --git a/app/components/app/specialist/detail/list.cfg.ts b/app/components/app/specialist/detail/list.cfg.ts
new file mode 100644
index 00000000..8faf9e61
--- /dev/null
+++ b/app/components/app/specialist/detail/list.cfg.ts
@@ -0,0 +1,61 @@
+import type { Config, RecComponent } from '~/components/pub/my-ui/data-table'
+import { defineAsyncComponent } from 'vue'
+import type { UnitPosition } from '~/models/unit-position'
+
+type SmallDetailDto = any
+
+const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-ud.vue'))
+
+export const config: Config = {
+ cols: [{}, {}, {}, {}, {}, { width: 50 }],
+
+ headers: [
+ [
+ { label: '#' },
+ { label: 'Kode Posisi' },
+ { label: 'Nama Posisi' },
+ { label: 'Karyawan' },
+ { label: 'Status Kepala' },
+ { label: '' },
+ ],
+ ],
+
+ keys: ['index', 'code', 'name', 'employee', 'head', 'action'],
+
+ delKeyNames: [
+ { key: 'code', label: 'Kode' },
+ { key: 'name', label: 'Nama' },
+ ],
+
+ parses: {
+ employee: (rec: unknown): unknown => {
+ const recX = rec as UnitPosition
+ const fullName = [recX.employee?.person.frontTitle, recX.employee?.person.name, recX.employee?.person.endTitle]
+ .filter(Boolean)
+ .join(' ')
+ .trim()
+
+ return fullName || '-'
+ },
+ head: (rec: unknown): unknown => {
+ const recX = rec as SmallDetailDto
+ return recX.headStatus ? 'Ya' : 'Tidak'
+ },
+ },
+
+ components: {
+ action(rec, idx) {
+ const res: RecComponent = {
+ idx,
+ rec: rec as object,
+ component: action,
+ props: {
+ size: 'sm',
+ },
+ }
+ return res
+ },
+ },
+
+ htmls: {},
+}
diff --git a/app/components/app/specialist/detail/list.vue b/app/components/app/specialist/detail/list.vue
new file mode 100644
index 00000000..da83e7ca
--- /dev/null
+++ b/app/components/app/specialist/detail/list.vue
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
diff --git a/app/components/app/specialist/list-cfg.ts b/app/components/app/specialist/list-cfg.ts
index 8ed75f28..010358c4 100644
--- a/app/components/app/specialist/list-cfg.ts
+++ b/app/components/app/specialist/list-cfg.ts
@@ -8,16 +8,9 @@ const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dr
export const config: Config = {
cols: [{}, {}, {}, { width: 50 }],
- headers: [
- [
- { label: 'Kode' },
- { label: 'Nama' },
- { label: 'Unit' },
- { label: '' },
- ],
- ],
+ headers: [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Nama Unit' }, { label: '' }]],
- keys: ['code', 'name', 'unit', 'action'],
+ keys: ['code', 'name', 'unit.name', 'action'],
delKeyNames: [
{ key: 'code', label: 'Kode' },
@@ -29,10 +22,6 @@ export const config: Config = {
const recX = rec as SmallDetailDto
return `${recX.name}`.trim()
},
- unit: (rec: unknown): unknown => {
- const recX = rec as SmallDetailDto
- return recX.unit_id || '-'
- },
},
components: {
diff --git a/app/components/app/subspecialist-position/entry-detail.vue b/app/components/app/subspecialist-position/entry-detail.vue
new file mode 100644
index 00000000..fd3f91b7
--- /dev/null
+++ b/app/components/app/subspecialist-position/entry-detail.vue
@@ -0,0 +1,192 @@
+
+
+
+
+
diff --git a/app/components/app/subspecialist-position/entry-form.vue b/app/components/app/subspecialist-position/entry-form.vue
new file mode 100644
index 00000000..c897b2f5
--- /dev/null
+++ b/app/components/app/subspecialist-position/entry-form.vue
@@ -0,0 +1,207 @@
+
+
+
+
+
diff --git a/app/components/app/subspecialist-position/list.cfg.ts b/app/components/app/subspecialist-position/list.cfg.ts
new file mode 100644
index 00000000..028bc7bf
--- /dev/null
+++ b/app/components/app/subspecialist-position/list.cfg.ts
@@ -0,0 +1,65 @@
+import type { Config, RecComponent } from '~/components/pub/my-ui/data-table'
+import { defineAsyncComponent } from 'vue'
+import type { SubSpecialistPosition } from '~/models/subspecialist-position'
+
+type SmallDetailDto = any
+
+const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-ud.vue'))
+
+export const config: Config = {
+ cols: [{}, {}, {}, {}, {}, { width: 50 }],
+
+ headers: [
+ [
+ { label: 'Kode Posisi' },
+ { label: 'Nama Posisi' },
+ { label: 'Nama Sub Spesialis ' },
+ { label: 'Karyawan' },
+ { label: 'Status Kepala' },
+ { label: '' },
+ ],
+ ],
+
+ keys: ['code', 'name', 'subspecialist', 'employee', 'head', 'action'],
+
+ delKeyNames: [
+ { key: 'code', label: 'Kode' },
+ { key: 'name', label: 'Nama' },
+ ],
+
+ parses: {
+ subspecialist: (rec: unknown): unknown => {
+ const recX = rec as SubSpecialistPosition
+ return recX.subspecialist?.name || '-'
+ },
+ employee: (rec: unknown): unknown => {
+ const recX = rec as SubSpecialistPosition
+ const fullName = [recX.employee?.person.frontTitle, recX.employee?.person.name, recX.employee?.person.endTitle]
+ .filter(Boolean)
+ .join(' ')
+ .trim()
+
+ return fullName || '-'
+ },
+ head: (rec: unknown): unknown => {
+ const recX = rec as SmallDetailDto
+ return recX.headStatus ? 'Ya' : 'Tidak'
+ },
+ },
+
+ components: {
+ action(rec, idx) {
+ const res: RecComponent = {
+ idx,
+ rec: rec as object,
+ component: action,
+ props: {
+ size: 'sm',
+ },
+ }
+ return res
+ },
+ },
+
+ htmls: {},
+}
diff --git a/app/components/app/subspecialist-position/list.vue b/app/components/app/subspecialist-position/list.vue
new file mode 100644
index 00000000..6ad7dd81
--- /dev/null
+++ b/app/components/app/subspecialist-position/list.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
diff --git a/app/components/app/subspecialist/detail/index.vue b/app/components/app/subspecialist/detail/index.vue
new file mode 100644
index 00000000..154acf75
--- /dev/null
+++ b/app/components/app/subspecialist/detail/index.vue
@@ -0,0 +1,49 @@
+
+
+
+ {{ subspecialist.code || '-' }}
+ {{ subspecialist.name || '-' }}
+
+ {{ [subspecialist.specialist?.code, subspecialist.specialist?.name].filter(Boolean).join(' / ') || '-' }}
+
+
+ {{
+ [subspecialist.specialist?.unit?.code, subspecialist.specialist?.unit?.name].filter(Boolean).join(' / ') || '-'
+ }}
+
+
+ {{
+ [subspecialist.specialist?.unit?.installation?.code, subspecialist.specialist?.unit?.installation?.name]
+ .filter(Boolean)
+ .join(' / ') || '-'
+ }}
+
+
+
+
diff --git a/app/components/app/subspecialist/detail/list.cfg.ts b/app/components/app/subspecialist/detail/list.cfg.ts
new file mode 100644
index 00000000..8faf9e61
--- /dev/null
+++ b/app/components/app/subspecialist/detail/list.cfg.ts
@@ -0,0 +1,61 @@
+import type { Config, RecComponent } from '~/components/pub/my-ui/data-table'
+import { defineAsyncComponent } from 'vue'
+import type { UnitPosition } from '~/models/unit-position'
+
+type SmallDetailDto = any
+
+const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-ud.vue'))
+
+export const config: Config = {
+ cols: [{}, {}, {}, {}, {}, { width: 50 }],
+
+ headers: [
+ [
+ { label: '#' },
+ { label: 'Kode Posisi' },
+ { label: 'Nama Posisi' },
+ { label: 'Karyawan' },
+ { label: 'Status Kepala' },
+ { label: '' },
+ ],
+ ],
+
+ keys: ['index', 'code', 'name', 'employee', 'head', 'action'],
+
+ delKeyNames: [
+ { key: 'code', label: 'Kode' },
+ { key: 'name', label: 'Nama' },
+ ],
+
+ parses: {
+ employee: (rec: unknown): unknown => {
+ const recX = rec as UnitPosition
+ const fullName = [recX.employee?.person.frontTitle, recX.employee?.person.name, recX.employee?.person.endTitle]
+ .filter(Boolean)
+ .join(' ')
+ .trim()
+
+ return fullName || '-'
+ },
+ head: (rec: unknown): unknown => {
+ const recX = rec as SmallDetailDto
+ return recX.headStatus ? 'Ya' : 'Tidak'
+ },
+ },
+
+ components: {
+ action(rec, idx) {
+ const res: RecComponent = {
+ idx,
+ rec: rec as object,
+ component: action,
+ props: {
+ size: 'sm',
+ },
+ }
+ return res
+ },
+ },
+
+ htmls: {},
+}
diff --git a/app/components/app/subspecialist/detail/list.vue b/app/components/app/subspecialist/detail/list.vue
new file mode 100644
index 00000000..11431e25
--- /dev/null
+++ b/app/components/app/subspecialist/detail/list.vue
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
diff --git a/app/components/app/subspecialist/list-cfg.ts b/app/components/app/subspecialist/list-cfg.ts
index 7e9e7b79..99d34169 100644
--- a/app/components/app/subspecialist/list-cfg.ts
+++ b/app/components/app/subspecialist/list-cfg.ts
@@ -8,16 +8,9 @@ const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dr
export const config: Config = {
cols: [{}, {}, {}, { width: 50 }],
- headers: [
- [
- { label: 'Kode' },
- { label: 'Nama' },
- { label: 'Specialis' },
- { label: '' },
- ],
- ],
+ headers: [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Specialis' }, { label: '' }]],
- keys: ['code', 'name', 'specialist', 'action'],
+ keys: ['code', 'name', 'specialist.name', 'action'],
delKeyNames: [
{ key: 'code', label: 'Kode' },
diff --git a/app/components/app/subspecialist/list.vue b/app/components/app/subspecialist/list.vue
index 1be60a60..2f7908cb 100644
--- a/app/components/app/subspecialist/list.vue
+++ b/app/components/app/subspecialist/list.vue
@@ -31,6 +31,9 @@ function handlePageChange(page: number) {
:rows="data"
:skeleton-size="paginationMeta?.pageSize"
/>
-
+
diff --git a/app/components/app/unit-position/entry-detail.vue b/app/components/app/unit-position/entry-detail.vue
new file mode 100644
index 00000000..fb84e41a
--- /dev/null
+++ b/app/components/app/unit-position/entry-detail.vue
@@ -0,0 +1,192 @@
+
+
+
+
+
diff --git a/app/components/app/unit-position/entry-form.vue b/app/components/app/unit-position/entry-form.vue
new file mode 100644
index 00000000..b6ab8609
--- /dev/null
+++ b/app/components/app/unit-position/entry-form.vue
@@ -0,0 +1,206 @@
+
+
+
+
+
diff --git a/app/components/app/unit-position/list.cfg.ts b/app/components/app/unit-position/list.cfg.ts
new file mode 100644
index 00000000..fb5e319b
--- /dev/null
+++ b/app/components/app/unit-position/list.cfg.ts
@@ -0,0 +1,61 @@
+import type { Config, RecComponent } from '~/components/pub/my-ui/data-table'
+import { defineAsyncComponent } from 'vue'
+import type { UnitPosition } from '~/models/unit-position'
+
+type SmallDetailDto = any
+
+const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-ud.vue'))
+
+export const config: Config = {
+ cols: [{}, {}, {}, {}, {}, { width: 50 }],
+
+ headers: [
+ [
+ { label: 'Kode Posisi' },
+ { label: 'Nama Posisi' },
+ { label: 'Nama Unit ' },
+ { label: 'Karyawan' },
+ { label: 'Status Kepala' },
+ { label: '' },
+ ],
+ ],
+
+ keys: ['code', 'name', 'unit.name', 'employee', 'head', 'action'],
+
+ delKeyNames: [
+ { key: 'code', label: 'Kode' },
+ { key: 'name', label: 'Nama' },
+ ],
+
+ parses: {
+ employee: (rec: unknown): unknown => {
+ const recX = rec as UnitPosition
+ const fullName = [recX.employee?.person.frontTitle, recX.employee?.person.name, recX.employee?.person.endTitle]
+ .filter(Boolean)
+ .join(' ')
+ .trim()
+
+ return fullName || '-'
+ },
+ head: (rec: unknown): unknown => {
+ const recX = rec as SmallDetailDto
+ return recX.headStatus ? 'Ya' : 'Tidak'
+ },
+ },
+
+ components: {
+ action(rec, idx) {
+ const res: RecComponent = {
+ idx,
+ rec: rec as object,
+ component: action,
+ props: {
+ size: 'sm',
+ },
+ }
+ return res
+ },
+ },
+
+ htmls: {},
+}
diff --git a/app/components/app/unit-position/list.vue b/app/components/app/unit-position/list.vue
new file mode 100644
index 00000000..6ad7dd81
--- /dev/null
+++ b/app/components/app/unit-position/list.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
diff --git a/app/components/app/unit/detail/index.vue b/app/components/app/unit/detail/index.vue
new file mode 100644
index 00000000..9b38aa2b
--- /dev/null
+++ b/app/components/app/unit/detail/index.vue
@@ -0,0 +1,35 @@
+
+
+
+ {{ unit.code || '-' }}
+ {{ unit.name || '-' }}
+
+
+
+
diff --git a/app/components/app/unit/detail/list.cfg.ts b/app/components/app/unit/detail/list.cfg.ts
new file mode 100644
index 00000000..8faf9e61
--- /dev/null
+++ b/app/components/app/unit/detail/list.cfg.ts
@@ -0,0 +1,61 @@
+import type { Config, RecComponent } from '~/components/pub/my-ui/data-table'
+import { defineAsyncComponent } from 'vue'
+import type { UnitPosition } from '~/models/unit-position'
+
+type SmallDetailDto = any
+
+const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-ud.vue'))
+
+export const config: Config = {
+ cols: [{}, {}, {}, {}, {}, { width: 50 }],
+
+ headers: [
+ [
+ { label: '#' },
+ { label: 'Kode Posisi' },
+ { label: 'Nama Posisi' },
+ { label: 'Karyawan' },
+ { label: 'Status Kepala' },
+ { label: '' },
+ ],
+ ],
+
+ keys: ['index', 'code', 'name', 'employee', 'head', 'action'],
+
+ delKeyNames: [
+ { key: 'code', label: 'Kode' },
+ { key: 'name', label: 'Nama' },
+ ],
+
+ parses: {
+ employee: (rec: unknown): unknown => {
+ const recX = rec as UnitPosition
+ const fullName = [recX.employee?.person.frontTitle, recX.employee?.person.name, recX.employee?.person.endTitle]
+ .filter(Boolean)
+ .join(' ')
+ .trim()
+
+ return fullName || '-'
+ },
+ head: (rec: unknown): unknown => {
+ const recX = rec as SmallDetailDto
+ return recX.headStatus ? 'Ya' : 'Tidak'
+ },
+ },
+
+ components: {
+ action(rec, idx) {
+ const res: RecComponent = {
+ idx,
+ rec: rec as object,
+ component: action,
+ props: {
+ size: 'sm',
+ },
+ }
+ return res
+ },
+ },
+
+ htmls: {},
+}
diff --git a/app/components/app/unit/detail/list.vue b/app/components/app/unit/detail/list.vue
new file mode 100644
index 00000000..f878d14c
--- /dev/null
+++ b/app/components/app/unit/detail/list.vue
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
diff --git a/app/components/content/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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+
+
+
+
+
+
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.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/content/cp-lab-order/list.vue b/app/components/content/cp-lab-order/list.vue
new file mode 100644
index 00000000..73b9361c
--- /dev/null
+++ b/app/components/content/cp-lab-order/list.vue
@@ -0,0 +1,169 @@
+
+
+
+
+
+
+
+ handleActionRemove(recId, getMyList, toast)"
+ @cancel=""
+ />
+
diff --git a/app/components/content/cp-lab-order/main.vue b/app/components/content/cp-lab-order/main.vue
new file mode 100644
index 00000000..033d093f
--- /dev/null
+++ b/app/components/content/cp-lab-order/main.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/app/components/content/division-position/list.vue b/app/components/content/division-position/list.vue
index 019e64a9..4fa8605d 100644
--- a/app/components/content/division-position/list.vue
+++ b/app/components/content/division-position/list.vue
@@ -54,6 +54,7 @@ const {
sort: 'createdAt:asc',
'page-number': params['page-number'] || 0,
'page-size': params['page-size'] || 10,
+ includes: 'division,Employee.Person',
})
return { success: result.success || false, body: result.body || {} }
},
@@ -61,7 +62,7 @@ const {
})
const headerPrep: HeaderPrep = {
- title: 'Divisi',
+ title: 'Divisi - Posisi',
icon: 'i-lucide-box',
refSearchNav: {
placeholder: 'Cari (min. 3 karakter)...',
@@ -105,12 +106,12 @@ watch([recId, recAction], () => {
switch (recAction.value) {
case ActionEvents.showDetail:
getCurrentDivisionDetail(recId.value)
- title.value = 'Detail Divisi'
+ title.value = 'Detail Divisi Position'
isReadonly.value = true
break
case ActionEvents.showEdit:
getCurrentDivisionDetail(recId.value)
- title.value = 'Edit Divisi'
+ title.value = 'Edit Divisi Position'
isReadonly.value = false
break
case ActionEvents.showConfirmDelete:
@@ -120,9 +121,19 @@ watch([recId, recAction], () => {
})
onMounted(async () => {
- divisions.value = await getDivisionLabelList({ sort: 'createdAt:asc', 'page-size': 100 })
- employees.value = await getEmployeeLabelList({ sort: 'createdAt:asc', 'page-size': 100 })
- await getDivisionList()
+ try {
+ divisions.value = await getDivisionLabelList({ sort: 'createdAt:asc', 'page-size': 100 })
+ employees.value = await getEmployeeLabelList({ sort: 'createdAt:asc', 'page-size': 100, includes: 'person' })
+ await getDivisionList()
+ } catch (err) {
+ console.log(err)
+ // show toast
+ toast({
+ title: 'Terjadi Kesalahan',
+ description: 'Terjadi kesalahan saat memuat data',
+ variant: 'destructive',
+ })
+ }
})
@@ -142,7 +153,7 @@ onMounted(async () => {
+
+
+
+
+
+
+ ID:
+ {{ record?.id }}
+
+
+ Pasien:
+ {{ record.patient.person.name }}
+
+
+ Kelas:
+ {{ record.class_code }}
+
+
+
+
diff --git a/app/components/content/encounter/process.vue b/app/components/content/encounter/process.vue
index aba72c94..3e07ee80 100644
--- a/app/components/content/encounter/process.vue
+++ b/app/components/content/encounter/process.vue
@@ -14,9 +14,12 @@ 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 GeneralConsentList from '~/components/content/general-consent/entry.vue'
+import ControlLetterList from '~/components/content/control-letter/list.vue'
const route = useRoute()
const router = useRouter()
@@ -61,17 +64,17 @@ const tabs: TabItem[] = [
{ value: 'education-assessment', label: 'Asesmen Kebutuhan Edukasi' },
{ value: 'consent', label: 'General Consent', component: GeneralConsentList, props: { encounter: data } },
{ 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/general-consent/form.vue b/app/components/content/general-consent/form.vue
index 146586ea..889e5799 100644
--- a/app/components/content/general-consent/form.vue
+++ b/app/components/content/general-consent/form.vue
@@ -22,47 +22,14 @@ const selectedFungsional = ref
(null)
const schema = FunctionSoapiSchema
const payload = ref({
encounter_id: 0,
- time: '',
- typeCode: 'function',
value: '',
})
const model = ref({
- 'prim-compl': '',
- 'past-disease': '',
- 'current-disease': '',
- gcs: '',
- 'respiratory-rate': '',
- 'respiratory-rate-type': '',
- pulse: '',
- 'pulse-type': '',
- 'right-arm-bp': '',
- 'left-arm-bp': '',
- 'axillary-temp': '',
- 'rektal-temp': '',
- skin: '',
- head: '',
- ear: '',
- nose: '',
- 'oral-cavity': '',
- eye: '',
- 'other-body-part': '',
- neck: '',
- thyroid: '',
- thorax: '',
- heart: '',
- lung: '',
- abdomen: '',
- heart2: '',
- lien: '',
- back: '',
- extremity: '',
- gender: '',
- rectum: '',
- 'system-syaraf': '',
- 'nervous-system': '',
- 'cardio-respiratory': '',
- imaging: '',
- laboratory: '',
+ relatives: [],
+ responsible: '',
+ informant: '',
+ witness1: '',
+ witness2: '',
})
const isLoading = reactive({
@@ -101,7 +68,7 @@ function handleClick(type: string) {
isOpenDiagnose.value = true
}
}
-const entryRehabRef = ref()
+const entryGeneralConsent = ref()
async function actionHandler(type: string) {
if (type === 'back') {
backToList()
@@ -112,24 +79,14 @@ async function actionHandler(type: string) {
isOpenDiagnose.value = true
return
}
- const result = await entryRehabRef.value?.validate()
+ const result = await entryGeneralConsent.value?.validate()
if (result?.valid) {
- if (
- selectedProcedure.value?.length > 0 ||
- selectedDiagnose.value?.length > 0 ||
- selectedFungsional.value?.length > 0
- ) {
- result.data.procedure = selectedProcedure.value || []
- result.data.diagnose = selectedDiagnose.value || []
- result.data.fungsional = selectedFungsional.value || []
- }
console.log('data', result.data)
handleActionSave(
{
...payload.value,
value: JSON.stringify(result.data),
encounter_id: +route.params.id,
- time: new Date().toISOString(),
},
{},
toast,
@@ -146,9 +103,9 @@ const icdPreview = ref({
function actionDialogHandler(type: string) {
if (type === 'submit') {
- icdPreview.value.procedures = selectedProcedure.value || []
- icdPreview.value.diagnoses = selectedDiagnose.value || []
- icdPreview.value.fungsional = selectedFungsional.value || []
+ // icdPreview.value.procedures = selectedProcedure.value || []
+ // icdPreview.value.diagnoses = selectedDiagnose.value || []
+ // icdPreview.value.fungsional = selectedFungsional.value || []
}
isOpenProcedure.value = false
isOpenDiagnose.value = false
@@ -159,10 +116,9 @@ provide('icdPreview', icdPreview)
diff --git a/app/components/content/general-consent/list.vue b/app/components/content/general-consent/list.vue
index f7f53972..588ff849 100644
--- a/app/components/content/general-consent/list.vue
+++ b/app/components/content/general-consent/list.vue
@@ -31,8 +31,7 @@ import {
} from '~/handlers/consultation.handler'
// Services
-import { getList, getDetail } from '~/services/consultation.service'
-import { getValueLabelList } from '~/services/unit.service'
+import { getList, getDetail } from '~/services/general-consent.service'
// Models
import type { Encounter } from '~/models/encounter'
@@ -61,7 +60,7 @@ const {
fetchData: getMyList,
} = usePaginatedList({
fetchFn: async ({ page, search }) => {
- const result = await getList({ 'encounter-id': props.encounter.id, includes: 'encounter,dstUnit', search, page })
+ const result = await getList({ 'encounter-id': props.encounter.id, includes: '', search, page })
if (result.success) {
data.value = result.body.data
}
@@ -90,15 +89,6 @@ const headerPrep: HeaderPrep = {
onClick: () => {
goToEntry()
emits('add')
- // recItem.value = {
- // encounter_id: encounterId.value,
- // date: today.toISOString().slice(0, 10),
- // unit_id: 0,
- // problem: '',
- // }
- // recId.value = 0
- // isFormEntryDialogOpen.value = true
- // isReadonly.value = false
},
},
}
@@ -127,11 +117,6 @@ watch([recId, recAction], () => {
title.value = 'Detail Konsultasi'
isReadonly.value = true
break
- case ActionEvents.showEdit:
- getMyDetail(recId.value)
- title.value = 'Edit Konsultasi'
- isReadonly.value = false
- break
case ActionEvents.showConfirmDelete:
isRecordConfirmationOpen.value = true
break
@@ -140,7 +125,6 @@ watch([recId, recAction], () => {
onMounted(async () => {
await getMyList()
- units.value = await getValueLabelList()
})
diff --git a/app/components/content/installation-position/list.vue b/app/components/content/installation-position/list.vue
new file mode 100644
index 00000000..ea60ee04
--- /dev/null
+++ b/app/components/content/installation-position/list.vue
@@ -0,0 +1,208 @@
+
+
+
+
+
+
+
+ {
+ onResetState()
+ isFormEntryDialogOpen = value
+ }
+ "
+ >
+ , resetForm: () => void) => {
+ if (recId > 0) {
+ handleActionEdit(recId, values, getInstallationPositionList, resetForm, toast)
+ return
+ }
+ handleActionSave(values, getInstallationPositionList, resetForm, toast)
+ }
+ "
+ @cancel="handleCancelForm"
+ />
+
+
+
+ handleActionRemove(recId, getInstallationPositionList, toast)"
+ @cancel=""
+ >
+
+
+
+ ID:
+ {{ record?.id }}
+
+
+ Nama:
+ {{ record.name }}
+
+
+ Kode:
+ {{ record.code }}
+
+
+
+
+
diff --git a/app/components/content/installation/detail.vue b/app/components/content/installation/detail.vue
new file mode 100644
index 00000000..0f12ad8c
--- /dev/null
+++ b/app/components/content/installation/detail.vue
@@ -0,0 +1,235 @@
+
+
+
+
+
+
+
+
+
+
+ {
+ onResetState()
+ isFormEntryDialogOpen = value
+ }
+ "
+ >
+ , resetForm: () => void) => {
+ console.log(values)
+ if (recId > 0) {
+ handleActionEdit(recId, values, getInstallationPositionList, onResetState, toast)
+ return
+ }
+ handleActionSave(values, getInstallationPositionList, onResetState, toast)
+ }
+ "
+ @cancel="handleCancelForm"
+ />
+
+ handleActionRemove(recId, getInstallationPositionList, toast)"
+ @cancel=""
+ >
+
+
+
+ {{ field.label }}:
+ {{ record[field.key] }}
+
+
+
+
+
diff --git a/app/components/content/installation/entry.ts b/app/components/content/installation/entry.ts
deleted file mode 100644
index c003a029..00000000
--- a/app/components/content/installation/entry.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import * as z from 'zod'
-
-export const installationConf = {
- msg: {
- placeholder: '---pilih encounter class (fhir7)',
- },
- items: [
- { value: '1', label: 'Ambulatory', code: 'AMB' },
- { value: '2', label: 'Inpatient', code: 'IMP' },
- { value: '3', label: 'Emergency', code: 'EMER' },
- { value: '4', label: 'Observation', code: 'OBSENC' },
- { value: '5', label: 'Pre-admission', code: 'PRENC' },
- { value: '6', label: 'Short Stay', code: 'SS' },
- { value: '7', label: 'Virtual', code: 'VR' },
- { value: '8', label: 'Home Health', code: 'HH' },
- ],
-}
-
-export const schemaConf = z.object({
- name: z
- .string({
- required_error: 'Nama instalasi harus diisi',
- })
- .min(3, 'Nama instalasi minimal 3 karakter'),
-
- code: z
- .string({
- required_error: 'Kode instalasi harus diisi',
- })
- .min(3, 'Kode instalasi minimal 3 karakter'),
-
- encounterClassCode: z
- .string({
- required_error: 'Kelompok encounter class harus dipilih',
- })
- .min(1, 'Kelompok encounter class harus dipilih'),
-})
diff --git a/app/components/content/installation/list.vue b/app/components/content/installation/list.vue
index 31486097..553d7ebb 100644
--- a/app/components/content/installation/list.vue
+++ b/app/components/content/installation/list.vue
@@ -102,9 +102,23 @@ const getCurrentInstallationDetail = async (id: number | string) => {
watch([recId, recAction], () => {
switch (recAction.value) {
case ActionEvents.showDetail:
- getCurrentInstallationDetail(recId.value)
- title.value = 'Detail Instalasi'
- isReadonly.value = true
+ if (Number(recId.value) > 0) {
+ const id = Number(recId.value)
+
+ recAction.value = ''
+ recItem.value = null
+ recId.value = 0
+ isFormEntryDialogOpen.value = false
+ isReadonly.value = false
+
+ navigateTo({
+ name: 'org-src-installation-id',
+ params: {
+ id,
+ },
+ })
+ }
+
break
case ActionEvents.showEdit:
getCurrentInstallationDetail(recId.value)
diff --git a/app/components/content/prescription/entry.vue b/app/components/content/prescription/entry.vue
new file mode 100644
index 00000000..4b3fa663
--- /dev/null
+++ b/app/components/content/prescription/entry.vue
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/content/prescription/list.vue b/app/components/content/prescription/list.vue
index f8059b9d..844cb04f 100644
--- a/app/components/content/prescription/list.vue
+++ b/app/components/content/prescription/list.vue
@@ -1,37 +1,82 @@
-
+
+
-
-
-
-
-
-
-
-
+ handleActionRemove(recId, getMyList, toast)"
+ @cancel=""
+ >
+
diff --git a/app/components/content/prescription/main.vue b/app/components/content/prescription/main.vue
new file mode 100644
index 00000000..033d093f
--- /dev/null
+++ b/app/components/content/prescription/main.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/app/components/content/radiology-order/entry.vue b/app/components/content/radiology-order/entry.vue
new file mode 100644
index 00000000..4d0aa002
--- /dev/null
+++ b/app/components/content/radiology-order/entry.vue
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pickerDialogOpen = false" class="justify-center" />
+
+
diff --git a/app/components/content/radiology-order/list.vue b/app/components/content/radiology-order/list.vue
new file mode 100644
index 00000000..b2c8571d
--- /dev/null
+++ b/app/components/content/radiology-order/list.vue
@@ -0,0 +1,169 @@
+
+
+
+
+
+
+
+ handleActionRemove(recId, getMyList, toast)"
+ @cancel=""
+ />
+
diff --git a/app/components/content/radiology-order/main.vue b/app/components/content/radiology-order/main.vue
new file mode 100644
index 00000000..033d093f
--- /dev/null
+++ b/app/components/content/radiology-order/main.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/app/components/content/sep/entry.vue b/app/components/content/sep/entry.vue
index 61107232..3a916c4d 100644
--- a/app/components/content/sep/entry.vue
+++ b/app/components/content/sep/entry.vue
@@ -1,113 +1,552 @@
-
- Tambah SEP
+
+ Tambah
+ SEP
-
-
+ {
+ if (value.search && value.search.length >= 3) {
+ // Use identifier search for specific searches (NIK, RM, etc.)
+ getPatientByIdentifierSearch(value.search)
+ } else {
+ // Use regular search for general searches
+ getPatientsList({ ...value, 'page-size': 10, includes: 'person' })
+ }
+ }
+ "
@save="handleSavePatient"
/>
-
-
-
+ getLetterMappers(value.admissionType, value.search)"
+ @save="handleSaveLetter"
+ />
diff --git a/app/components/content/sep/list.vue b/app/components/content/sep/list.vue
index 9a6cd8db..013b076a 100644
--- a/app/components/content/sep/list.vue
+++ b/app/components/content/sep/list.vue
@@ -1,4 +1,5 @@
-
+
-
-
+
@@ -226,9 +241,7 @@ provide('table_data_loader', isLoading)
Hapus SEP
-
- Apakah anda yakin ingin menghapus SEP dengan data:
-
+
Apakah anda yakin ingin menghapus SEP dengan data:
No. SEP : {{ sepData.no_sep }}
@@ -237,11 +250,21 @@ provide('table_data_loader', isLoading)
-
diff --git a/app/components/content/specialist-position/list.vue b/app/components/content/specialist-position/list.vue
new file mode 100644
index 00000000..1ebf697e
--- /dev/null
+++ b/app/components/content/specialist-position/list.vue
@@ -0,0 +1,203 @@
+
+
+
+
+
+ {
+ onResetState()
+ isFormEntryDialogOpen = value
+ }
+ "
+ >
+ , resetForm: () => void) => {
+ if (recId > 0) {
+ handleActionEdit(recId, values, getSpecialistList, resetForm, toast)
+ return
+ }
+ handleActionSave(values, getSpecialistList, resetForm, toast)
+ }
+ "
+ @cancel="handleCancelForm"
+ />
+
+
+ handleActionRemove(recId, getSpecialistList, toast)"
+ @cancel=""
+ >
+
+
+
+ {{ field.label }}:
+ {{ record[field.key] }}
+
+
+
+
+
diff --git a/app/components/content/specialist/detail.vue b/app/components/content/specialist/detail.vue
new file mode 100644
index 00000000..df4e79b6
--- /dev/null
+++ b/app/components/content/specialist/detail.vue
@@ -0,0 +1,236 @@
+
+
+
+
+
+
+
+
+
+
+ {
+ onResetState()
+ isFormEntryDialogOpen = value
+ }
+ "
+ >
+ , resetForm: () => void) => {
+ console.log(values)
+ if (recId > 0) {
+ handleActionEdit(recId, values, getPositionList, onResetState, toast)
+ return
+ }
+ handleActionSave(values, getPositionList, onResetState, toast)
+ }
+ "
+ @cancel="handleCancelForm"
+ />
+
+ handleActionRemove(recId, getPositionList, toast)"
+ @cancel=""
+ >
+
+
+
+ {{ field.label }}:
+ {{ record[field.key] }}
+
+
+
+
+
diff --git a/app/components/content/specialist/entry.ts b/app/components/content/specialist/entry.ts
deleted file mode 100644
index c89302c2..00000000
--- a/app/components/content/specialist/entry.ts
+++ /dev/null
@@ -1,95 +0,0 @@
-import * as z from 'zod'
-
-export const schemaConf = z.object({
- name: z
- .string({
- required_error: 'Nama spesialisasi harus diisi',
- })
- .min(3, 'Nama spesialisasi minimal 3 karakter'),
-
- code: z
- .string({
- required_error: 'Kode spesialisasi harus diisi',
- })
- .min(3, 'Kode spesialisasi minimal 3 karakter'),
-
- installationId: z
- .string({
- required_error: 'Instalasi harus dipilih',
- })
- .min(1, 'Instalasi harus dipilih'),
-
- unitId: z
- .string({
- required_error: 'Unit harus dipilih',
- })
- .min(1, 'Unit harus dipilih'),
-})
-
-// Unit mapping berdasarkan installation
-export const installationUnitMapping: Record
= {
- '1': ['1', '3', '5'],
- '2': ['2', '4', '6'],
- '3': ['7', '8', '9', '10', '11'],
-}
-
-export const unitConf = {
- msg: {
- placeholder: '---pilih unit',
- search: 'kode, nama unit',
- empty: 'unit tidak ditemukan',
- },
- items: [
- { value: '1', label: 'Instalasi Medis', code: 'MED' },
- { value: '2', label: 'Instalasi Keperawatan', code: 'NUR' },
- { value: '3', label: 'Instalasi Administrasi', code: 'ADM' },
- { value: '4', label: 'Instalasi Penunjang Non-Medis', code: 'SUP' },
- { value: '5', label: 'Instalasi Pendidikan & Pelatihan', code: 'EDU' },
- { value: '6', label: 'Instalasi Farmasi', code: 'PHA' },
- { value: '7', label: 'Instalasi Radiologi', code: 'RAD' },
- { value: '8', label: 'Instalasi Laboratorium', code: 'LAB' },
- { value: '9', label: 'Instalasi Keuangan', code: 'FIN' },
- { value: '10', label: 'Instalasi SDM', code: 'HR' },
- { value: '11', label: 'Instalasi Teknologi Informasi', code: 'ITS' },
- { value: '12', label: 'Instalasi Pemeliharaan & Sarana', code: 'MNT' },
- { value: '13', label: 'Instalasi Gizi / Catering', code: 'CAT' },
- { value: '14', label: 'Instalasi Keamanan', code: 'SEC' },
- { value: '15', label: 'Instalasi Gawat Darurat', code: 'EMR' },
- { value: '16', label: 'Instalasi Bedah Sentral', code: 'SUR' },
- { value: '17', label: 'Instalasi Rawat Jalan', code: 'OUT' },
- { value: '18', label: 'Instalasi Rawat Inap', code: 'INP' },
- { value: '19', label: 'Instalasi Rehabilitasi Medik', code: 'REB' },
- { value: '20', label: 'Instalasi Penelitian & Pengembangan', code: 'RSH' },
- ],
-}
-
-export const installationConf = {
- msg: {
- placeholder: '---pilih instalasi',
- search: 'kode, nama instalasi',
- empty: 'instalasi tidak ditemukan',
- },
- items: [
- { value: '1', label: 'Ambulatory', code: 'AMB' },
- { value: '2', label: 'Inpatient', code: 'IMP' },
- { value: '3', label: 'Emergency', code: 'EMER' },
- ],
-}
-
-// Helper function untuk filter unit berdasarkan installation
-export function getFilteredUnits(installationId: string) {
- if (!installationId || !installationUnitMapping[installationId]) {
- return []
- }
-
- const allowedUnitIds = installationUnitMapping[installationId]
- return unitConf.items.filter((unit) => allowedUnitIds.includes(unit.value))
-}
-
-// Helper function untuk membuat unit config yang ter-filter
-export function createFilteredUnitConf(installationId: string) {
- return {
- ...unitConf,
- items: getFilteredUnits(installationId),
- }
-}
diff --git a/app/components/content/specialist/list.vue b/app/components/content/specialist/list.vue
index 9bbf755f..ca293026 100644
--- a/app/components/content/specialist/list.vue
+++ b/app/components/content/specialist/list.vue
@@ -103,9 +103,23 @@ const getCurrentSpecialistDetail = async (id: number | string) => {
watch([recId, recAction], () => {
switch (recAction.value) {
case ActionEvents.showDetail:
- getCurrentSpecialistDetail(recId.value)
- title.value = 'Detail Spesialis'
- isReadonly.value = true
+ if (Number(recId.value) > 0) {
+ const id = Number(recId.value)
+
+ recAction.value = ''
+ recItem.value = null
+ recId.value = 0
+ isFormEntryDialogOpen.value = false
+ isReadonly.value = false
+
+ navigateTo({
+ name: 'org-src-specialist-id',
+ params: {
+ id,
+ },
+ })
+ }
+
break
case ActionEvents.showEdit:
getCurrentSpecialistDetail(recId.value)
diff --git a/app/components/content/subspecialist-position/list.vue b/app/components/content/subspecialist-position/list.vue
new file mode 100644
index 00000000..4c833ce2
--- /dev/null
+++ b/app/components/content/subspecialist-position/list.vue
@@ -0,0 +1,211 @@
+
+
+
+
+
+
+
+ {
+ onResetState()
+ isFormEntryDialogOpen = value
+ }
+ "
+ >
+ , resetForm: () => void) => {
+ if (recId > 0) {
+ handleActionEdit(recId, values, getSubSpecialistList, onResetState, toast)
+ return
+ }
+ handleActionSave(values, getSubSpecialistList, onResetState, toast)
+ }
+ "
+ @cancel="handleCancelForm"
+ />
+
+
+
+ handleActionRemove(recId, getSubSpecialistList, toast)"
+ @cancel=""
+ >
+
+
+
+ {{ field.label }}:
+ {{ record[field.key] }}
+
+
+
+
+
diff --git a/app/components/content/subspecialist/detail.vue b/app/components/content/subspecialist/detail.vue
new file mode 100644
index 00000000..d432eb22
--- /dev/null
+++ b/app/components/content/subspecialist/detail.vue
@@ -0,0 +1,239 @@
+
+
+
+
+
+
+
+
+
+
+ {
+ onResetState()
+ isFormEntryDialogOpen = value
+ }
+ "
+ >
+ , resetForm: () => void) => {
+ console.log(values)
+ if (recId > 0) {
+ handleActionEdit(recId, values, getPositionList, onResetState, toast)
+ return
+ }
+ handleActionSave(values, getPositionList, onResetState, toast)
+ }
+ "
+ @cancel="handleCancelForm"
+ />
+
+ handleActionRemove(recId, getPositionList, toast)"
+ @cancel=""
+ >
+
+
+
+ {{ field.label }}:
+ {{ record[field.key] }}
+
+
+
+
+
diff --git a/app/components/content/subspecialist/entry.ts b/app/components/content/subspecialist/entry.ts
deleted file mode 100644
index 5a93847d..00000000
--- a/app/components/content/subspecialist/entry.ts
+++ /dev/null
@@ -1,98 +0,0 @@
-import * as z from 'zod'
-
-export const schemaConf = z.object({
- name: z
- .string({
- required_error: 'Nama spesialisasi harus diisi',
- })
- .min(3, 'Nama spesialisasi minimal 3 karakter'),
-
- code: z
- .string({
- required_error: 'Kode spesialisasi harus diisi',
- })
- .min(3, 'Kode spesialisasi minimal 3 karakter'),
-
- installationId: z
- .string({
- required_error: 'Instalasi harus dipilih',
- })
- .min(1, 'Instalasi harus dipilih'),
-
- unitId: z
- .string({
- required_error: 'Unit harus dipilih',
- })
- .min(1, 'Unit harus dipilih'),
- specialistId: z
- .string({
- required_error: 'Specialist harus dipilih',
- })
- .min(1, 'Specialist harus dipilih'),
-})
-
-// Unit mapping berdasarkan installation
-export const installationUnitMapping: Record = {
- '1': ['1', '3'],
- '2': ['2', '3'],
- '3': ['1', '2', '3'],
-}
-
-export const unitConf = {
- msg: {
- placeholder: '---pilih unit',
- search: 'kode, nama unit',
- empty: 'unit tidak ditemukan',
- },
- items: [
- { value: '1', label: 'Instalasi Medis', code: 'MED' },
- { value: '2', label: 'Instalasi Keperawatan', code: 'NUR' },
- { value: '3', label: 'Instalasi Administrasi', code: 'ADM' },
- ],
-}
-
-export const specialistConf = {
- msg: {
- placeholder: '---pilih specialist',
- search: 'kode, nama specialist',
- empty: 'specialist tidak ditemukan',
- },
- items: [
- { value: '1', label: 'Spesialis Jantung', code: 'CARD' },
- { value: '2', label: 'Spesialis Mata', code: 'OPHT' },
- { value: '3', label: 'Spesialis Bedah', code: 'SURG' },
- { value: '4', label: 'Spesialis Anak', code: 'PEDI' },
- { value: '5', label: 'Spesialis Kandungan', code: 'OBGY' },
- ],
-}
-
-export const installationConf = {
- msg: {
- placeholder: '---pilih instalasi',
- search: 'kode, nama instalasi',
- empty: 'instalasi tidak ditemukan',
- },
- items: [
- { value: '1', label: 'Ambulatory', code: 'AMB' },
- { value: '2', label: 'Inpatient', code: 'IMP' },
- { value: '3', label: 'Emergency', code: 'EMER' },
- ],
-}
-
-// Helper function untuk filter unit berdasarkan installation
-export function getFilteredUnits(installationId: string) {
- if (!installationId || !installationUnitMapping[installationId]) {
- return []
- }
-
- const allowedUnitIds = installationUnitMapping[installationId]
- return unitConf.items.filter((unit) => allowedUnitIds.includes(unit.value))
-}
-
-// Helper function untuk membuat unit config yang ter-filter
-export function createFilteredUnitConf(installationId: string) {
- return {
- ...unitConf,
- items: getFilteredUnits(installationId),
- }
-}
diff --git a/app/components/content/subspecialist/list.vue b/app/components/content/subspecialist/list.vue
index e2c6db52..bb1b63f5 100644
--- a/app/components/content/subspecialist/list.vue
+++ b/app/components/content/subspecialist/list.vue
@@ -103,9 +103,23 @@ const getCurrentSubSpecialistDetail = async (id: number | string) => {
watch([recId, recAction], () => {
switch (recAction.value) {
case ActionEvents.showDetail:
- getCurrentSubSpecialistDetail(recId.value)
- title.value = 'Detail Sub Spesialis'
- isReadonly.value = true
+ if (Number(recId.value) > 0) {
+ const id = Number(recId.value)
+
+ recAction.value = ''
+ recItem.value = null
+ recId.value = 0
+ isFormEntryDialogOpen.value = false
+ isReadonly.value = false
+
+ navigateTo({
+ name: 'org-src-subspecialist-id',
+ params: {
+ id,
+ },
+ })
+ }
+
break
case ActionEvents.showEdit:
getCurrentSubSpecialistDetail(recId.value)
diff --git a/app/components/content/unit-position/list.vue b/app/components/content/unit-position/list.vue
new file mode 100644
index 00000000..55ab3f29
--- /dev/null
+++ b/app/components/content/unit-position/list.vue
@@ -0,0 +1,206 @@
+
+
+
+
+
+
+
+ {
+ onResetState()
+ isFormEntryDialogOpen = value
+ }
+ "
+ >
+ , resetForm: () => void) => {
+ if (recId > 0) {
+ handleActionEdit(recId, values, getListUnit, resetForm, toast)
+ return
+ }
+ handleActionSave(values, getListUnit, resetForm, toast)
+ }
+ "
+ @cancel="handleCancelForm"
+ />
+
+
+ handleActionRemove(recId, getListUnit, toast)"
+ @cancel=""
+ >
+
+
+
+ {{ field.label }}:
+ {{ record[field.key] }}
+
+
+
+
+
diff --git a/app/components/content/unit/detail.vue b/app/components/content/unit/detail.vue
new file mode 100644
index 00000000..6c51624f
--- /dev/null
+++ b/app/components/content/unit/detail.vue
@@ -0,0 +1,234 @@
+
+
+
+
+
+
+
+
+
+
+ {
+ onResetState()
+ isFormEntryDialogOpen = value
+ }
+ "
+ >
+ , resetForm: () => void) => {
+ console.log(values)
+ if (recId > 0) {
+ handleActionEdit(recId, values, getPositionList, onResetState, toast)
+ return
+ }
+ handleActionSave(values, getPositionList, onResetState, toast)
+ }
+ "
+ @cancel="handleCancelForm"
+ />
+
+ handleActionRemove(recId, getPositionList, toast)"
+ @cancel=""
+ >
+
+
+
+ {{ field.label }}:
+ {{ record[field.key] }}
+
+
+
+
+
diff --git a/app/components/content/unit/entry.ts b/app/components/content/unit/entry.ts
deleted file mode 100644
index bf85a0ed..00000000
--- a/app/components/content/unit/entry.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import * as z from 'zod'
-
-export const unitConf = {
- msg: {
- placeholder: '--- pilih instalasi',
- search: 'kode, nama instalasi',
- empty: 'instalasi tidak ditemukan',
- },
- items: [
- { value: '1', label: 'Instalasi Medis', code: 'MED' },
- { value: '2', label: 'Instalasi Keperawatan', code: 'NUR' },
- { value: '3', label: 'Instalasi Administrasi', code: 'ADM' },
- { value: '4', label: 'Instalasi Penunjang Non-Medis', code: 'SUP' },
- { value: '5', label: 'Instalasi Pendidikan & Pelatihan', code: 'EDU' },
- { value: '6', label: 'Instalasi Farmasi', code: 'PHA' },
- { value: '7', label: 'Instalasi Radiologi', code: 'RAD' },
- { value: '8', label: 'Instalasi Laboratorium', code: 'LAB' },
- { value: '9', label: 'Instalasi Keuangan', code: 'FIN' },
- { value: '10', label: 'Instalasi SDM', code: 'HR' },
- { value: '11', label: 'Instalasi Teknologi Informasi', code: 'ITS' },
- { value: '12', label: 'Instalasi Pemeliharaan & Sarana', code: 'MNT' },
- { value: '13', label: 'Instalasi Gizi / Catering', code: 'CAT' },
- { value: '14', label: 'Instalasi Keamanan', code: 'SEC' },
- { value: '15', label: 'Instalasi Gawat Darurat', code: 'EMR' },
- { value: '16', label: 'Instalasi Bedah Sentral', code: 'SUR' },
- { value: '17', label: 'Instalasi Rawat Jalan', code: 'OUT' },
- { value: '18', label: 'Instalasi Rawat Inap', code: 'INP' },
- { value: '19', label: 'Instalasi Rehabilitasi Medik', code: 'REB' },
- { value: '20', label: 'Instalasi Penelitian & Pengembangan', code: 'RSH' },
- ],
-}
-
-export const schemaConf = z.object({
- name: z
- .string({
- required_error: 'Nama unit harus diisi',
- })
- .min(1, 'Nama unit harus diisi'),
-
- code: z
- .string({
- required_error: 'Kode unit harus diisi',
- })
- .min(1, 'Kode unit harus diisi'),
- parentId: z.preprocess(
- (input: unknown) => {
- if (typeof input === 'string') {
- // Handle empty string case
- if (input.trim() === '') {
- return 0
- }
- return Number(input)
- }
-
- return input
- },
- z
- .number({
- required_error: 'Instalasi induk harus dipilih',
- })
- .refine((num) => num > 0, 'Instalasi induk harus dipilih'),
- ),
-})
diff --git a/app/components/content/unit/list.vue b/app/components/content/unit/list.vue
index 03edd231..34b647ef 100644
--- a/app/components/content/unit/list.vue
+++ b/app/components/content/unit/list.vue
@@ -103,9 +103,23 @@ const getCurrentUnitDetail = async (id: number | string) => {
watch([recId, recAction], () => {
switch (recAction.value) {
case ActionEvents.showDetail:
- getCurrentUnitDetail(recId.value)
- title.value = 'Detail Unit'
- isReadonly.value = true
+ if (Number(recId.value) > 0) {
+ const id = Number(recId.value)
+
+ recAction.value = ''
+ recItem.value = null
+ recId.value = 0
+ isFormEntryDialogOpen.value = false
+ isReadonly.value = false
+
+ navigateTo({
+ name: 'org-src-unit-id',
+ params: {
+ id,
+ },
+ })
+ }
+
break
case ActionEvents.showEdit:
getCurrentUnitDetail(recId.value)
diff --git a/app/components/layout/AppSidebar.vue b/app/components/layout/AppSidebar.vue
index 4f51e42c..a14b2137 100644
--- a/app/components/layout/AppSidebar.vue
+++ b/app/components/layout/AppSidebar.vue
@@ -1,5 +1,12 @@
diff --git a/app/components/layout/SidebarNavFooter.vue b/app/components/layout/SidebarNavFooter.vue
index 68d8d9a2..2c1e942c 100644
--- a/app/components/layout/SidebarNavFooter.vue
+++ b/app/components/layout/SidebarNavFooter.vue
@@ -10,8 +10,8 @@ import { useSidebar } from '~/components/pub/ui/sidebar'
// }>()
const { isMobile } = useSidebar()
-const { logout } = useUserStore()
-const userStore = useUserStore().user
+const { user, logout, setActiveRole, getActiveRole } = useUserStore()
+// const userStore = useUserStore().user
function handleLogout() {
navigateTo('/auth/login')
@@ -32,19 +32,19 @@ const showModalTheme = ref(false)
class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
>
-
+
{{
- userStore?.user_name
+ user.user_name
?.split(' ')
- .map((n) => n[0])
+ .map((n: string) => n[0])
.join('') || ''
}}
- {{ userStore?.user_name || '' }}
- {{ userStore?.user_email || '' }}
+ {{ user.user_name || '' }}
+ {{ user.user_email || '' }}
@@ -52,35 +52,40 @@ const showModalTheme = ref(false)
diff --git a/app/components/pub/my-ui/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/combobox.vue b/app/components/pub/my-ui/combobox/combobox.vue
index 23505393..713edd57 100644
--- a/app/components/pub/my-ui/combobox/combobox.vue
+++ b/app/components/pub/my-ui/combobox/combobox.vue
@@ -16,22 +16,23 @@ const props = defineProps<{
const emit = defineEmits<{
'update:modelValue': [value: string]
+ 'update:searchText': [value: string]
}>()
const open = ref(false)
-
+const searchText = ref('')
+const debouncedSearchText = refDebounced(searchText, 500) // 500ms debounce
const selectedItem = computed(() => props.items.find((item) => item.value === props.modelValue))
const displayText = computed(() => {
- console.log(selectedItem)
if (selectedItem.value?.label) {
return selectedItem.value.label
}
return props.placeholder || 'Pilih item'
})
-watch(props, () => {
- console.log(props.modelValue)
+watch(debouncedSearchText, (newValue) => {
+ emit('update:searchText', newValue)
})
const searchableItems = computed(() => {
@@ -106,6 +107,11 @@ function onSelect(item: Item) {
class="h-9 border-0 border-b border-gray-200 bg-white text-black focus:ring-0 dark:border-gray-700 dark:bg-gray-800 dark:text-white"
:placeholder="searchPlaceholder || 'Cari...'"
:aria-label="`Cari ${displayText}`"
+ @input="
+ (evt: any) => {
+ searchText = evt?.target?.value || ''
+ }
+ "
/>
{{ emptyMessage || 'Item tidak ditemukan.' }}
diff --git a/app/components/pub/my-ui/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..928d7827 100644
--- a/app/components/pub/my-ui/confirmation/confirmation.vue
+++ b/app/components/pub/my-ui/confirmation/confirmation.vue
@@ -8,6 +8,8 @@ interface ConfirmationProps {
message?: string
confirmText?: string
cancelText?: string
+ noTrueSlot?: boolean
+ skipClosingMessage?: boolean
variant?: 'default' | 'destructive' | 'warning'
size?: 'sm' | 'md' | 'lg' | 'xl'
}
@@ -72,19 +74,21 @@ function handleCancel() {
-
+
-
- {{ message }}
-
+ {{ message }} {{ !noTrueSlot ? ' dengan informasi sebagai berikut:' : '.' }}
-
+
+
+ Lanjutkan Proses?
+
+
diff --git a/app/components/pub/my-ui/confirmation/record-confirmation.vue b/app/components/pub/my-ui/confirmation/record-confirmation.vue
index cff54b2b..87249635 100644
--- a/app/components/pub/my-ui/confirmation/record-confirmation.vue
+++ b/app/components/pub/my-ui/confirmation/record-confirmation.vue
@@ -46,31 +46,31 @@ const actionConfig = computed(() => {
const configs = {
delete: {
title: 'Hapus Data',
- message: 'Apakah Anda yakin ingin menghapus data ini? Tindakan ini tidak dapat dibatalkan.',
+ message: 'Akan dilakukan penghapusan data',
confirmText: 'Hapus',
variant: 'destructive' as const,
},
deactivate: {
title: 'Nonaktifkan Data',
- message: 'Apakah Anda yakin ingin menonaktifkan data ini?',
+ message: 'Akan dilakukan peng-nonaktifkan data',
confirmText: 'Nonaktifkan',
variant: 'warning' as const,
},
activate: {
title: 'Aktifkan Data',
- message: 'Apakah Anda yakin ingin mengaktifkan data ini?',
+ message: 'Akan dilakukan pengaktifkan data',
confirmText: 'Aktifkan',
variant: 'default' as const,
},
archive: {
title: 'Arsipkan Data',
- message: 'Apakah Anda yakin ingin mengarsipkan data ini?',
+ message: 'Akan dilakukan pengarsipan data',
confirmText: 'Arsipkan',
variant: 'warning' as const,
},
restore: {
title: 'Pulihkan Data',
- message: 'Apakah Anda yakin ingin memulihkan data ini?',
+ message: 'Akan dilakukan pemulihan data',
confirmText: 'Pulihkan',
variant: 'default' as const,
},
@@ -107,6 +107,8 @@ const finalCancelText = computed(() => {
function handleConfirm() {
if (props.record) {
emit('confirm', props.record, props.action)
+ } else {
+ emit('confirm', { id: 0 }, 'confirmed')
}
emit('update:open', false)
}
@@ -119,11 +121,13 @@ 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/dropdown-action-dsd.vue b/app/components/pub/my-ui/data/dropdown-action-dsd.vue
new file mode 100644
index 00000000..c2eca763
--- /dev/null
+++ b/app/components/pub/my-ui/data/dropdown-action-dsd.vue
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
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 71979c7c..dfcf1ada 100644
--- a/app/components/pub/my-ui/data/dropdown-action-dud.vue
+++ b/app/components/pub/my-ui/data/dropdown-action-dud.vue
@@ -2,9 +2,14 @@
import type { LinkItem, ListItemDto } from './types'
import { ActionEvents } from './types'
-const props = defineProps<{
+interface Props {
rec: ListItemDto
-}>()
+ size?: 'default' | 'sm' | 'lg'
+}
+
+const props = withDefaults(defineProps(), {
+ size: 'lg',
+})
const recId = inject[>('rec_id')!
const recAction = inject][>('rec_action')!
@@ -58,7 +63,7 @@ function del() {
]
diff --git a/app/components/pub/my-ui/modal/dialog.vue b/app/components/pub/my-ui/modal/dialog.vue
index 974013a2..d771924f 100644
--- a/app/components/pub/my-ui/modal/dialog.vue
+++ b/app/components/pub/my-ui/modal/dialog.vue
@@ -52,8 +52,8 @@ const isOpen = computed({
>
-
-
+
+
{{ props.title }}
@@ -61,7 +61,7 @@ const isOpen = computed({
{{ props.description }}
-
+
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 @@
+
+
+
+
+
+ Back
+
+
+
diff --git a/app/components/pub/my-ui/nav-header/filter-dialog.vue b/app/components/pub/my-ui/nav-header/filter-dialog.vue
new file mode 100644
index 00000000..c0d5b854
--- /dev/null
+++ b/app/components/pub/my-ui/nav-header/filter-dialog.vue
@@ -0,0 +1,85 @@
+
+
+
+
+
diff --git a/app/components/pub/my-ui/nav-header/filter.vue b/app/components/pub/my-ui/nav-header/filter.vue
index 01b1ab55..74f6d8dc 100644
--- a/app/components/pub/my-ui/nav-header/filter.vue
+++ b/app/components/pub/my-ui/nav-header/filter.vue
@@ -5,11 +5,13 @@ import type { Ref } from 'vue'
import type { DateRange } from 'radix-vue'
import { CalendarDate, DateFormatter, getLocalTimeZone } from '@internationalized/date'
import { cn } from '~/lib/utils'
-import type { HeaderPrep, RefSearchNav } from '~/components/pub/my-ui/data/types'
+import type { HeaderPrep, RefExportNav, RefSearchNav } from '~/components/pub/my-ui/data/types'
const props = defineProps<{
prep: HeaderPrep
refSearchNav?: RefSearchNav
+ enableExport?: boolean
+ refExportNav?: RefExportNav
}>()
// function emitSearchNavClick() {
@@ -34,9 +36,18 @@ const df = new DateFormatter('en-US', {
dateStyle: 'medium',
})
+// Get current date
+const today = new Date()
+const todayCalendar = new CalendarDate(today.getFullYear(), today.getMonth() + 1, today.getDate())
+
+// Get date 1 month ago
+const oneMonthAgo = new Date(today)
+oneMonthAgo.setMonth(today.getMonth() - 1)
+const oneMonthAgoCalendar = new CalendarDate(oneMonthAgo.getFullYear(), oneMonthAgo.getMonth() + 1, oneMonthAgo.getDate())
+
const value = ref({
- start: new CalendarDate(2022, 1, 20),
- end: new CalendarDate(2022, 1, 20).add({ days: 20 }),
+ start: oneMonthAgoCalendar,
+ end: todayCalendar,
}) as Ref
function onFilterClick() {
@@ -48,7 +59,7 @@ function onFilterClick() {
-
+
@@ -88,6 +99,30 @@ function onFilterClick() {
Filter
+
+
+
+
+
+ Ekspor
+
+
+
+
+ Ekspor PDF
+
+
+ Ekspor CSV
+
+
+ Ekspor Excel
+
+
+
+
diff --git a/app/components/pub/my-ui/nav-header/prep.vue b/app/components/pub/my-ui/nav-header/prep.vue
index 63535847..7aa5e4f2 100644
--- a/app/components/pub/my-ui/nav-header/prep.vue
+++ b/app/components/pub/my-ui/nav-header/prep.vue
@@ -30,15 +30,24 @@ function btnClick() {
- {{ props.prep.title }}
+ {{ prep.title }}
+
+
+
+
+
()
const emit = defineEmits<{
@@ -17,8 +21,10 @@ function handlePageChange(page: number) {
diff --git a/app/components/pub/my-ui/pagination/pagination.vue b/app/components/pub/my-ui/pagination/pagination.vue
index 4ba0da5f..9b1618c3 100644
--- a/app/components/pub/my-ui/pagination/pagination.vue
+++ b/app/components/pub/my-ui/pagination/pagination.vue
@@ -15,11 +15,13 @@ interface Props {
paginationMeta: PaginationMeta
onPageChange?: (page: number) => void
showInfo?: boolean
+ showControl?: boolean
}
const props = withDefaults(defineProps
(), {
onPageChange: undefined,
showInfo: true,
+ showControl: true,
})
const emit = defineEmits<{
@@ -65,7 +67,7 @@ const formattedRecordCount = computed(() => {
})
const startRecord = computed(() => {
- const start = ((props.paginationMeta.page - 1) * props.paginationMeta.pageSize) + 1
+ const start = (props.paginationMeta.page - 1) * props.paginationMeta.pageSize + 1
return Number(start).toLocaleString('id-ID')
})
@@ -77,53 +79,95 @@ const endRecord = computed(() => {
function getButtonClass(pageNumber: number) {
const digits = pageNumber.toString().length
- if (digits >= 4) { // 1000+ (1k+)
+ if (digits >= 4) {
+ // 1000+ (1k+)
return 'h-9 px-4 min-w-12'
- } else if (digits === 3) { // 100-999
+ } else if (digits === 3) {
+ // 100-999
return 'h-9 px-3 min-w-10'
- } else { // 1-99
+ } else {
+ // 1-99
return 'w-9 h-9 p-0'
}
}
-
+
-
- Menampilkan {{ startRecord }}
- hingga {{ Number(endRecord).toLocaleString('id-ID') }}
- dari {{ formattedRecordCount }} data
+
+ Menampilkan {{ startRecord }} hingga {{ Number(endRecord).toLocaleString('id-ID') }} dari
+ {{ formattedRecordCount }} data
+
+
+ -
-
-
-
+
-
+
-
-
-
+ v-slot="{ page }"
+ :total="paginationMeta.recordCount"
+ :sibling-count="1"
+ :page="paginationMeta.page"
+ :items-per-page="paginationMeta.pageSize"
+ show-edges
+ >
+
+
+
-
+ >
+
{{ item.value }}
-
+
-
-
+
+
diff --git a/app/components/pub/my-ui/toggle/provided-toggle.vue b/app/components/pub/my-ui/toggle/provided-toggle.vue
new file mode 100644
index 00000000..f028118c
--- /dev/null
+++ b/app/components/pub/my-ui/toggle/provided-toggle.vue
@@ -0,0 +1,34 @@
+
+
+
+ model = !model"
+ :variant="model ? 'default' : 'outline'"
+ >
+ {{ label }}
+
+
+
+
diff --git a/app/components/pub/ui/button/index.ts b/app/components/pub/ui/button/index.ts
index c4063089..43c75876 100644
--- a/app/components/pub/ui/button/index.ts
+++ b/app/components/pub/ui/button/index.ts
@@ -19,7 +19,7 @@ export const buttonVariants = cva(
link: 'text-primary underline-offset-4 hover:underline',
},
size: {
- default: 'md:h8 2xl:h-9 px-4 py-2',
+ default: 'md:h-8 2xl:h-9 px-4 py-2',
xs: 'h-7 rounded px-2',
sm: 'h-8 rounded-md px-3 text-xs',
lg: 'h-10 rounded-md px-8',
diff --git a/app/components/pub/ui/toggle/index.ts b/app/components/pub/ui/toggle/index.ts
index 07acae50..9486e903 100644
--- a/app/components/pub/ui/toggle/index.ts
+++ b/app/components/pub/ui/toggle/index.ts
@@ -4,16 +4,16 @@ import { cva } from 'class-variance-authority'
export { default as Toggle } from './Toggle.vue'
export const toggleVariants = cva(
- 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground',
+ 'inline-flex items-center justify-center rounded-md text-xs 2xl:text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground',
{
variants: {
variant: {
default: 'bg-transparent',
outline:
- 'border border-input bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground',
+ 'border border-slate-300 bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground',
},
size: {
- default: 'h-9 px-3',
+ default: 'md:h-8 2xl:h-9 px-3',
sm: 'h-8 px-2',
lg: 'h-10 px-3',
},
diff --git a/app/handlers/control-letter.handler.ts b/app/handlers/control-letter.handler.ts
new file mode 100644
index 00000000..b096a178
--- /dev/null
+++ b/app/handlers/control-letter.handler.ts
@@ -0,0 +1,24 @@
+// Handlers
+import { genCrudHandler } from '~/handlers/_handler'
+
+// Services
+import { create, update, remove } from '~/services/control-letter.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({
+ create,
+ update,
+ remove,
+})
diff --git a/app/handlers/installation-position.handler.ts b/app/handlers/installation-position.handler.ts
new file mode 100644
index 00000000..e3cfcf38
--- /dev/null
+++ b/app/handlers/installation-position.handler.ts
@@ -0,0 +1,24 @@
+// Handlers
+import { genCrudHandler } from '~/handlers/_handler'
+
+// Services
+import { create, update, remove } from '~/services/installation-position.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({
+ create,
+ update,
+ remove,
+})
diff --git a/app/handlers/mcu-order-item.handler.ts b/app/handlers/mcu-order-item.handler.ts
new file mode 100644
index 00000000..62e1861e
--- /dev/null
+++ b/app/handlers/mcu-order-item.handler.ts
@@ -0,0 +1,17 @@
+import { createCrudHandler, genCrudHandler } from '~/handlers/_handler'
+import { create, update, remove } from '~/services/prescription.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({ create, update, remove})
diff --git a/app/handlers/mcu-order.handler.ts b/app/handlers/mcu-order.handler.ts
new file mode 100644
index 00000000..4b114dfc
--- /dev/null
+++ b/app/handlers/mcu-order.handler.ts
@@ -0,0 +1,17 @@
+import { createCrudHandler, genCrudHandler } from '~/handlers/_handler'
+import { create, update, remove } from '~/services/mcu-order.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({ create, update, remove})
diff --git a/app/handlers/mcu-src-category.handler.ts b/app/handlers/mcu-src-category.handler.ts
new file mode 100644
index 00000000..8369666b
--- /dev/null
+++ b/app/handlers/mcu-src-category.handler.ts
@@ -0,0 +1,24 @@
+// Handlers
+import { genCrudHandler } from '~/handlers/_handler'
+
+// Services
+import { create, update, remove } from '~/services/mcu-src-category.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({
+ create,
+ update,
+ remove,
+})
diff --git a/app/handlers/patient.handler.ts b/app/handlers/patient.handler.ts
index f87eaf71..198b3a22 100644
--- a/app/handlers/patient.handler.ts
+++ b/app/handlers/patient.handler.ts
@@ -1,8 +1,128 @@
// Handlers
import { genCrudHandler } from '~/handlers/_handler'
+// Types
+import type { PatientEntity } from '~/models/patient'
+import type { PaginationMeta } from '~/components/pub/my-ui/pagination/pagination.type'
+
// Services
-import { postPatient as create, patchPatient as update, removePatient as remove } from '~/services/patient.service'
+import {
+ postPatient as create,
+ patchPatient as update,
+ removePatient as remove,
+ getPatientDetail,
+ getPatients,
+ getPatientByIdentifier,
+} from '~/services/patient.service'
+
+const isPatientsLoading = ref(false)
+const patients = ref
>([])
+const selectedPatient = ref('')
+const selectedPatientObject = ref(null)
+const paginationMeta = ref({
+ recordCount: 0,
+ page: 1,
+ pageSize: 10,
+ totalPage: 5,
+ hasNext: false,
+ hasPrev: false,
+})
+
+function mapPatientToRow(patient: PatientEntity) {
+ const identity = patient?.person?.residentIdentityNumber || '-'
+ const number = patient?.number || '-'
+ const bpjs = '-'
+ const name = patient?.person?.name || '-'
+ return { id: patient.id ? String(patient.id) : '-', identity, number, bpjs, name }
+}
+
+function mapPaginationMetaToRow(meta: any) {
+ const recordCount = meta['record_totalCount'] ? Number(meta['record_totalCount']) : 0
+ const currentCount = meta['record_currentCount'] ? Number(meta['record_currentCount']) : 0
+ const page = meta['page_number'] ? Number(meta['page_number']) : 1
+ const pageSize = meta['page_size'] ? Number(meta['page_size']) : 10
+ const totalPage = Math.ceil(recordCount / pageSize)
+
+ return {
+ recordCount,
+ page,
+ pageSize,
+ totalPage,
+ hasNext: currentCount < recordCount && page < totalPage,
+ hasPrev: page > 1,
+ }
+}
+
+async function getPatientsList(params: any = { 'page-size': 10 }) {
+ try {
+ isPatientsLoading.value = true
+ patients.value = []
+ paginationMeta.value = {} as PaginationMeta
+ const result = await getPatients(params)
+ if (result && result.success && result.body && Array.isArray(result.body.data)) {
+ const meta = result.body.meta
+ patients.value = result.body.data.map(mapPatientToRow)
+ paginationMeta.value = mapPaginationMetaToRow(meta)
+ } else {
+ patients.value = [] // fallback to empty array
+ }
+ } catch (err) {
+ console.error('Failed to fetch patients for SEP search:', err)
+ patients.value = []
+ } finally {
+ isPatientsLoading.value = false
+ }
+}
+
+async function getPatientCurrent(id: string) {
+ try {
+ const result = await getPatientDetail(Number(id))
+ if (result && result.success && result.body && result.body.data) {
+ const patient = result.body.data || null
+ selectedPatientObject.value = patient
+ }
+ } catch (err) {
+ console.error('Failed to fetch patient:', err)
+ }
+}
+
+async function getPatientByIdentifierSearch(search: string) {
+ try {
+ isPatientsLoading.value = true
+ patients.value = []
+ paginationMeta.value = {} as PaginationMeta
+ const result = await getPatientByIdentifier(search)
+ if (result && result.success && result.body) {
+ if (result.type === 'resident-identity' && result.body.data) {
+ patients.value = [mapPatientToRow(result.body.data)]
+ } else if (result.type === 'identity') {
+ patients.value = Array.isArray(result.body.data) ? result.body.data.map(mapPatientToRow) : result.body.data ? [mapPatientToRow(result.body.data)] : []
+ } else {
+ const meta = result.body.meta
+ patients.value = Array.isArray(result.body.data) ? result.body.data.map(mapPatientToRow) : result.body.data ? [mapPatientToRow(result.body.data)] : []
+ paginationMeta.value = mapPaginationMetaToRow(meta)
+ }
+ } else {
+ patients.value = [] // fallback to empty array
+ }
+ } catch (err) {
+ console.error('Failed to fetch patients by identifier:', err)
+ patients.value = []
+ } finally {
+ isPatientsLoading.value = false
+ }
+}
+
+export {
+ isPatientsLoading,
+ patients,
+ selectedPatient,
+ selectedPatientObject,
+ paginationMeta,
+ getPatientsList,
+ getPatientCurrent,
+ getPatientByIdentifierSearch,
+}
export const {
recId,
diff --git a/app/handlers/prescription-item.handler.ts b/app/handlers/prescription-item.handler.ts
new file mode 100644
index 00000000..70450970
--- /dev/null
+++ b/app/handlers/prescription-item.handler.ts
@@ -0,0 +1,17 @@
+import { createCrudHandler, genCrudHandler } from '~/handlers/_handler'
+import { create, update, remove } from '~/services/prescription-item.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({ create, update, remove})
diff --git a/app/handlers/prescription.handler.ts b/app/handlers/prescription.handler.ts
new file mode 100644
index 00000000..62e1861e
--- /dev/null
+++ b/app/handlers/prescription.handler.ts
@@ -0,0 +1,17 @@
+import { createCrudHandler, genCrudHandler } from '~/handlers/_handler'
+import { create, update, remove } from '~/services/prescription.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({ create, update, remove})
diff --git a/app/handlers/specialist-position.handler.ts b/app/handlers/specialist-position.handler.ts
new file mode 100644
index 00000000..859070ba
--- /dev/null
+++ b/app/handlers/specialist-position.handler.ts
@@ -0,0 +1,24 @@
+// Handlers
+import { genCrudHandler } from '~/handlers/_handler'
+
+// Services
+import { create, update, remove } from '~/services/specialist-position.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({
+ create,
+ update,
+ remove,
+})
diff --git a/app/handlers/subspecialist-position.handler.ts b/app/handlers/subspecialist-position.handler.ts
new file mode 100644
index 00000000..42473f86
--- /dev/null
+++ b/app/handlers/subspecialist-position.handler.ts
@@ -0,0 +1,24 @@
+// Handlers
+import { genCrudHandler } from '~/handlers/_handler'
+
+// Services
+import { create, update, remove } from '~/services/subspecialist-position.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({
+ create,
+ update,
+ remove,
+})
diff --git a/app/handlers/unit-position.handler.ts b/app/handlers/unit-position.handler.ts
new file mode 100644
index 00000000..1cf4994b
--- /dev/null
+++ b/app/handlers/unit-position.handler.ts
@@ -0,0 +1,24 @@
+// Handlers
+import { genCrudHandler } from '~/handlers/_handler'
+
+// Services
+import { create, update, remove } from '~/services/unit-position.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = genCrudHandler({
+ create,
+ update,
+ remove,
+})
diff --git a/app/lib/constants.vclaim.ts b/app/lib/constants.vclaim.ts
new file mode 100644
index 00000000..84fe5d52
--- /dev/null
+++ b/app/lib/constants.vclaim.ts
@@ -0,0 +1,94 @@
+export const serviceTypes: Record = {
+ '1': 'Rawat Inap',
+ '2': 'Rawat Jalan',
+}
+
+export const registerMethods: Record = {
+ '1': 'Rujukan',
+ '2': 'IGD',
+ '3': 'Kontrol',
+ '4': 'Rujukan Internal',
+}
+
+export const classLevels: Record = {
+ '1': 'Kelas 1',
+ '2': 'Kelas 2',
+ '3': 'Kelas 3',
+}
+
+export const classLevelUpgrades: Record = {
+ '1': 'VVIP',
+ '2': 'VIP',
+ '3': 'Kelas 1',
+ '4': 'Kelas 2',
+ '5': 'Kelas 3',
+ '6': 'ICCU',
+ '7': 'ICU',
+ '8': 'Diatas Kelas 1',
+}
+
+export const classPaySources: Record = {
+ '1': 'Pribadi',
+ '2': 'Pemberi Kerja',
+ '3': 'Asuransi Kesehatan Tambahan',
+}
+
+export const procedureTypes: Record = {
+ '0': 'Prosedur tidak berkelanjutan',
+ '1': 'Prosedur dan terapi berkelanjutan',
+}
+
+export const purposeOfVisits: Record = {
+ '0': 'Normal',
+ '1': 'Prosedur',
+ '2': 'Konsul Dokter',
+}
+
+export const trafficAccidents: Record = {
+ '0': 'Bukan Kecelakaan lalu lintas [BKLL]',
+ '1': 'KLL dan Bukan Kecelakaan Kerja [BKK]',
+ '2': 'KLL dan KK',
+ '3': 'KK',
+}
+
+export const supportCodes: Record = {
+ '1': 'Radioterapi',
+ '2': 'Kemoterapi',
+ '3': 'Rehabilitasi Medik',
+ '4': 'Rehabilitasi Psikososial',
+ '5': 'Transfusi Darah',
+ '6': 'Pelayanan Gigi',
+ '7': 'Laboratorium',
+ '8': 'USG',
+ '9': 'Farmasi',
+ '10': 'Lain-Lain',
+ '11': 'MRI',
+ '12': 'HEMODIALISA',
+}
+
+export const serviceAssessments: Record = {
+ '1': 'Poli spesialis tidak tersedia pada hari sebelumnya',
+ '2': 'Jam Poli telah berakhir pada hari sebelumnya',
+ '3': 'Dokter Spesialis yang dimaksud tidak praktek pada hari sebelumnya',
+ '4': 'Atas Instruksi RS',
+ '5': 'Tujuan Kontrol',
+}
+
+export const paymentTypes: Record = {
+ jkn: 'JKN (Jaminan Kesehatan Nasional)',
+ jkmm: 'JKMM (Jaminan Kesehatan Mandiri)',
+ spm: 'SPM (Sistem Pembayaran Mandiri)',
+ pks: 'PKS (Pembiayaan Kesehatan Sosial)',
+}
+
+export const sepRefTypeCodes: Record = {
+ internal: 'Rujukan Internal',
+ external: 'Faskes Lain',
+}
+
+export const participantGroups: Record = {
+ pbi: 'PBI (Penerima Bantuan Iuran)',
+ ppu: 'PPU (Pekerja Penerima Upah)',
+ pbu: 'PBU (Pekerja Bukan Penerima Upah)',
+ bp: 'BP (Bukan Pekerja)',
+}
\ No newline at end of file
diff --git a/app/lib/date.ts b/app/lib/date.ts
index 502a6cfb..2c7b92cf 100644
--- a/app/lib/date.ts
+++ b/app/lib/date.ts
@@ -41,4 +41,12 @@ export function getAge(dateString: string, comparedDate?: string): { idFormat: s
idFormat,
extFormat
};
+}
+
+export function formatDateYyyyMmDd(isoDateString: string): string {
+ const date = new Date(isoDateString);
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, '0');
+ const day = String(date.getDate()).padStart(2, '0');
+ return `${year}-${month}-${day}`;
}
\ No newline at end of file
diff --git a/app/lib/page-permission.ts b/app/lib/page-permission.ts
index c527a8cc..ab7b5550 100644
--- a/app/lib/page-permission.ts
+++ b/app/lib/page-permission.ts
@@ -2,43 +2,67 @@ import type { RoleAccess } from '~/models/role'
export const PAGE_PERMISSIONS = {
'/patient': {
- doctor: ['R'],
- nurse: ['R'],
- admisi: ['C', 'R', 'U', 'D'],
- pharmacy: ['R'],
- billing: ['R'],
- management: ['R'],
+ 'emp|doc': ['R'],
+ 'emp|nur': ['R'],
+ 'emp|reg': ['C', 'R', 'U', 'D'],
+ 'emp|pha': ['R'],
+ 'emp|pay': ['R'],
+ 'emp|mng': ['R'],
},
'/doctor': {
- doctor: ['C', 'R', 'U', 'D'],
- nurse: ['R'],
- admisi: ['R'],
- pharmacy: ['R'],
- billing: ['R'],
- management: ['R'],
+ 'emp|doc': ['C', 'R', 'U', 'D'],
+ 'emp|nur': ['R'],
+ 'emp|reg': ['R'],
+ 'emp|pha': ['R'],
+ 'emp|pay': ['R'],
+ 'emp|mng': ['R'],
},
'/satusehat': {
- doctor: ['R'],
- nurse: ['R'],
- admisi: ['C', 'R', 'U', 'D'],
- pharmacy: ['R'],
- billing: ['R'],
- management: ['R'],
+ 'emp|doc': ['R'],
+ 'emp|nur': ['R'],
+ 'emp|reg': ['C', 'R', 'U', 'D'],
+ 'emp|pha': ['R'],
+ 'emp|pay': ['R'],
+ 'emp|mng': ['R'],
+ },
+ '/outpatient/encounter': {
+ 'emp|doc': ['C', 'R', 'U', 'D'],
+ 'emp|nur': ['C', 'R', 'U', 'D'],
+ 'emp|reg': ['R'],
+ 'emp|pha': ['R'],
+ 'emp|pay': ['R'],
+ 'emp|mng': ['R'],
+ },
+ '/emergency/encounter': {
+ 'emp|doc': ['C', 'R', 'U', 'D'],
+ 'emp|nur': ['C', 'R', 'U', 'D'],
+ 'emp|reg': ['R'],
+ 'emp|pha': ['R'],
+ 'emp|pay': ['R'],
+ 'emp|mng': ['R'],
+ },
+ '/inpatient/encounter': {
+ 'emp|doc': ['C', 'R', 'U', 'D'],
+ 'emp|nur': ['C', 'R', 'U', 'D'],
+ 'emp|reg': ['R'],
+ 'emp|pha': ['R'],
+ 'emp|pay': ['R'],
+ 'emp|mng': ['R'],
},
'/rehab/encounter': {
- doctor: ['C', 'R', 'U', 'D'],
- nurse: ['R'],
- admisi: ['R'],
- pharmacy: ['R'],
- billing: ['R'],
- management: ['R'],
+ 'emp|doc': ['C', 'R', 'U', 'D'],
+ 'emp|nur': ['R'],
+ 'emp|reg': ['R'],
+ 'emp|pha': ['R'],
+ 'emp|pay': ['R'],
+ 'emp|mng': ['R'],
},
'/rehab/registration': {
- doctor: ['C', 'R', 'U', 'D'],
- nurse: ['R'],
- admisi: ['R'],
- pharmacy: ['R'],
- billing: ['R'],
- management: ['R'],
+ 'emp|doc': ['C', 'R', 'U', 'D'],
+ 'emp|nur': ['R'],
+ 'emp|reg': ['R'],
+ 'emp|pha': ['R'],
+ 'emp|pay': ['R'],
+ 'emp|mng': ['R'],
},
} as const satisfies Record
diff --git a/app/models/consultation.ts b/app/models/consultation.ts
index 09d050a8..595d628e 100644
--- a/app/models/consultation.ts
+++ b/app/models/consultation.ts
@@ -28,9 +28,10 @@ export interface DeleteDto {
export function genCreateDto(): CreateDto {
return {
+ date: '',
encounter_id: 0,
problem: '',
- unit_id: 0,
+ dstUnit_id: 0,
}
}
diff --git a/app/models/control-letter.ts b/app/models/control-letter.ts
new file mode 100644
index 00000000..8f520212
--- /dev/null
+++ b/app/models/control-letter.ts
@@ -0,0 +1,37 @@
+import { type Base, genBase } from "./_base"
+import { genDoctor, type Doctor } from "./doctor"
+import { genEncounter, type Encounter } from "./encounter"
+import { genSpecialist, type Specialist } from "./specialist"
+import { genSubspecialist, type Subspecialist } from "./subspecialist"
+import { genUnit, type Unit } from "./unit"
+
+export interface ControlLetter extends Base {
+ encounter_id: number
+ encounter: Encounter
+ unit_id: number
+ unit: Unit
+ specialist_id: number
+ specialist: Specialist
+ subspecialist_id: number
+ subspecialist: Subspecialist
+ doctor_id: number
+ doctor: Doctor
+ date: ''
+}
+
+export function genControlLetter(): ControlLetter {
+ return {
+ ...genBase(),
+ encounter_id: 0,
+ encounter: genEncounter(),
+ unit_id: 0,
+ unit: genUnit(),
+ specialist_id: 0,
+ specialist: genSpecialist(),
+ subspecialist_id: 0,
+ subspecialist: genSubspecialist(),
+ doctor_id: 0,
+ doctor: genDoctor(),
+ date: ''
+ }
+}
diff --git a/app/models/division-position.ts b/app/models/division-position.ts
index 3bd5e63a..dc263ada 100644
--- a/app/models/division-position.ts
+++ b/app/models/division-position.ts
@@ -1,11 +1,13 @@
import { type Base, genBase } from './_base'
-
+import type { Employee } from './employee'
export interface DivisionPosition extends Base {
code: string
name: string
headStatus?: boolean
division_id: number
employee_id?: number
+
+ employee?: Employee | null
}
export function genDivisionPosition(): DivisionPosition {
diff --git a/app/models/division.ts b/app/models/division.ts
index 0f6d9185..c54a0e24 100644
--- a/app/models/division.ts
+++ b/app/models/division.ts
@@ -1,10 +1,13 @@
-import { type Base, genBase } from "./_base"
-
+import { type Base, genBase } from './_base'
+import type { DivisionPosition } from './division-position'
export interface Division extends Base {
code: string
name: string
parent_id?: number | null
childrens?: Division[] | null
+
+ // preload
+ divisionPosition?: DivisionPosition[] | null
}
export function genDivision(): Division {
diff --git a/app/models/doctor.ts b/app/models/doctor.ts
index 3f517476..1b631907 100644
--- a/app/models/doctor.ts
+++ b/app/models/doctor.ts
@@ -8,10 +8,11 @@ export interface Doctor extends Base {
employee: Employee
ihs_number: string
sip_number: string
- unit_id?: number
- specialist_id?: number
+ code?: string
+ unit_icode?: number
+ specialist_icode?: number
specialist?: Specialist
- subspecialist_id?: number
+ subspecialist_icode?: number
subspecialist?: Subspecialist
bpjs_code?: string
}
@@ -21,9 +22,9 @@ export interface CreateDto {
employee_id: number
ihs_number: string
sip_number: string
- unit_id?: number
- specialist_id?: number
- subspecialist_id?: number
+ unit_code?: number
+ specialist_code?: number
+ subspecialist_code?: number
bpjs_code: string
}
diff --git a/app/models/general-consent.ts b/app/models/general-consent.ts
index c12df7ca..643230ef 100644
--- a/app/models/general-consent.ts
+++ b/app/models/general-consent.ts
@@ -1,19 +1,20 @@
export interface GeneralConsent {
id: number
encounter_id: number
- date?: string
- unit_id: number
- doctor_id?: number
- problem: string
- solution?: string
- repliedAt?: string
+ value: string
+}
+
+export interface ValueCreateDto {
+ relatives: string[]
+ responsible: string
+ informant: string
+ witness1: string
+ witness2: string
}
export interface CreateDto {
encounter_id: number
- date: string
- problem: string
- dstUnit_id: number
+ value: string
}
export interface UpdateDto {
diff --git a/app/models/installation-position.ts b/app/models/installation-position.ts
new file mode 100644
index 00000000..199038d7
--- /dev/null
+++ b/app/models/installation-position.ts
@@ -0,0 +1,23 @@
+import { type Base, genBase } from './_base'
+import type { Employee } from './employee'
+
+export interface InstallationPosition extends Base {
+ installation_id: number
+ code: string
+ name: string
+ headStatus?: boolean
+ employee_id?: number
+
+ employee?: Employee | null
+}
+
+export function genInstallationPosition(): InstallationPosition {
+ return {
+ ...genBase(),
+ installation_id: 0,
+ code: '',
+ name: '',
+ headStatus: false,
+ employee_id: 0,
+ }
+}
diff --git a/app/models/mcu-order.ts b/app/models/mcu-order.ts
index e3899aab..35e4018c 100644
--- a/app/models/mcu-order.ts
+++ b/app/models/mcu-order.ts
@@ -1,14 +1,18 @@
import { type Base, genBase } from "./_base"
+import { type Doctor, genDoctor } from "./doctor"
+import type { McuOrderItem } from "./mcu-order-item"
export interface McuOrder extends Base {
encounter_id: number
doctor_id: number
+ doctor: Doctor
status_code?: string
specimenPickTime: string
examinationDate: string
number?: number
temperature?: number
mcuUrgencyLevel_code?: string
+ items: McuOrderItem[]
}
export function genMcuOrder(): McuOrder {
@@ -16,8 +20,10 @@ export function genMcuOrder(): McuOrder {
...genBase(),
encounter_id: 0,
doctor_id: 0,
+ doctor: genDoctor(),
specimenPickTime: '',
- examinationDate: ''
+ examinationDate: '',
+ items: []
}
}
diff --git a/app/models/prescription.ts b/app/models/prescription.ts
index 543724d2..12d5eb9d 100644
--- a/app/models/prescription.ts
+++ b/app/models/prescription.ts
@@ -1,10 +1,10 @@
+import { type Base, genBase } from "./_base";
import { type Encounter, genEncounter } from "./encounter";
import { type Doctor, genDoctor } from "./doctor";
import { type PrescriptionItem } from "./prescription-item";
import type { SpecialistIntern } from "./specialist-intern";
-export interface Prescription {
- id: number
+export interface Prescription extends Base {
encounter_id: number
encounter: Encounter
doctor_id: number
@@ -44,7 +44,7 @@ export interface DeleteDto {
export function genPresciption(): Prescription {
return {
- id: 0,
+ ...genBase(),
encounter_id: 0,
encounter: genEncounter(),
doctor_id: 0,
diff --git a/app/models/specialist-position.ts b/app/models/specialist-position.ts
new file mode 100644
index 00000000..727e8374
--- /dev/null
+++ b/app/models/specialist-position.ts
@@ -0,0 +1,22 @@
+import { type Base, genBase } from './_base'
+import type { Employee } from './employee'
+
+export interface SpecialistPosition extends Base {
+ specialist_id: number
+ code: string
+ name: string
+ headStatus?: boolean
+ employee_id?: number
+ employee?: Employee | null
+}
+
+export function genSpecialistPosition(): SpecialistPosition {
+ return {
+ ...genBase(),
+ specialist_id: 0,
+ code: '',
+ name: '',
+ headStatus: false,
+ employee_id: 0,
+ }
+}
diff --git a/app/models/specialist.ts b/app/models/specialist.ts
index b4fe1115..d3180a73 100644
--- a/app/models/specialist.ts
+++ b/app/models/specialist.ts
@@ -1,9 +1,12 @@
-import { type Base, genBase } from "./_base"
+import { type Base, genBase } from './_base'
+import type { Unit } from './unit'
+import type { Subspecialist } from "./subspecialist"
export interface Specialist extends Base {
code: string
name: string
- unit_id?: number | string | null
+ unit?: Unit | null
+ subspecialists?: Subspecialist[]
}
export function genSpecialist(): Specialist {
@@ -11,6 +14,6 @@ export function genSpecialist(): Specialist {
...genBase(),
code: '',
name: '',
- unit_id: 0
+ unit_id: 0,
}
}
diff --git a/app/models/subspecialist-position.ts b/app/models/subspecialist-position.ts
new file mode 100644
index 00000000..28ea2287
--- /dev/null
+++ b/app/models/subspecialist-position.ts
@@ -0,0 +1,25 @@
+import { type Base, genBase } from './_base'
+import type { Employee } from './employee'
+import type { Subspecialist } from './subspecialist'
+
+export interface SubSpecialistPosition extends Base {
+ subspecialist_id: number
+ code: string
+ name: string
+ headStatus?: boolean
+ employee_id?: number
+
+ subspecialist?: Subspecialist | null
+ employee?: Employee | null
+}
+
+export function genSubSpecialistPosition(): SubSpecialistPosition {
+ return {
+ ...genBase(),
+ subspecialist_id: 0,
+ code: '',
+ name: '',
+ headStatus: false,
+ employee_id: 0,
+ }
+}
diff --git a/app/models/subspecialist.ts b/app/models/subspecialist.ts
index 6343b847..e67333e9 100644
--- a/app/models/subspecialist.ts
+++ b/app/models/subspecialist.ts
@@ -1,9 +1,11 @@
-import { type Base, genBase } from "./_base"
-
+import { type Base, genBase } from './_base'
+import { type Specialist } from './specialist'
export interface Subspecialist extends Base {
code: string
name: string
specialist_id?: number | string | null
+
+ specialist?: Specialist | null
}
export function genSubspecialist(): Subspecialist {
@@ -11,6 +13,6 @@ export function genSubspecialist(): Subspecialist {
...genBase(),
code: '',
name: '',
- specialist_id: 0
+ specialist_id: 0,
}
}
diff --git a/app/models/unit-position.ts b/app/models/unit-position.ts
new file mode 100644
index 00000000..11e97806
--- /dev/null
+++ b/app/models/unit-position.ts
@@ -0,0 +1,23 @@
+import { type Base, genBase } from './_base'
+import type { Employee } from './employee'
+
+export interface UnitPosition extends Base {
+ unit_id: number
+ code: string
+ name: string
+ headStatus?: boolean
+ employee_id?: number
+
+ employee?: Employee | null
+}
+
+export function genUnitPosition(): UnitPosition {
+ return {
+ ...genBase(),
+ unit_id: 0,
+ code: '',
+ name: '',
+ headStatus: false,
+ employee_id: 0,
+ }
+}
diff --git a/app/models/unit.ts b/app/models/unit.ts
index 142f0570..ba8ba5a1 100644
--- a/app/models/unit.ts
+++ b/app/models/unit.ts
@@ -1,9 +1,11 @@
-import { type Base, genBase } from "./_base"
-
+import { type Base, genBase } from './_base'
+import { type Installation } from '~/models/installation'
export interface Unit extends Base {
code: string
name: string
installation_id?: number | string | null
+
+ installation?: Installation | null
}
export function genUnit(): Unit {
diff --git a/app/models/vclaim.ts b/app/models/vclaim.ts
new file mode 100644
index 00000000..21ffb94f
--- /dev/null
+++ b/app/models/vclaim.ts
@@ -0,0 +1,15 @@
+export interface VclaimSepData {
+ letterDate: string
+ letterNumber: string
+ serviceType: string
+ flow: string
+ medicalRecordNumber: string
+ patientName: string
+ cardNumber: string
+ controlLetterNumber: string
+ controlLetterDate: string
+ clinicDestination: string
+ attendingDoctor: string
+ diagnosis: string
+ careClass: string
+}
diff --git a/app/pages/(features)/emergency/encounter/[id]/edit.vue b/app/pages/(features)/emergency/encounter/[id]/edit.vue
new file mode 100644
index 00000000..92d263d7
--- /dev/null
+++ b/app/pages/(features)/emergency/encounter/[id]/edit.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/emergency/encounter/add.vue b/app/pages/(features)/emergency/encounter/add.vue
new file mode 100644
index 00000000..aa382643
--- /dev/null
+++ b/app/pages/(features)/emergency/encounter/add.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/emergency/encounter/index.vue b/app/pages/(features)/emergency/encounter/index.vue
index 50485cec..ed05c25e 100644
--- a/app/pages/(features)/emergency/encounter/index.vue
+++ b/app/pages/(features)/emergency/encounter/index.vue
@@ -1,10 +1,47 @@
-
-
Hello world!!
-
You are accessing "{{ route.fullPath }}"
+
diff --git a/app/pages/(features)/inpatient/encounter/[id]/edit.vue b/app/pages/(features)/inpatient/encounter/[id]/edit.vue
new file mode 100644
index 00000000..2df3d4f6
--- /dev/null
+++ b/app/pages/(features)/inpatient/encounter/[id]/edit.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/inpatient/encounter/add.vue b/app/pages/(features)/inpatient/encounter/add.vue
new file mode 100644
index 00000000..bd827f79
--- /dev/null
+++ b/app/pages/(features)/inpatient/encounter/add.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/inpatient/encounter/index.vue b/app/pages/(features)/inpatient/encounter/index.vue
index 50485cec..7c9d1ac5 100644
--- a/app/pages/(features)/inpatient/encounter/index.vue
+++ b/app/pages/(features)/inpatient/encounter/index.vue
@@ -1,10 +1,47 @@
-
-
Hello world!!
-
You are accessing "{{ route.fullPath }}"
+
diff --git a/app/pages/(features)/integration/bpjs/control-letter/index.vue b/app/pages/(features)/integration/bpjs/control-letter/index.vue
new file mode 100644
index 00000000..8dcb9006
--- /dev/null
+++ b/app/pages/(features)/integration/bpjs/control-letter/index.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
diff --git a/app/pages/(features)/integration/bpjs/sep/add.vue b/app/pages/(features)/integration/bpjs/sep/add.vue
index 5db12aac..0658780b 100644
--- a/app/pages/(features)/integration/bpjs/sep/add.vue
+++ b/app/pages/(features)/integration/bpjs/sep/add.vue
@@ -22,12 +22,12 @@ const { checkRole, hasCreateAccess } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
-if (!hasAccess) {
- throw createError({
- statusCode: 403,
- statusMessage: 'Access denied',
- })
-}
+// if (!hasAccess) {
+// throw createError({
+// statusCode: 403,
+// statusMessage: 'Access denied',
+// })
+// }
// Define permission-based computed properties
const canCreate = true // hasCreateAccess(roleAccess)
diff --git a/app/pages/(features)/integration/bpjs/sep/index.vue b/app/pages/(features)/integration/bpjs/sep/index.vue
index b8ec57c4..d99dbb5d 100644
--- a/app/pages/(features)/integration/bpjs/sep/index.vue
+++ b/app/pages/(features)/integration/bpjs/sep/index.vue
@@ -22,9 +22,9 @@ const { checkRole, hasReadAccess } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
-if (!hasAccess) {
- navigateTo('/403')
-}
+// if (!hasAccess) {
+// navigateTo('/403')
+// }
// Define permission-based computed properties
const canRead = true // hasReadAccess(roleAccess)
diff --git a/app/pages/(features)/org-src/division-position/index.vue b/app/pages/(features)/org-src/division-position/index.vue
new file mode 100644
index 00000000..53551b48
--- /dev/null
+++ b/app/pages/(features)/org-src/division-position/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/org-src/division/[id]/index.vue b/app/pages/(features)/org-src/division/[id]/index.vue
new file mode 100644
index 00000000..658652d9
--- /dev/null
+++ b/app/pages/(features)/org-src/division/[id]/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/org-src/installation-position/index.vue b/app/pages/(features)/org-src/installation-position/index.vue
new file mode 100644
index 00000000..0b525098
--- /dev/null
+++ b/app/pages/(features)/org-src/installation-position/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/org-src/installation/[id]/index.vue b/app/pages/(features)/org-src/installation/[id]/index.vue
new file mode 100644
index 00000000..0264dd65
--- /dev/null
+++ b/app/pages/(features)/org-src/installation/[id]/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/org-src/specialist-position/index.vue b/app/pages/(features)/org-src/specialist-position/index.vue
new file mode 100644
index 00000000..a2e29428
--- /dev/null
+++ b/app/pages/(features)/org-src/specialist-position/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/org-src/specialist/[id]/index.vue b/app/pages/(features)/org-src/specialist/[id]/index.vue
new file mode 100644
index 00000000..c5554a71
--- /dev/null
+++ b/app/pages/(features)/org-src/specialist/[id]/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/org-src/subspecialist-position/index.vue b/app/pages/(features)/org-src/subspecialist-position/index.vue
new file mode 100644
index 00000000..650ae9ee
--- /dev/null
+++ b/app/pages/(features)/org-src/subspecialist-position/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/org-src/subspecialist/[id]/index.vue b/app/pages/(features)/org-src/subspecialist/[id]/index.vue
new file mode 100644
index 00000000..7bd0b8ee
--- /dev/null
+++ b/app/pages/(features)/org-src/subspecialist/[id]/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/org-src/unit-position/index.vue b/app/pages/(features)/org-src/unit-position/index.vue
new file mode 100644
index 00000000..c40a0654
--- /dev/null
+++ b/app/pages/(features)/org-src/unit-position/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/org-src/unit/[id]/index.vue b/app/pages/(features)/org-src/unit/[id]/index.vue
new file mode 100644
index 00000000..1230b57c
--- /dev/null
+++ b/app/pages/(features)/org-src/unit/[id]/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/outpatient/encounter/[id]/edit.vue b/app/pages/(features)/outpatient/encounter/[id]/edit.vue
new file mode 100644
index 00000000..9713675f
--- /dev/null
+++ b/app/pages/(features)/outpatient/encounter/[id]/edit.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/outpatient/encounter/[id]/index.vue b/app/pages/(features)/outpatient/encounter/[id]/index.vue
new file mode 100644
index 00000000..1864cf2c
--- /dev/null
+++ b/app/pages/(features)/outpatient/encounter/[id]/index.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
diff --git a/app/pages/(features)/outpatient/encounter/add.vue b/app/pages/(features)/outpatient/encounter/add.vue
new file mode 100644
index 00000000..948b16c6
--- /dev/null
+++ b/app/pages/(features)/outpatient/encounter/add.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
diff --git a/app/pages/(features)/outpatient/encounter/index.vue b/app/pages/(features)/outpatient/encounter/index.vue
index 50485cec..1e679c5d 100644
--- a/app/pages/(features)/outpatient/encounter/index.vue
+++ b/app/pages/(features)/outpatient/encounter/index.vue
@@ -1,10 +1,47 @@
-
-
Hello world!!
-
You are accessing "{{ route.fullPath }}"
+
diff --git a/app/pages/(features)/outpation-action/cemotherapy/index.vue b/app/pages/(features)/outpation-action/cemotherapy/index.vue
deleted file mode 100644
index 50485cec..00000000
--- a/app/pages/(features)/outpation-action/cemotherapy/index.vue
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
Hello world!!
-
You are accessing "{{ route.fullPath }}"
-
-
diff --git a/app/pages/(features)/outpation-action/chemotherapy/[mode]/[id]/verification.vue b/app/pages/(features)/outpation-action/chemotherapy/[mode]/[id]/verification.vue
new file mode 100644
index 00000000..ef936ff2
--- /dev/null
+++ b/app/pages/(features)/outpation-action/chemotherapy/[mode]/[id]/verification.vue
@@ -0,0 +1,47 @@
+
+
+
+
+
diff --git a/app/pages/(features)/outpation-action/chemotherapy/[mode]/index.vue b/app/pages/(features)/outpation-action/chemotherapy/[mode]/index.vue
new file mode 100644
index 00000000..cf33691a
--- /dev/null
+++ b/app/pages/(features)/outpation-action/chemotherapy/[mode]/index.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
+
diff --git a/app/pages/(features)/outpation-action/chemotherapy/index.vue b/app/pages/(features)/outpation-action/chemotherapy/index.vue
new file mode 100644
index 00000000..a2dfdea5
--- /dev/null
+++ b/app/pages/(features)/outpation-action/chemotherapy/index.vue
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/app/pages/(features)/outpation-action/chemotherapy/list.vue b/app/pages/(features)/outpation-action/chemotherapy/list.vue
new file mode 100644
index 00000000..a141baaa
--- /dev/null
+++ b/app/pages/(features)/outpation-action/chemotherapy/list.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
diff --git a/app/pages/(features)/rehab/examination-queue/index.vue b/app/pages/(features)/rehab/encounter-queue/index.vue
similarity index 100%
rename from app/pages/(features)/rehab/examination-queue/index.vue
rename to app/pages/(features)/rehab/encounter-queue/index.vue
diff --git a/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/edit.vue b/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/edit.vue
new file mode 100644
index 00000000..cc5d182f
--- /dev/null
+++ b/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/edit.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
diff --git a/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/index.vue b/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/index.vue
new file mode 100644
index 00000000..612315ad
--- /dev/null
+++ b/app/pages/(features)/rehab/encounter/[id]/control-letter/[control_letter_id]/index.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
diff --git a/app/pages/(features)/rehab/encounter/[id]/control-letter/add.vue b/app/pages/(features)/rehab/encounter/[id]/control-letter/add.vue
new file mode 100644
index 00000000..1070a29f
--- /dev/null
+++ b/app/pages/(features)/rehab/encounter/[id]/control-letter/add.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
diff --git a/app/pages/(features)/rehab/encounter/[id]/edit.vue b/app/pages/(features)/rehab/encounter/[id]/edit.vue
index 77b0dd3e..02dc5428 100644
--- a/app/pages/(features)/rehab/encounter/[id]/edit.vue
+++ b/app/pages/(features)/rehab/encounter/[id]/edit.vue
@@ -6,7 +6,7 @@ import { PAGE_PERMISSIONS } from '~/lib/page-permission'
definePageMeta({
middleware: ['rbac'],
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
- title: 'Tambah Kunjungan',
+ title: 'Edit Kunjungan',
contentFrame: 'cf-full-width',
})
@@ -18,7 +18,7 @@ useHead({
const roleAccess: PagePermission = PAGE_PERMISSIONS['/rehab/encounter']
-const { checkRole, hasCreateAccess } = useRBAC()
+const { checkRole, hasUpdateAccess } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
@@ -30,12 +30,26 @@ if (!hasAccess) {
}
// Define permission-based computed properties
-const canCreate = hasCreateAccess(roleAccess)
+const canUpdate = hasUpdateAccess(roleAccess)
+
+// Get encounter ID from route params
+const encounterId = computed(() => {
+ const id = route.params.id
+ return typeof id === 'string' ? parseInt(id) : 0
+})
-
-
+
+
-
+
diff --git a/app/pages/(features)/rehab/encounter/[id]/process.vue b/app/pages/(features)/rehab/encounter/[id]/process.vue
index 3fa7525a..abd0efa7 100644
--- a/app/pages/(features)/rehab/encounter/[id]/process.vue
+++ b/app/pages/(features)/rehab/encounter/[id]/process.vue
@@ -22,15 +22,15 @@ const { checkRole, hasCreateAccess } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
-if (!hasAccess) {
- throw createError({
- statusCode: 403,
- statusMessage: 'Access denied',
- })
-}
+// if (!hasAccess) {
+// throw createError({
+// statusCode: 403,
+// statusMessage: 'Access denied',
+// })
+// }
// Define permission-based computed properties
-const canCreate = hasCreateAccess(roleAccess)
+const canCreate = true // hasCreateAccess(roleAccess)
diff --git a/app/pages/(features)/rehab/encounter/add.vue b/app/pages/(features)/rehab/encounter/add.vue
index f20b90c1..fe7dd98c 100644
--- a/app/pages/(features)/rehab/encounter/add.vue
+++ b/app/pages/(features)/rehab/encounter/add.vue
@@ -35,7 +35,15 @@ const canCreate = hasCreateAccess(roleAccess)
-
+
-
+
diff --git a/app/pages/(features)/rehab/encounter/index.vue b/app/pages/(features)/rehab/encounter/index.vue
index 7a8564a8..f50ad954 100644
--- a/app/pages/(features)/rehab/encounter/index.vue
+++ b/app/pages/(features)/rehab/encounter/index.vue
@@ -5,7 +5,7 @@ import { PAGE_PERMISSIONS } from '~/lib/page-permission'
definePageMeta({
middleware: ['rbac'],
- roles: ['system', 'doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
+ roles: ['system', 'emp-doc', 'emp-nur', 'emp-reg', 'emp-pha', 'emp-pay', 'emp-mng'],
title: 'Daftar Kunjungan',
contentFrame: 'cf-full-width',
})
@@ -23,18 +23,25 @@ const { checkRole, hasReadAccess } = useRBAC()
// Check if user has access to this page
const hasAccess = checkRole(roleAccess)
if (!hasAccess) {
- navigateTo('/403')
+ // navigateTo('/403')
}
// Define permission-based computed properties
-const canRead = hasReadAccess(roleAccess)
+const canRead = true // hasReadAccess(roleAccess)
diff --git a/app/pages/(features)/rehab/examination/index.vue b/app/pages/(features)/rehab/examination/index.vue
deleted file mode 100644
index 806b2650..00000000
--- a/app/pages/(features)/rehab/examination/index.vue
+++ /dev/null
@@ -1,3 +0,0 @@
-
- Examination
-
diff --git a/app/schemas/chemotherapy.schema.ts b/app/schemas/chemotherapy.schema.ts
new file mode 100644
index 00000000..212e5358
--- /dev/null
+++ b/app/schemas/chemotherapy.schema.ts
@@ -0,0 +1,73 @@
+import { z } from 'zod'
+
+const dateStringSchema = z.string().min(1)
+
+export const chemotherapySchema = z.object({
+ // Data Pasien
+ namaPasien: z.string({
+ required_error: 'Nama pasien harus diisi',
+ }).min(1, 'Nama pasien harus diisi'),
+
+ tanggalLahir: z.string({
+ required_error: 'Tanggal lahir harus diisi',
+ }).min(1, 'Tanggal lahir harus diisi'),
+
+ noRM: z.string({
+ required_error: 'Nomor RM harus diisi',
+ }).min(1, 'Nomor RM harus diisi'),
+
+ alamat: z.string({
+ required_error: 'Alamat harus diisi',
+ }).min(1, 'Alamat harus diisi'),
+
+ beratBadan: z.union([
+ z.string(),
+ z.number()
+ ]).transform(val => val === '' ? null : Number(val))
+ .refine(val => val === null || (val >= 0 && val <= 500), {
+ message: 'Berat badan harus di antara 0-500 kg',
+ }),
+
+ tinggiBadan: z.union([
+ z.string(),
+ z.number()
+ ]).transform(val => val === '' ? null : Number(val))
+ .refine(val => val === null || (val >= 0 && val <= 300), {
+ message: 'Tinggi badan harus di antara 0-300 cm',
+ }),
+
+ diagnosa: z.string({
+ required_error: 'Diagnosa harus dipilih',
+ }).min(1, 'Diagnosa harus dipilih'),
+
+ // Protokol Kemoterapi
+ siklus: z.string({
+ required_error: 'Siklus harus diisi',
+ }).min(1, 'Siklus harus diisi'),
+
+ periodeAwal: z.string({
+ required_error: 'Periode awal harus diisi',
+ }).min(1, 'Periode awal harus diisi'),
+
+ periodeAkhir: dateStringSchema.refine((val) => {
+ if (!val) return false
+ const date = new Date(val)
+ return !isNaN(date.getTime())
+ }, {
+ message: 'Format tanggal tidak valid'
+ }),
+
+ tanggalKemoterapi: dateStringSchema.refine((val) => {
+ if (!val) return false
+ const date = new Date(val)
+ return !isNaN(date.getTime())
+ }, {
+ message: 'Format tanggal tidak valid'
+ }),
+
+ dokterKRJ: z.string({
+ required_error: 'Dokter harus dipilih',
+ }).refine(val => val !== '', {
+ message: 'Dokter harus dipilih',
+ }),
+})
\ No newline at end of file
diff --git a/app/schemas/control-letter.schema.ts b/app/schemas/control-letter.schema.ts
new file mode 100644
index 00000000..c82ffaac
--- /dev/null
+++ b/app/schemas/control-letter.schema.ts
@@ -0,0 +1,47 @@
+import { z } from 'zod'
+
+const ControlLetterSchema = z.object({
+ sepStatus: z.string({
+ required_error: 'Mohon isi status SEP',
+ }).default('SEP Internal'),
+ unit_code: z.string({
+ required_error: 'Mohon isi Unit',
+ }),
+ specialist_code: z.string({
+ required_error: 'Mohon isi Spesialis',
+ }),
+ subspecialist_code: z.string({
+ required_error: 'Mohon isi Sub Spesialis',
+ }),
+ doctor_code: z.string({
+ required_error: 'Mohon isi DPJP',
+ }),
+ encounter_code: z.string().optional(),
+ date: z.string({
+ required_error: 'Mohon lengkapi Tanggal Kontrol',
+ })
+ .refine(
+ (date) => {
+ // Jika kosong, return false untuk required validation
+ if (!date || date.trim() === '') return false
+
+ // Jika ada isi, validasi format tanggal
+ try {
+ const dateObj = new Date(date)
+ // Cek apakah tanggal valid dan tahun >= 1900
+ return !isNaN(dateObj.getTime()) && dateObj.getFullYear() >= 1900
+ } catch {
+ return false
+ }
+ },
+ {
+ message: 'Mohon lengkapi Tanggal Kontrol dengan format yang valid',
+ },
+ )
+ .transform((dateStr) => new Date(dateStr).toISOString()),
+})
+
+type ControlLetterFormData = z.infer
+
+export { ControlLetterSchema }
+export type { ControlLetterFormData }
diff --git a/app/schemas/general-consent.schema.ts b/app/schemas/general-consent.schema.ts
index 8aa61fe7..43014fa0 100644
--- a/app/schemas/general-consent.schema.ts
+++ b/app/schemas/general-consent.schema.ts
@@ -2,9 +2,11 @@ import { z } from 'zod'
import type { CreateDto } from '~/models/general-consent'
const GeneralConsentSchema = z.object({
- date: z.string({ required_error: 'Tanggal harus diisi' }),
- dstUnit_id: z.number({ required_error: 'Unit harus diisi' }),
- problem: z.string({ required_error: 'Uraian harus diisi' }).min(20, 'Uraian minimum 20 karakter'),
+ relatives: z.string().optional(),
+ responsible_doctor: z.string().optional(),
+ informant: z.string().optional(),
+ witness1: z.string().optional(),
+ witness2: z.string().optional(),
})
type GeneralConsentFormData = z.infer & CreateDto
diff --git a/app/schemas/installation-position.schema.ts b/app/schemas/installation-position.schema.ts
new file mode 100644
index 00000000..5990fc6c
--- /dev/null
+++ b/app/schemas/installation-position.schema.ts
@@ -0,0 +1,20 @@
+import { z } from 'zod'
+import type { InstallationPosition } from '~/models/installation-position'
+
+const InstallationPositionSchema = z.object({
+ code: z.string({ required_error: 'Kode harus diisi' }).min(1, 'Kode minimum 1 karakter'),
+ name: z.string({ required_error: 'Nama harus diisi' }).min(1, 'Nama minimum 1 karakter'),
+ headStatus: z.boolean().optional().nullable(),
+ installation_id: z.union([
+ z.string({ required_error: 'Instalasi Induk harus diisi' }),
+ z.number({ required_error: 'Instalasi Induk harus diisi' }),
+ ]),
+ employee_id: z
+ .union([z.string({ required_error: 'Karyawan harus diisi' }), z.number({ required_error: 'Karyawan harus diisi' })])
+ .optional()
+ .nullable(),
+})
+type InstallationPositionFormData = z.infer & Partial
+
+export { InstallationPositionSchema }
+export type { InstallationPositionFormData }
diff --git a/app/schemas/integration-bpjs.schema.ts b/app/schemas/integration-bpjs.schema.ts
new file mode 100644
index 00000000..47206edf
--- /dev/null
+++ b/app/schemas/integration-bpjs.schema.ts
@@ -0,0 +1,255 @@
+import { z } from 'zod'
+
+const ERROR_MESSAGES = {
+ required: {
+ sepDate: 'Tanggal wajib diisi',
+ serviceType: 'Jenis Pelayanan wajib diisi',
+ admissionType: 'Jenis Pendaftaran wajib diisi',
+ cardNumber: 'No. Kartu BPJS wajib diisi',
+ nationalId: 'Nomor ID wajib diisi',
+ medicalRecordNumber: 'Nomor Rekam Medis wajib diisi',
+ patientName: 'Nama wajib diisi',
+ phoneNumber: 'Nomor Telepon wajib diisi',
+ referralLetterNumber: 'Nomor Surat Kontrol wajib diisi',
+ referralLetterDate: 'Tanggal Surat Kontrol wajib diisi',
+ fromClinic: 'Faskes Asal wajib diisi',
+ destinationClinic: 'Klinik Tujuan wajib diisi',
+ attendingDoctor: 'Dokter wajib diisi',
+ initialDiagnosis: 'Diagnosa Awal wajib diisi',
+ cob: 'COB wajib diisi',
+ cataract: 'Katarak wajib diisi',
+ clinicExcecutive: 'Klinkik eksekutif wajib diisi',
+ subSpecialistId: 'Subspesialis wajib diisi',
+ procedureType: 'Jenis Prosedur wajib diisi',
+ supportCode: 'Kode Penunjang wajib diisi',
+ note: 'Catatan wajib diisi',
+ trafficAccident: 'Kejadian lalu lintas wajib diisi',
+ purposeOfVisit: 'Tujuan Kunjungan wajib diisi',
+ serviceAssessment: 'Assemen Pelayanan wajib diisi',
+ lpNumber: 'Nomor LP wajib diisi',
+ accidentDate: 'Tanggal Kejadian lalu lintas wajib diisi',
+ accidentNote: 'Keterangan Kejadian lalu lintas wajib diisi',
+ accidentProvince: 'Provinsi Kejadian lalu lintas wajib diisi',
+ accidentCity: 'Kota Kejadian lalu lintas wajib diisi',
+ accidentDistrict: 'Kecamatan Kejadian lalu lintas wajib diisi',
+ suplesi: 'Suplesi wajib diisi',
+ suplesiNumber: 'Nomor Suplesi wajib diisi',
+ classLevel: 'Kelas Rawat wajib diisi',
+ classLevelUpgrade: 'Kelas Rawat Naik wajib diisi',
+ classPaySource: 'Pembiayaan wajib diisi',
+ responsiblePerson: 'Penanggung Jawab wajib diisi',
+ },
+}
+
+const IntegrationBpjsSchema = z
+ .object({
+ sepDate: z.string({ required_error: ERROR_MESSAGES.required.sepDate }).min(1, ERROR_MESSAGES.required.sepDate),
+ serviceType: z
+ .string({ required_error: ERROR_MESSAGES.required.serviceType })
+ .min(1, ERROR_MESSAGES.required.serviceType)
+ .optional(),
+ admissionType: z
+ .string({ required_error: ERROR_MESSAGES.required.admissionType })
+ .min(1, ERROR_MESSAGES.required.admissionType),
+ cardNumber: z
+ .string({ required_error: ERROR_MESSAGES.required.cardNumber })
+ .min(1, ERROR_MESSAGES.required.cardNumber),
+ nationalId: z
+ .string({ required_error: ERROR_MESSAGES.required.nationalId })
+ .min(1, ERROR_MESSAGES.required.nationalId),
+ medicalRecordNumber: z
+ .string({ required_error: ERROR_MESSAGES.required.medicalRecordNumber })
+ .min(1, ERROR_MESSAGES.required.medicalRecordNumber),
+ patientName: z
+ .string({ required_error: ERROR_MESSAGES.required.patientName })
+ .min(1, ERROR_MESSAGES.required.patientName),
+ phoneNumber: z
+ .string({ required_error: ERROR_MESSAGES.required.phoneNumber })
+ .min(1, ERROR_MESSAGES.required.phoneNumber),
+ referralLetterNumber: z
+ .string({ required_error: ERROR_MESSAGES.required.referralLetterNumber })
+ .min(1, ERROR_MESSAGES.required.referralLetterNumber).optional(),
+ referralLetterDate: z
+ .string({ required_error: ERROR_MESSAGES.required.referralLetterDate })
+ .min(1, ERROR_MESSAGES.required.referralLetterDate).optional(),
+ fromClinic: z
+ .string({ required_error: ERROR_MESSAGES.required.fromClinic })
+ .min(1, ERROR_MESSAGES.required.fromClinic)
+ .optional(),
+ destinationClinic: z
+ .string({ required_error: ERROR_MESSAGES.required.destinationClinic })
+ .min(1, ERROR_MESSAGES.required.destinationClinic),
+ attendingDoctor: z
+ .string({ required_error: ERROR_MESSAGES.required.attendingDoctor })
+ .min(1, ERROR_MESSAGES.required.attendingDoctor),
+ initialDiagnosis: z
+ .string({ required_error: ERROR_MESSAGES.required.initialDiagnosis })
+ .min(1, ERROR_MESSAGES.required.initialDiagnosis),
+ cob: z.string({ required_error: ERROR_MESSAGES.required.cob }).min(1, ERROR_MESSAGES.required.cob),
+ cataract: z.string({ required_error: ERROR_MESSAGES.required.cataract }).min(1, ERROR_MESSAGES.required.cataract),
+ clinicExcecutive: z
+ .string({ required_error: ERROR_MESSAGES.required.clinicExcecutive })
+ .min(1, ERROR_MESSAGES.required.clinicExcecutive),
+ subSpecialistId: z
+ .string({ required_error: ERROR_MESSAGES.required.subSpecialistId })
+ .min(1, ERROR_MESSAGES.required.subSpecialistId)
+ .optional(),
+ procedureType: z
+ .string({ required_error: ERROR_MESSAGES.required.procedureType })
+ .min(1, ERROR_MESSAGES.required.procedureType)
+ .optional(),
+ supportCode: z
+ .string({ required_error: ERROR_MESSAGES.required.supportCode })
+ .min(1, ERROR_MESSAGES.required.supportCode)
+ .optional(),
+ note: z.string({ required_error: ERROR_MESSAGES.required.note }).min(1, ERROR_MESSAGES.required.note).optional(),
+ trafficAccident: z
+ .string({ required_error: ERROR_MESSAGES.required.trafficAccident })
+ .min(1, ERROR_MESSAGES.required.trafficAccident)
+ .optional(),
+ purposeOfVisit: z
+ .string({ required_error: ERROR_MESSAGES.required.purposeOfVisit })
+ .min(1, ERROR_MESSAGES.required.purposeOfVisit)
+ .optional(),
+ serviceAssessment: z
+ .string({ required_error: ERROR_MESSAGES.required.serviceAssessment })
+ .min(1, ERROR_MESSAGES.required.serviceAssessment)
+ .optional(),
+ lpNumber: z.string({ required_error: ERROR_MESSAGES.required.lpNumber }).optional(),
+ accidentDate: z.string({ required_error: ERROR_MESSAGES.required.accidentDate }).optional(),
+ accidentNote: z.string({ required_error: ERROR_MESSAGES.required.accidentNote }).optional(),
+ accidentProvince: z.string({ required_error: ERROR_MESSAGES.required.accidentProvince }).optional(),
+ accidentCity: z.string({ required_error: ERROR_MESSAGES.required.accidentCity }).optional(),
+ accidentDistrict: z.string({ required_error: ERROR_MESSAGES.required.accidentDistrict }).optional(),
+ suplesi: z.string({ required_error: ERROR_MESSAGES.required.suplesi }).optional(),
+ suplesiNumber: z.string({ required_error: ERROR_MESSAGES.required.suplesiNumber }).optional(),
+ classLevel: z.string({ required_error: ERROR_MESSAGES.required.classLevel }).optional(),
+ classLevelUpgrade: z.string({ required_error: ERROR_MESSAGES.required.classLevelUpgrade }).optional(),
+ classPaySource: z.string({ required_error: ERROR_MESSAGES.required.classPaySource }).optional(),
+ responsiblePerson: z.string({ required_error: ERROR_MESSAGES.required.responsiblePerson }).optional(),
+ })
+ .refine(
+ (data) => {
+ if (data.trafficAccident && data.trafficAccident.trim() !== '') {
+ return data.accidentDate && data.accidentDate.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.accidentDate,
+ path: ['accidentDate'],
+ },
+ )
+ .refine(
+ (data) => {
+ if (data.trafficAccident && data.trafficAccident.trim() !== '') {
+ return data.accidentProvince && data.accidentProvince.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.accidentProvince,
+ path: ['accidentProvince'],
+ },
+ )
+ .refine(
+ (data) => {
+ if (data.trafficAccident && data.trafficAccident.trim() !== '') {
+ return data.accidentCity && data.accidentCity.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.accidentCity,
+ path: ['accidentCity'],
+ },
+ )
+ .refine(
+ (data) => {
+ if (data.trafficAccident && data.trafficAccident.trim() !== '') {
+ return data.accidentDistrict && data.accidentDistrict.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.accidentDistrict,
+ path: ['accidentDistrict'],
+ },
+ )
+ .refine(
+ (data) => {
+ if (data.trafficAccident && data.trafficAccident.trim() !== '') {
+ return data.suplesi && data.suplesi.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.suplesi,
+ path: ['suplesi'],
+ },
+ )
+ .refine(
+ (data) => {
+ if (data.trafficAccident && data.trafficAccident.trim() !== '' && data.suplesi?.trim() === 'yes') {
+ return data.suplesiNumber && data.suplesiNumber.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.suplesiNumber,
+ path: ['suplesiNumber'],
+ },
+ )
+ .refine(
+ (data) => {
+ if (data.serviceType === '1') {
+ return data.classLevel && data.classLevel.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.classLevel,
+ path: ['classLevel'],
+ },
+ )
+ .refine(
+ (data) => {
+ if (data.serviceType === '1') {
+ return data.classLevelUpgrade && data.classLevelUpgrade.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.classLevelUpgrade,
+ path: ['classLevelUpgrade'],
+ },
+ )
+ .refine(
+ (data) => {
+ if (data.serviceType === '1' && data.classLevelUpgrade?.trim() !== '') {
+ return data.classPaySource && data.classPaySource.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.classPaySource,
+ path: ['classPaySource'],
+ },
+ )
+ .refine(
+ (data) => {
+ if (data.serviceType === '1' && data.classPaySource?.trim() !== '') {
+ return data.responsiblePerson && data.responsiblePerson.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.responsiblePerson,
+ path: ['responsiblePerson'],
+ },
+ )
+
+type IntegrationBpjsFormData = z.infer
+
+export { IntegrationBpjsSchema }
+export type { IntegrationBpjsFormData }
diff --git a/app/schemas/integration-encounter.schema.ts b/app/schemas/integration-encounter.schema.ts
new file mode 100644
index 00000000..32327328
--- /dev/null
+++ b/app/schemas/integration-encounter.schema.ts
@@ -0,0 +1,133 @@
+import { z } from 'zod'
+
+const ERROR_MESSAGES = {
+ required: {
+ doctorId: 'Dokter wajib diisi',
+ registerDate: 'Tanggal Daftar wajib diisi',
+ paymentType: 'Jenis Pembayaran wajib diisi',
+ subSpecialistId: 'Subspesialis wajib diisi',
+ patientCategory: 'Kelompok Peserta wajib diisi',
+ cardNumber: 'No. Kartu BPJS wajib diisi',
+ sepType: 'Jenis SEP wajib diisi',
+ sepNumber: 'No. SEP wajib diisi',
+ },
+}
+
+const ACCEPTED_UPLOAD_TYPES = ['image/jpeg', 'image/png', 'application/pdf']
+
+const IntegrationEncounterSchema = z
+ .object({
+ // Patient data (readonly, populated from selected patient)
+ patientName: z.string().optional(),
+ nationalIdentity: z.string().optional(),
+ medicalRecordNumber: z.string().optional(),
+
+ // Visit data
+ doctorId: z
+ .string({ required_error: ERROR_MESSAGES.required.doctorId })
+ .min(1, ERROR_MESSAGES.required.doctorId),
+ subSpecialistId: z
+ .string({ required_error: ERROR_MESSAGES.required.subSpecialistId })
+ .min(1, ERROR_MESSAGES.required.subSpecialistId)
+ .optional(),
+ registerDate: z
+ .string({ required_error: ERROR_MESSAGES.required.registerDate })
+ .min(1, ERROR_MESSAGES.required.registerDate),
+ paymentType: z
+ .string({ required_error: ERROR_MESSAGES.required.paymentType })
+ .min(1, ERROR_MESSAGES.required.paymentType),
+
+ // BPJS related fields
+ patientCategory: z
+ .string()
+ .min(1, ERROR_MESSAGES.required.patientCategory)
+ .optional(),
+ cardNumber: z
+ .string()
+ .min(1, ERROR_MESSAGES.required.cardNumber)
+ .optional(),
+ sepType: z
+ .string()
+ .min(1, ERROR_MESSAGES.required.sepType)
+ .optional(),
+ sepNumber: z
+ .string()
+ .min(1, ERROR_MESSAGES.required.sepNumber)
+ .optional(),
+
+ // File uploads
+ sepFile: z
+ .any()
+ .optional()
+ .refine((f) => !f || f instanceof File, { message: 'Harus berupa file yang valid' })
+ .refine((f) => !f || ACCEPTED_UPLOAD_TYPES.includes(f.type), {
+ message: 'Format file harus JPG, PNG, atau PDF',
+ })
+ .refine((f) => !f || f.size <= 1 * 1024 * 1024, { message: 'Maksimal 1MB' }),
+ sippFile: z
+ .any()
+ .optional()
+ .refine((f) => !f || f instanceof File, { message: 'Harus berupa file yang valid' })
+ .refine((f) => !f || ACCEPTED_UPLOAD_TYPES.includes(f.type), {
+ message: 'Format file harus JPG, PNG, atau PDF',
+ })
+ .refine((f) => !f || f.size <= 1 * 1024 * 1024, { message: 'Maksimal 1MB' }),
+ })
+ .refine(
+ (data) => {
+ // If payment type is jkn, then patient category is required
+ if (data.paymentType === 'jkn') {
+ return data.patientCategory && data.patientCategory.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.patientCategory,
+ path: ['patientCategory'],
+ },
+ )
+ .refine(
+ (data) => {
+ // If payment type is jkn, then card number is required
+ if (data.paymentType === 'jkn') {
+ return data.cardNumber && data.cardNumber.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.cardNumber,
+ path: ['cardNumber'],
+ },
+ )
+ .refine(
+ (data) => {
+ // If payment type is jkn, then SEP type is required
+ if (data.paymentType === 'jkn') {
+ return data.sepType && data.sepType.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.sepType,
+ path: ['sepType'],
+ },
+ )
+ .refine(
+ (data) => {
+ // If payment type is jkn and SEP type is selected, then SEP number is required
+ if (data.paymentType === 'jkn' && data.sepType && data.sepType.trim() !== '') {
+ return data.sepNumber && data.sepNumber.trim() !== ''
+ }
+ return true
+ },
+ {
+ message: ERROR_MESSAGES.required.sepNumber,
+ path: ['sepNumber'],
+ },
+ )
+
+type IntegrationEncounterFormData = z.infer
+
+export { IntegrationEncounterSchema }
+export type { IntegrationEncounterFormData }
+
diff --git a/app/schemas/prescription-item.schema.ts b/app/schemas/prescription-item.schema.ts
new file mode 100644
index 00000000..7c3ca7d3
--- /dev/null
+++ b/app/schemas/prescription-item.schema.ts
@@ -0,0 +1,10 @@
+import { z } from 'zod'
+import type { PrescriptionItem } from '~/models/prescription-item'
+
+const PrescriptionItemSchema = z.object({
+})
+
+type PrescriptionItemFormData = z.infer & PrescriptionItem
+
+export { PrescriptionItemSchema }
+export type { PrescriptionItemFormData }
diff --git a/app/schemas/prescription.schema.ts b/app/schemas/prescription.schema.ts
new file mode 100644
index 00000000..1e23f642
--- /dev/null
+++ b/app/schemas/prescription.schema.ts
@@ -0,0 +1,11 @@
+import { z } from 'zod'
+import type { Prescription } from '~/models/prescription'
+
+const PrescriptionSchema = z.object({
+ 'encounter-id': z.number().nullable().optional(),
+})
+
+type PrescriptionFormData = z.infer & Prescription
+
+export { PrescriptionSchema }
+export type { PrescriptionFormData }
diff --git a/app/schemas/specialist-position.schema.ts b/app/schemas/specialist-position.schema.ts
new file mode 100644
index 00000000..7aacef37
--- /dev/null
+++ b/app/schemas/specialist-position.schema.ts
@@ -0,0 +1,24 @@
+import { z } from 'zod'
+import type { SpecialistPosition } from '~/models/specialist-position'
+
+const SpecialistPositionSchema = z.object({
+ code: z.string({ required_error: 'Kode harus diisi' }).min(1, 'Kode minimum 1 karakter'),
+ name: z.string({ required_error: 'Nama harus diisi' }).min(1, 'Nama minimum 1 karakter'),
+ headStatus: z.boolean().optional().nullable(),
+ specialist_id: z
+ .union([
+ z.string({ required_error: 'Spesialis harus diisi' }),
+ z.number({ required_error: 'Spesialis harus diisi' }),
+ ])
+ .optional()
+ .nullable(),
+ employee_id: z
+ .union([z.string({ required_error: 'Karyawan harus diisi' }), z.number({ required_error: 'Karyawan harus diisi' })])
+ .optional()
+ .nullable(),
+})
+
+type SpecialistPositionFormData = z.infer & Partial
+
+export { SpecialistPositionSchema }
+export type { SpecialistPositionFormData }
diff --git a/app/schemas/subspecialist-position.schema.ts b/app/schemas/subspecialist-position.schema.ts
new file mode 100644
index 00000000..7f458e7b
--- /dev/null
+++ b/app/schemas/subspecialist-position.schema.ts
@@ -0,0 +1,24 @@
+import { z } from 'zod'
+import type { SubSpecialistPosition } from '~/models/subspecialist-position'
+
+const SubSpecialistPositionSchema = z.object({
+ code: z.string({ required_error: 'Kode harus diisi' }).min(1, 'Kode minimum 1 karakter'),
+ name: z.string({ required_error: 'Nama harus diisi' }).min(1, 'Nama minimum 1 karakter'),
+ headStatus: z.boolean().optional().nullable(),
+ subspecialist_id: z
+ .union([
+ z.string({ required_error: 'Spesialis harus diisi' }),
+ z.number({ required_error: 'Spesialis harus diisi' }),
+ ])
+ .optional()
+ .nullable(),
+ employee_id: z
+ .union([z.string({ required_error: 'Karyawan harus diisi' }), z.number({ required_error: 'Karyawan harus diisi' })])
+ .optional()
+ .nullable(),
+})
+
+type SubSpecialistPositionFormData = z.infer & Partial
+
+export { SubSpecialistPositionSchema }
+export type { SubSpecialistPositionFormData }
diff --git a/app/schemas/unit-position.schema.ts b/app/schemas/unit-position.schema.ts
new file mode 100644
index 00000000..2422b9a1
--- /dev/null
+++ b/app/schemas/unit-position.schema.ts
@@ -0,0 +1,24 @@
+import { z } from 'zod'
+import type { UnitPosition } from '~/models/unit-position'
+
+const UnitPositionSchema = z.object({
+ code: z.string({ required_error: 'Kode harus diisi' }).min(1, 'Kode minimum 1 karakter'),
+ name: z.string({ required_error: 'Nama harus diisi' }).min(1, 'Nama minimum 1 karakter'),
+ headStatus: z.boolean().optional().nullable(),
+ unit_id: z
+ .union([
+ z.string({ required_error: 'Unit Induk harus diisi' }),
+ z.number({ required_error: 'Unit Induk harus diisi' }),
+ ])
+ .optional()
+ .nullable(),
+ employee_id: z
+ .union([z.string({ required_error: 'Karyawan harus diisi' }), z.number({ required_error: 'Karyawan harus diisi' })])
+ .optional()
+ .nullable(),
+})
+
+type UnitPositionFormData = z.infer & Partial
+
+export { UnitPositionSchema }
+export type { UnitPositionFormData }
diff --git a/app/services/control-letter.service.ts b/app/services/control-letter.service.ts
new file mode 100644
index 00000000..29b3722b
--- /dev/null
+++ b/app/services/control-letter.service.ts
@@ -0,0 +1,28 @@
+// Base
+import * as base from './_crud-base'
+
+// Constants
+import { encounterClassCodes } from '~/lib/constants'
+
+const path = '/api/v1/control-letter'
+const name = 'control-letter'
+
+export function create(data: any) {
+ return base.create(path, data, name)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export function getDetail(id: number | string, params?: any) {
+ return base.getDetail(path, id, name, params)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data, name)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id, name)
+}
\ No newline at end of file
diff --git a/app/services/doctor.service.ts b/app/services/doctor.service.ts
index 64ab22e9..e6ae0051 100644
--- a/app/services/doctor.service.ts
+++ b/app/services/doctor.service.ts
@@ -3,7 +3,7 @@ import * as base from './_crud-base'
import type { Doctor } from "~/models/doctor";
const path = '/api/v1/doctor'
-const name = 'device'
+const name = 'doctor'
export function create(data: any) {
return base.create(path, data, name)
@@ -25,14 +25,16 @@ export function remove(id: number | string) {
return base.remove(path, id, name)
}
-export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+export async function getValueLabelList(params: any = null, useCodeAsValue = false): Promise<{ value: string; label: string }[]> {
let data: { value: string; label: string }[] = []
const result = await getList(params)
if (result.success) {
const resultData = result.body?.data || []
data = resultData.map((item: Doctor) => ({
- value: item.id,
- label: item.employee.person.name,
+ value: useCodeAsValue ? item.code
+ : item.id ? Number(item.id)
+ : item.id,
+ label: item.employee?.person?.name || '',
}))
}
return data
diff --git a/app/services/employee.service.ts b/app/services/employee.service.ts
index 366ef71e..3121e7a2 100644
--- a/app/services/employee.service.ts
+++ b/app/services/employee.service.ts
@@ -1,4 +1,5 @@
// Base
+import type { Employee } from '~/models/employee'
import * as base from './_crud-base'
const path = '/api/v1/employee'
@@ -29,9 +30,9 @@ export async function getValueLabelList(params: any = null): Promise<{ value: st
const result = await getList(params)
if (result.success) {
const resultData = result.body?.data || []
- data = resultData.map((item: any) => ({
- value: item.id ? Number(item.id) : item.code,
- label: item.person.name,
+ data = resultData.map((item: Employee) => ({
+ value: item.id,
+ label: `${item.person.frontTitle} ${item.person.name} ${item.person.endTitle}`.trim(),
}))
}
return data
diff --git a/app/services/general-consent.service.ts b/app/services/general-consent.service.ts
new file mode 100644
index 00000000..2a6611fc
--- /dev/null
+++ b/app/services/general-consent.service.ts
@@ -0,0 +1,23 @@
+import * as base from './_crud-base'
+
+const path = '/api/v1/general-consent'
+
+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/installation-position.service.ts b/app/services/installation-position.service.ts
new file mode 100644
index 00000000..13d5e914
--- /dev/null
+++ b/app/services/installation-position.service.ts
@@ -0,0 +1,41 @@
+// Base
+import * as base from './_crud-base'
+
+// Types
+import type { Installation } from '~/models/installation'
+
+const path = '/api/v1/installation-position'
+const name = 'installation'
+
+export function create(data: any) {
+ return base.create(path, data, name)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export function getDetail(id: number | string) {
+ return base.getDetail(path, id, name)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data, name)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id, name)
+}
+
+export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+ let data: { value: string; label: string }[] = []
+ const result = await getList(params)
+ if (result.success) {
+ const resultData = result.body?.data || []
+ data = resultData.map((item: Installation) => ({
+ value: item.id ? Number(item.id) : item.code,
+ label: item.name,
+ }))
+ }
+ return data
+}
diff --git a/app/services/mcu-order-item.service.ts b/app/services/mcu-order-item.service.ts
new file mode 100644
index 00000000..b7ffbbfe
--- /dev/null
+++ b/app/services/mcu-order-item.service.ts
@@ -0,0 +1,24 @@
+import * as base from './_crud-base'
+
+const path = '/api/v1/mcu-order-item'
+const name = 'mcu-order-item'
+
+export function create(data: any) {
+ return base.create(path, data)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params)
+}
+
+export function getDetail(id: number | string, params?: any) {
+ return base.getDetail(path, id, name, params)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id)
+}
diff --git a/app/services/mcu-order.service.ts b/app/services/mcu-order.service.ts
new file mode 100644
index 00000000..77e023d7
--- /dev/null
+++ b/app/services/mcu-order.service.ts
@@ -0,0 +1,24 @@
+import * as base from './_crud-base'
+
+const path = '/api/v1/mcu-order'
+const name = 'mcu-order'
+
+export function create(data: any) {
+ return base.create(path, data)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params)
+}
+
+export function getDetail(id: number | string, params?: any) {
+ return base.getDetail(path, id, name, params)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id)
+}
diff --git a/app/services/mcu-src-category.service.ts b/app/services/mcu-src-category.service.ts
new file mode 100644
index 00000000..c154b1dc
--- /dev/null
+++ b/app/services/mcu-src-category.service.ts
@@ -0,0 +1,25 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/v1/mcu-src-category'
+const name = 'mcu-src-category'
+
+export function create(data: any) {
+ return base.create(path, data, name)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export function getDetail(id: number | string) {
+ return base.getDetail(path, id, name)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data, name)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id, name)
+}
diff --git a/app/services/mcu-src.service.ts b/app/services/mcu-src.service.ts
new file mode 100644
index 00000000..a7a466b8
--- /dev/null
+++ b/app/services/mcu-src.service.ts
@@ -0,0 +1,25 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/v1/mcu-src'
+const name = 'mcu-src'
+
+export function create(data: any) {
+ return base.create(path, data, name)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export function getDetail(id: number | string) {
+ return base.getDetail(path, id, name)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data, name)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id, name)
+}
diff --git a/app/services/patient.service.ts b/app/services/patient.service.ts
index 7591f356..6a7742c3 100644
--- a/app/services/patient.service.ts
+++ b/app/services/patient.service.ts
@@ -40,6 +40,22 @@ export async function getPatientDetail(id: number) {
}
}
+export async function getPatientByIdentifier(search: string) {
+ try {
+ const urlPath = search.length === 16 ? `by-resident-identity/search=${encodeURIComponent(search)}` : `/search/${search}`
+ const url = `${mainUrl}/${urlPath}`
+ const resp = await xfetch(url, 'GET')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ result.type = urlPath.includes('by-resident-identity') ? 'resident-identity' : 'identity'
+ return result
+ } catch (error) {
+ console.error('Error fetching patient by identifier:', error)
+ throw new Error('Failed to get patient by identifier')
+ }
+}
+
export async function postPatient(record: any) {
try {
const resp = await xfetch(mainUrl, 'POST', record)
diff --git a/app/services/prescription-item.service.ts b/app/services/prescription-item.service.ts
new file mode 100644
index 00000000..22649e14
--- /dev/null
+++ b/app/services/prescription-item.service.ts
@@ -0,0 +1,23 @@
+import * as base from './_crud-base'
+
+const path = '/api/v1/prescription-item'
+
+export function create(data: any) {
+ return base.create(path, data)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params)
+}
+
+export function getDetail(id: number | string) {
+ return base.getDetail(path, id)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id)
+}
diff --git a/app/services/prescription.service.ts b/app/services/prescription.service.ts
new file mode 100644
index 00000000..150357ab
--- /dev/null
+++ b/app/services/prescription.service.ts
@@ -0,0 +1,24 @@
+import * as base from './_crud-base'
+
+const path = '/api/v1/prescription'
+const name = 'prescription'
+
+export function create(data: any) {
+ return base.create(path, data)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params)
+}
+
+export function getDetail(id: number | string, params?: any) {
+ return base.getDetail(path, id, name, params)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id)
+}
diff --git a/app/services/specialist-position.service.ts b/app/services/specialist-position.service.ts
new file mode 100644
index 00000000..6966ca60
--- /dev/null
+++ b/app/services/specialist-position.service.ts
@@ -0,0 +1,25 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/v1/specialist-position'
+const name = 'specialist-position'
+
+export function create(data: any) {
+ return base.create(path, data, name)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export function getDetail(id: number | string) {
+ return base.getDetail(path, id, name)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data, name)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id, name)
+}
diff --git a/app/services/specialist.service.ts b/app/services/specialist.service.ts
index c2c34e3f..d4c81b5c 100644
--- a/app/services/specialist.service.ts
+++ b/app/services/specialist.service.ts
@@ -3,6 +3,7 @@ import * as base from './_crud-base'
// Types
import type { Specialist } from '~/models/specialist'
+import type { TreeItem } from '~/models/_base'
const path = '/api/v1/specialist'
const name = 'specialist'
@@ -15,8 +16,8 @@ export function getList(params: any = null) {
return base.getList(path, params, name)
}
-export function getDetail(id: number | string) {
- return base.getDetail(path, id, name)
+export function getDetail(id: number | string, params?: any) {
+ return base.getDetail(path, id, name, params)
}
export function update(id: number | string, data: any) {
@@ -27,16 +28,35 @@ export function remove(id: number | string) {
return base.remove(path, id, name)
}
-export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+export async function getValueLabelList(params: any = null, useCodeAsValue = false): Promise<{ value: string; label: string }[]> {
let data: { value: string; label: string }[] = []
const result = await getList(params)
if (result.success) {
const resultData = result.body?.data || []
data = resultData.map((item: Specialist) => ({
- value: item.id ? Number(item.id) : item.code,
+ value: useCodeAsValue ? item.code
+ : item.id ? Number(item.id)
+ : item.id,
label: item.name,
parent: item.unit_id ? Number(item.unit_id) : null,
}))
}
return data
}
+
+/**
+ * Convert specialist response to TreeItem[] with subspecialist children
+ * @param specialists Array of specialist objects from API
+ * @returns TreeItem[]
+ */
+export function getValueTreeItems(specialists: any[], byCode = true): TreeItem[] {
+ return specialists.map((specialist: Specialist) => ({
+ value: byCode ? String(specialist.code) : String(specialist.id),
+ label: specialist.name,
+ hasChildren: Array.isArray(specialist.subspecialists) && specialist.subspecialists.length > 0,
+ children:
+ Array.isArray(specialist.subspecialists) && specialist.subspecialists.length > 0
+ ? getValueTreeItems(specialist.subspecialists)
+ : undefined,
+ }))
+}
diff --git a/app/services/subspecialist-position.service.ts b/app/services/subspecialist-position.service.ts
new file mode 100644
index 00000000..9653100b
--- /dev/null
+++ b/app/services/subspecialist-position.service.ts
@@ -0,0 +1,25 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/v1/subspecialist-position'
+const name = 'subspecialist-position'
+
+export function create(data: any) {
+ return base.create(path, data, name)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export function getDetail(id: number | string) {
+ return base.getDetail(path, id, name)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data, name)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id, name)
+}
diff --git a/app/services/subspecialist.service.ts b/app/services/subspecialist.service.ts
index 94e70a09..f13c715f 100644
--- a/app/services/subspecialist.service.ts
+++ b/app/services/subspecialist.service.ts
@@ -15,8 +15,8 @@ export function getList(params: any = null) {
return base.getList(path, params, name)
}
-export function getDetail(id: number | string) {
- return base.getDetail(path, id, name)
+export function getDetail(id: number | string, params?: any) {
+ return base.getDetail(path, id, name, params)
}
export function update(id: number | string, data: any) {
@@ -27,13 +27,15 @@ export function remove(id: number | string) {
return base.remove(path, id, name)
}
-export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+export async function getValueLabelList(params: any = null, useCodeAsValue = false): Promise<{ value: string; label: string }[]> {
let data: { value: string; label: string }[] = []
const result = await getList(params)
if (result.success) {
const resultData = result.body?.data || []
data = resultData.map((item: Subspecialist) => ({
- value: item.id ? Number(item.id) : item.code,
+ value: useCodeAsValue ? item.code
+ : item.id ? Number(item.id)
+ : item.id,
label: item.name,
parent: item.specialist_id ? Number(item.specialist_id) : null,
}))
diff --git a/app/services/unit-position.service.ts b/app/services/unit-position.service.ts
new file mode 100644
index 00000000..ee9cf89c
--- /dev/null
+++ b/app/services/unit-position.service.ts
@@ -0,0 +1,25 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/v1/unit-position'
+const name = 'unit-position'
+
+export function create(data: any) {
+ return base.create(path, data, name)
+}
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export function getDetail(id: number | string) {
+ return base.getDetail(path, id, name)
+}
+
+export function update(id: number | string, data: any) {
+ return base.update(path, id, data, name)
+}
+
+export function remove(id: number | string) {
+ return base.remove(path, id, name)
+}
diff --git a/app/services/unit.service.ts b/app/services/unit.service.ts
index 438625f1..402504b6 100644
--- a/app/services/unit.service.ts
+++ b/app/services/unit.service.ts
@@ -2,7 +2,7 @@
import * as base from './_crud-base'
// Types
-import type { Unit } from "~/models/unit";
+import type { Unit } from '~/models/unit'
const path = '/api/v1/unit'
const name = 'unit'
@@ -27,13 +27,15 @@ export function remove(id: number | string) {
return base.remove(path, id, name)
}
-export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+export async function getValueLabelList(params: any = null, useCodeAsValue = false): Promise<{ value: string; label: string }[]> {
let data: { value: string; label: string }[] = []
const result = await getList(params)
if (result.success) {
const resultData = result.body?.data || []
data = resultData.map((item: Unit) => ({
- value: item.id,
+ value: useCodeAsValue ? item.code
+ : item.id ? Number(item.id)
+ : item.id,
label: item.name,
}))
}
diff --git a/app/services/vclaim-control-letter.service.ts b/app/services/vclaim-control-letter.service.ts
new file mode 100644
index 00000000..007e91c5
--- /dev/null
+++ b/app/services/vclaim-control-letter.service.ts
@@ -0,0 +1,29 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim-swagger/RencanaKontrol'
+const name = 'rencana-kontrol'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.letterNumber && params.mode === 'by-control') {
+ url += `/noSuratKontrol/${params.letterNumber}`
+ }
+ if (params?.letterNumber && params.mode === 'by-card') {
+ url += `/noka/${params.letterNumber}`
+ }
+ if (params?.letterNumber && params.mode === 'by-sep') {
+ url += `/${params.letterNumber}`
+ }
+ if (params?.letterNumber && params.mode === 'by-schedule') {
+ url += `/jadwalDokter?jeniskontrol=${params.controlType}&kodepoli=${params.poliCode}&tanggalkontrol=${params.controlDate}`
+ delete params.controlType
+ delete params.poliCode
+ delete params.controlDate
+ }
+ if (params) {
+ delete params.letterNumber
+ delete params.mode
+ }
+ return base.getList(url, params, name)
+}
\ No newline at end of file
diff --git a/app/services/vclaim-diagnose-referral.service.ts b/app/services/vclaim-diagnose-referral.service.ts
new file mode 100644
index 00000000..34b94780
--- /dev/null
+++ b/app/services/vclaim-diagnose-referral.service.ts
@@ -0,0 +1,9 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/reference/diagnose-prb'
+const name = 'diagnose-referral'
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
diff --git a/app/services/vclaim-diagnose.service.ts b/app/services/vclaim-diagnose.service.ts
new file mode 100644
index 00000000..a676f516
--- /dev/null
+++ b/app/services/vclaim-diagnose.service.ts
@@ -0,0 +1,28 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/reference/diagnose'
+const name = 'diagnose'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params && params?.diagnosa) {
+ url += `/${params.diagnosa}`
+ delete params.diagnosa
+ }
+ return base.getList(url, params, name)
+}
+
+export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+ let data: { value: string; label: string }[] = []
+ const result = await getList(params)
+ if (result.success) {
+ const resultData = result.body?.response?.diagnosa || []
+ const resultUnique = [...new Map(resultData.map((item: any) => [item.kode, item])).values()]
+ data = resultUnique.map((item: any) => ({
+ value: item.kode ? String(item.kode) : '',
+ label: `${item.kode} - ${item.nama}`,
+ }))
+ }
+ return data
+}
diff --git a/app/services/vclaim-doctor.service.ts b/app/services/vclaim-doctor.service.ts
new file mode 100644
index 00000000..0d5ec9dc
--- /dev/null
+++ b/app/services/vclaim-doctor.service.ts
@@ -0,0 +1,36 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/reference/responsible-doctor'
+const name = 'responsible-doctor'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.serviceType) {
+ url += `/${params.serviceType}`
+ delete params.serviceType
+ }
+ if (params?.serviceDate) {
+ url += `/${params.serviceDate}`
+ delete params.serviceDate
+ }
+ if (params?.specialistCode || (Number(params.specialistCode) === 0)) {
+ url += `/${params.specialistCode}`
+ delete params.specialistCode
+ }
+ return base.getList(url, params, name)
+}
+
+export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+ let data: { value: string; label: string }[] = []
+ const result = await getList(params)
+ if (result.success) {
+ const resultData = result.body?.response?.list || []
+ const resultUnique = [...new Map(resultData.map((item: any) => [item.kode, item])).values()]
+ data = resultUnique.map((item: any) => ({
+ value: item.kode ? String(item.kode) : '',
+ label: `${item.kode} - ${item.nama}`,
+ }))
+ }
+ return data
+}
diff --git a/app/services/vclaim-healthcare.service.ts b/app/services/vclaim-healthcare.service.ts
new file mode 100644
index 00000000..09cc0089
--- /dev/null
+++ b/app/services/vclaim-healthcare.service.ts
@@ -0,0 +1,32 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/reference/healthcare'
+const name = 'healthcare'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.healthcare) {
+ url += `/${params.healthcare}`
+ delete params.healthcare
+ }
+ if (params?.healthcareType) {
+ url += `/${params.healthcareType}`
+ delete params.healthcareType
+ }
+ return base.getList(url, params, name)
+}
+
+export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+ let data: { value: string; label: string }[] = []
+ const result = await getList(params)
+ if (result.success) {
+ const resultData = result.body?.response?.faskes || []
+ const resultUnique = [...new Map(resultData.map((item: any) => [item.kode, item])).values()]
+ data = resultUnique.map((item: any) => ({
+ value: item.kode ? String(item.kode) : '',
+ label: `${item.kode} - ${item.nama}`,
+ }))
+ }
+ return data
+}
diff --git a/app/services/vclaim-medicine.service.ts b/app/services/vclaim-medicine.service.ts
new file mode 100644
index 00000000..15a42050
--- /dev/null
+++ b/app/services/vclaim-medicine.service.ts
@@ -0,0 +1,22 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/reference/medicine'
+const name = 'medicine'
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+ let data: { value: string; label: string }[] = []
+ const result = await getList(params)
+ if (result.success) {
+ const resultData = result.body?.response?.list || []
+ data = resultData.map((item: any) => ({
+ value: item.kode ? String(item.kode) : '',
+ label: item.nama,
+ }))
+ }
+ return data
+}
diff --git a/app/services/vclaim-member.service.ts b/app/services/vclaim-member.service.ts
new file mode 100644
index 00000000..bbe054ec
--- /dev/null
+++ b/app/services/vclaim-member.service.ts
@@ -0,0 +1,21 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/member'
+const name = 'member'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.number && params.mode === 'by-identity') {
+ url += `/nik/${params.number}/${params.date}`
+ }
+ if (params?.number && params.mode === 'by-card') {
+ url += `/bpjs/${params.number}/${params.date}`
+ }
+ if (params) {
+ delete params.number
+ delete params.mode
+ delete params.date
+ }
+ return base.getList(url, params, name)
+}
diff --git a/app/services/vclaim-monitoring-history.service.ts b/app/services/vclaim-monitoring-history.service.ts
new file mode 100644
index 00000000..ac9f2113
--- /dev/null
+++ b/app/services/vclaim-monitoring-history.service.ts
@@ -0,0 +1,17 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/monitoring/hist'
+const name = 'monitoring-history'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params && params?.cardNumber) {
+ url += `/${params.cardNumber}/${params.startDate}/${params.endDate}`
+ delete params.cardNumber
+ delete params.startDate
+ delete params.endDate
+ }
+
+ return base.getList(url, params, name)
+}
diff --git a/app/services/vclaim-monitoring-visit.service.ts b/app/services/vclaim-monitoring-visit.service.ts
new file mode 100644
index 00000000..0c5da64e
--- /dev/null
+++ b/app/services/vclaim-monitoring-visit.service.ts
@@ -0,0 +1,71 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/monitoring/visit'
+const name = 'monitoring-visit'
+
+const dummyResponse = {
+ metaData: {
+ code: '200',
+ message: 'Sukses',
+ },
+ response: {
+ sep: [
+ {
+ diagnosa: 'K65.0',
+ jnsPelayanan: 'R.Inap',
+ kelasRawat: '2',
+ nama: 'HANIF ABDURRAHMAN',
+ noKartu: '0001819122189',
+ noSep: '0301R00110170000004',
+ noRujukan: '0301U01108180200084',
+ poli: null,
+ tglPlgSep: '2017-10-03',
+ tglSep: '2017-10-01',
+ },
+ {
+ diagnosa: 'I50.0',
+ jnsPelayanan: 'R.Inap',
+ kelasRawat: '3',
+ nama: 'ASRIZAL',
+ noKartu: '0002283324674',
+ noSep: '0301R00110170000005',
+ noRujukan: '0301U01108180200184',
+ poli: null,
+ tglPlgSep: '2017-10-10',
+ tglSep: '2017-10-01',
+ },
+ ],
+ },
+}
+
+export async function getList(params: any = null) {
+ try {
+ let url = path
+ if (params?.date && params.serviceType) {
+ url += `/${params.date}/${params.serviceType}`
+ }
+ if (params) {
+ delete params.date
+ delete params.serviceType
+ }
+ const resp = await base.getList(url, params, name)
+
+ // Jika success false, return dummy response
+ if (!resp.success || !resp.body?.response) {
+ return {
+ success: true,
+ body: dummyResponse,
+ }
+ }
+
+ return resp
+ } catch (error) {
+ // Jika terjadi error, return dummy response
+ console.error(`Error fetching ${name}s:`, error)
+ return {
+ success: true,
+ body: dummyResponse,
+ }
+ }
+}
diff --git a/app/services/vclaim-reference-hospital-letter.service.ts b/app/services/vclaim-reference-hospital-letter.service.ts
new file mode 100644
index 00000000..115f6558
--- /dev/null
+++ b/app/services/vclaim-reference-hospital-letter.service.ts
@@ -0,0 +1,16 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim-swagger/Rujukan/RS'
+const name = 'rujukan-rumah-sakit'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.letterNumber) {
+ url += `/${params.letterNumber}`
+ }
+ if (params) {
+ delete params.letterNumber
+ }
+ return base.getList(url, params, name)
+}
\ No newline at end of file
diff --git a/app/services/vclaim-reference-letter.service.ts b/app/services/vclaim-reference-letter.service.ts
new file mode 100644
index 00000000..0a721d19
--- /dev/null
+++ b/app/services/vclaim-reference-letter.service.ts
@@ -0,0 +1,16 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim-swagger/RujukanKhusus'
+const name = 'rujukan-khusus'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.letterNumber) {
+ url += `?noRujukan=${params.letterNumber}`
+ }
+ if (params) {
+ delete params.letterNumber
+ }
+ return base.getList(url, params, name)
+}
\ No newline at end of file
diff --git a/app/services/vclaim-region-city.service.ts b/app/services/vclaim-region-city.service.ts
new file mode 100644
index 00000000..4ebfca20
--- /dev/null
+++ b/app/services/vclaim-region-city.service.ts
@@ -0,0 +1,27 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/reference/regency'
+const name = 'cities'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.province) {
+ url += `/${params.province}`
+ delete params.province
+ }
+ return base.getList(url, params, name)
+}
+
+export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+ let data: { value: string; label: string }[] = []
+ const result = await getList(params)
+ if (result.success) {
+ const resultData = result.body?.response?.list || []
+ data = resultData.map((item: any) => ({
+ value: item.kode ? String(item.kode) : '',
+ label: item.nama,
+ }))
+ }
+ return data
+}
diff --git a/app/services/vclaim-region-district.service.ts b/app/services/vclaim-region-district.service.ts
new file mode 100644
index 00000000..0b0585a8
--- /dev/null
+++ b/app/services/vclaim-region-district.service.ts
@@ -0,0 +1,27 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/reference/district'
+const name = 'districts'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.city) {
+ url += `/${params.city}`
+ delete params.city
+ }
+ return base.getList(url, params, name)
+}
+
+export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+ let data: { value: string; label: string }[] = []
+ const result = await getList(params)
+ if (result.success) {
+ const resultData = result.body?.response?.list || []
+ data = resultData.map((item: any) => ({
+ value: item.kode ? String(item.kode) : '',
+ label: item.nama,
+ }))
+ }
+ return data
+}
diff --git a/app/services/vclaim-region-province.service.ts b/app/services/vclaim-region-province.service.ts
new file mode 100644
index 00000000..5d58bb26
--- /dev/null
+++ b/app/services/vclaim-region-province.service.ts
@@ -0,0 +1,22 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/reference/province'
+const name = 'provinces'
+
+export function getList(params: any = null) {
+ return base.getList(path, params, name)
+}
+
+export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+ let data: { value: string; label: string }[] = []
+ const result = await getList(params)
+ if (result.success) {
+ const resultData = result.body?.response?.list || []
+ data = resultData.map((item: any) => ({
+ value: item.kode ? String(item.kode) : '',
+ label: item.nama,
+ }))
+ }
+ return data
+}
diff --git a/app/services/vclaim-sep.service.ts b/app/services/vclaim-sep.service.ts
new file mode 100644
index 00000000..fdccc9c4
--- /dev/null
+++ b/app/services/vclaim-sep.service.ts
@@ -0,0 +1,95 @@
+// Base
+import * as base from './_crud-base'
+
+// Types
+import type { IntegrationBpjsFormData } from '~/schemas/integration-bpjs.schema'
+
+const path = '/api/vclaim-swagger/sep'
+const name = 'sep'
+
+export function create(data: any) {
+ return base.create(path, data, name)
+}
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.number) {
+ url += `/${params.number}`
+ delete params.number
+ }
+ return base.getList(url, params, name)
+}
+
+export function makeSepData(
+ data: IntegrationBpjsFormData & {
+ referralFrom?: string
+ referralTo?: string
+ referralLetterDate?: string
+ referralLetterNumber?: string
+ },
+) {
+ const content = {
+ noKartu: data.cardNumber || '',
+ tglSep: data.sepDate,
+ ppkPelayanan: data.fromClinic || '',
+ jnsPelayanan: data.admissionType ? String(data.admissionType) : '1',
+ noMR: data.medicalRecordNumber || '',
+ catatan: data.note || '',
+ diagAwal: data.initialDiagnosis || '',
+ poli: {
+ tujuan: data.destinationClinic || '',
+ eksekutif: data.clinicExcecutive === 'yes' ? '1' : '0',
+ },
+ cob: {
+ cob: data.cob === 'yes' ? '1' : '0',
+ },
+ katarak: {
+ katarak: data.cataract === 'yes' ? '1' : '0',
+ },
+ tujuanKunj: data.purposeOfVisit || '',
+ flagProcedure: data.procedureType || '',
+ kdPenunjang: data.supportCode || '',
+ assesmentPel: data.serviceAssessment || '',
+ skdp: {
+ noSurat: ['3'].includes(data.admissionType) ? data.referralLetterNumber : '',
+ kodeDPJP: ['3'].includes(data.admissionType)? data.attendingDoctor : '',
+ },
+ rujukan: {
+ asalRujukan: ['2'].includes(data.admissionType) ? data?.referralFrom || '' : '',
+ tglRujukan: ['2'].includes(data.admissionType) ? data?.referralLetterDate || '' : '',
+ noRujukan: ['2'].includes(data.admissionType) ? data?.referralLetterNumber || '' : '',
+ ppkRujukan: ['2'].includes(data.admissionType) ? data?.referralTo || '' : '',
+ },
+ klsRawat: {
+ klsRawatHak: data.classLevel || '',
+ klsRawatNaik: data.classLevelUpgrade || '',
+ pembiayaan: data.classPaySource || '',
+ penanggungJawab: data.responsiblePerson || '',
+ },
+ dpjpLayan: data.attendingDoctor || '',
+ noTelp: data.phoneNumber || '',
+ user: data.patientName || '',
+ jaminan: {
+ lakaLantas: data.trafficAccident || '0',
+ noLP: data.lpNumber || '',
+ penjamin: {
+ tglKejadian: data.accidentDate || '',
+ keterangan: data.accidentNote || '',
+ suplesi: {
+ suplesi: data.suplesi === 'yes' ? '1' : '0',
+ noSepSuplesi: data.suplesiNumber || '',
+ lokasiLaka: {
+ kdPropinsi: data.accidentProvince || '',
+ kdKabupaten: data.accidentCity || '',
+ kdKecamatan: data.accidentDistrict || '',
+ },
+ },
+ },
+ },
+ }
+ return {
+ request: {
+ t_sep: content,
+ },
+ }
+}
diff --git a/app/services/vclaim-unit.service.ts b/app/services/vclaim-unit.service.ts
new file mode 100644
index 00000000..970a3f00
--- /dev/null
+++ b/app/services/vclaim-unit.service.ts
@@ -0,0 +1,28 @@
+// Base
+import * as base from './_crud-base'
+
+const path = '/api/vclaim/v1/reference/unit'
+const name = 'unit'
+
+export function getList(params: any = null) {
+ let url = path
+ if (params?.unitCode) {
+ url += `/${params.unitCode}`
+ delete params.unitCode
+ }
+ return base.getList(url, params, name)
+}
+
+export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> {
+ let data: { value: string; label: string }[] = []
+ const result = await getList(params)
+ if (result.success) {
+ const resultData = result.body?.response?.faskes || []
+ const resultUnique = [...new Map(resultData.map((item: any) => [item.kode, item])).values()]
+ data = resultUnique.map((item: any) => ({
+ value: item.kode ? String(item.kode) : '',
+ label: `${item.kode} - ${item.nama}`,
+ }))
+ }
+ return data
+}
diff --git a/app/stores/user.ts b/app/stores/user.ts
index 14ab7134..97bd4665 100644
--- a/app/stores/user.ts
+++ b/app/stores/user.ts
@@ -5,12 +5,13 @@ export const useUserStore = defineStore(
// const token = useCookie('authentication')
const isAuthenticated = computed(() => !!user.value)
+
const userRole = computed(() => {
- const roles = user.value?.roles || []
- return roles.map((input: string) => {
- const parts = input.split('-')
- return parts.length > 1 ? parts[1]: parts[0]
- })
+ return user.value?.roles || []
+ // return roles.map((input: string) => {
+ // const parts = input.split('|')
+ // return parts.length > 1 ? parts[1]: parts[0]
+ // })
})
const login = async (userData: any) => {
@@ -21,12 +22,30 @@ export const useUserStore = defineStore(
user.value = null
}
+ const setActiveRole = (role: string) => {
+ if (user.value && user.value.roles.includes(role)) {
+ user.value.activeRole = role
+ }
+ }
+
+ const getActiveRole = () => {
+ if (user.value?.activeRole) {
+ return user.value.activeRole
+ }
+ if (user.value?.roles.length > 0) {
+ user.value.activeRole = user.value.roles[0]
+ return user.value.activeRole
+ }
+ }
+
return {
user,
isAuthenticated,
userRole,
login,
logout,
+ setActiveRole,
+ getActiveRole,
}
},
{
diff --git a/nuxt.config.ts b/nuxt.config.ts
index 55cdb6bf..f4f0b231 100644
--- a/nuxt.config.ts
+++ b/nuxt.config.ts
@@ -5,8 +5,12 @@ export default defineNuxtConfig({
devtools: { enabled: true },
runtimeConfig: {
API_ORIGIN: process.env.NUXT_API_ORIGIN || 'http://localhost:3000',
+ VCLAIM: process.env.NUXT_API_VCLAIM || 'http://localhost:3000',
+ VCLAIM_SWAGGER: process.env.NUXT_API_VCLAIM_SWAGGER || 'http://localhost:3000',
public: {
API_ORIGIN: process.env.NUXT_API_ORIGIN || 'http://localhost:3000',
+ VCLAIM: process.env.NUXT_API_VCLAIM || 'http://localhost:3000',
+ VCLAIM_SWAGGER: process.env.NUXT_API_VCLAIM_SWAGGER || 'http://localhost:3000',
},
},
ssr: false,
diff --git a/public/side-menu-items/blank.json b/public/side-menu-items/blank.json
new file mode 100644
index 00000000..9d7a78b3
--- /dev/null
+++ b/public/side-menu-items/blank.json
@@ -0,0 +1,12 @@
+[
+ {
+ "heading": "Menu Utama",
+ "items": [
+ {
+ "title": "Dashboard",
+ "icon": "i-lucide-home",
+ "link": "/"
+ }
+ ]
+ }
+]
diff --git a/public/side-menu-items/div-crd.json b/public/side-menu-items/div-crd.json
new file mode 100644
index 00000000..9d7a78b3
--- /dev/null
+++ b/public/side-menu-items/div-crd.json
@@ -0,0 +1,12 @@
+[
+ {
+ "heading": "Menu Utama",
+ "items": [
+ {
+ "title": "Dashboard",
+ "icon": "i-lucide-home",
+ "link": "/"
+ }
+ ]
+ }
+]
diff --git a/public/side-menu-items/doc.json b/public/side-menu-items/emp-doc.json
similarity index 96%
rename from public/side-menu-items/doc.json
rename to public/side-menu-items/emp-doc.json
index e3ab2cdf..b7ecb430 100644
--- a/public/side-menu-items/doc.json
+++ b/public/side-menu-items/emp-doc.json
@@ -84,12 +84,12 @@
{
"title": "Kemoterapi",
"icon": "i-lucide-droplets",
- "link": "/outpatient-action/cemotherapy"
+ "link": "/outpation-action/chemotherapy"
},
{
"title": "Hemofilia",
"icon": "i-lucide-droplet-off",
- "link": "/outpatient-action/hemophilia/encounter"
+ "link": "/outpation-action/hemophilia"
}
]
},
diff --git a/public/side-menu-items/lab.json b/public/side-menu-items/emp-lab.json
similarity index 100%
rename from public/side-menu-items/lab.json
rename to public/side-menu-items/emp-lab.json
diff --git a/public/side-menu-items/miw.json b/public/side-menu-items/emp-mid.json
similarity index 93%
rename from public/side-menu-items/miw.json
rename to public/side-menu-items/emp-mid.json
index ebb43da6..80eeee7c 100644
--- a/public/side-menu-items/miw.json
+++ b/public/side-menu-items/emp-mid.json
@@ -20,7 +20,7 @@
{
"title": "Rehabilitasi Medik",
"icon": "i-lucide-bike",
- "link": "/rehab/polyclinic-queue"
+ "link": "/rehab/encounter-queue"
},
{
"title": "Rawat Inap",
diff --git a/public/side-menu-items/nur.json b/public/side-menu-items/emp-nur.json
similarity index 89%
rename from public/side-menu-items/nur.json
rename to public/side-menu-items/emp-nur.json
index 8185456c..1c993144 100644
--- a/public/side-menu-items/nur.json
+++ b/public/side-menu-items/emp-nur.json
@@ -13,10 +13,10 @@
"children": [
{
"title": "Antrian Poliklinik",
- "link": "/outpatient/polyclinic-queue"
+ "link": "/outpatient/encounter-queue"
},
{
- "title": "Pendaftaran",
+ "title": "Kunjungan",
"link": "/outpatient/encounter"
}
]
@@ -30,7 +30,7 @@
"link": "/emergency/triage"
},
{
- "title": "Pemeriksaan",
+ "title": "Kunjungan",
"link": "/emergency/encounter"
}
]
@@ -42,7 +42,7 @@
"children": [
{
"title": "Antrean Poliklinik",
- "link": "/rehab/polyclinic-queue"
+ "link": "/rehab/encounter-queue"
},
{
"title": "Kunjungan",
@@ -63,7 +63,7 @@
{
"title": "Kemoterapi",
"icon": "i-lucide-droplets",
- "link": "/outpation-action/cemotherapy"
+ "link": "/outpation-action/chemotherapy"
},
{
"title": "Hemofilia",
diff --git a/public/side-menu-items/nut.json b/public/side-menu-items/emp-nut.json
similarity index 93%
rename from public/side-menu-items/nut.json
rename to public/side-menu-items/emp-nut.json
index 4368b22e..ef71282a 100644
--- a/public/side-menu-items/nut.json
+++ b/public/side-menu-items/emp-nut.json
@@ -35,12 +35,12 @@
{
"title": "Kemoterapi",
"icon": "i-lucide-droplets",
- "link": "/outpatient-action/cemotherapy"
+ "link": "/outpation-action/chemotherapy"
},
{
"title": "Hemofilia",
"icon": "i-lucide-droplet-off",
- "link": "/outpatient-action/hemophilia"
+ "link": "/outpation-action/hemophilia"
}
]
},
diff --git a/public/side-menu-items/pha.json b/public/side-menu-items/emp-pha.json
similarity index 100%
rename from public/side-menu-items/pha.json
rename to public/side-menu-items/emp-pha.json
diff --git a/public/side-menu-items/reg.json b/public/side-menu-items/emp-reg.json
similarity index 100%
rename from public/side-menu-items/reg.json
rename to public/side-menu-items/emp-reg.json
diff --git a/public/side-menu-items/sys.json b/public/side-menu-items/system.json
similarity index 90%
rename from public/side-menu-items/sys.json
rename to public/side-menu-items/system.json
index 19491069..5bf62f36 100644
--- a/public/side-menu-items/sys.json
+++ b/public/side-menu-items/system.json
@@ -17,7 +17,7 @@
},
{
"title": "Antrian Poliklinik",
- "link": "/outpatient/polyclinic-queue"
+ "link": "/outpatient/encounter-queue"
},
{
"title": "Kunjungan",
@@ -57,7 +57,7 @@
},
{
"title": "Antrean Poliklinik",
- "link": "/rehab/polyclinic-queue"
+ "link": "/rehab/encounter-queue"
},
{
"title": "Kunjungan",
@@ -139,7 +139,7 @@
{
"title": "Kemoterapi",
"icon": "i-lucide-droplets",
- "link": "/outpation-action/cemotherapy"
+ "link": "/outpation-action/chemotherapy"
},
{
"title": "Hemofilia",
@@ -199,6 +199,11 @@
"title": "Peserta",
"icon": "i-lucide-circuit-board",
"link": "/integration/bpjs/member"
+ },
+ {
+ "title": "Surat Kontrol",
+ "icon": "i-lucide-circuit-board",
+ "link": "/integration/bpjs/control-letter"
}
]
},
@@ -320,21 +325,41 @@
"title": "Divisi",
"link": "/org-src/division"
},
+ {
+ "title": "Divisi - Posisi",
+ "link": "/org-src/division-position"
+ },
{
"title": "Instalasi",
"link": "/org-src/installation"
},
+ {
+ "title": "Instalasi - Posisi",
+ "link": "/org-src/installation-position"
+ },
{
"title": "Unit",
"link": "/org-src/unit"
},
+ {
+ "title": "Unit - Posisi",
+ "link": "/org-src/unit-position"
+ },
{
"title": "Spesialis",
"link": "/org-src/specialist"
},
+ {
+ "title": "Spesialis - Posisi",
+ "link": "/org-src/specialist-position"
+ },
{
"title": "Sub Spesialis",
"link": "/org-src/subspecialist"
+ },
+ {
+ "title": "Sub Spesialis - Posisi",
+ "link": "/org-src/subspecialist-position"
}
]
},
diff --git a/server/api/[...req].ts b/server/api/[...req].ts
index 8404cc2a..5948eda6 100644
--- a/server/api/[...req].ts
+++ b/server/api/[...req].ts
@@ -5,11 +5,20 @@ export default defineEventHandler(async (event) => {
const headers = getRequestHeaders(event)
const url = getRequestURL(event)
const config = useRuntimeConfig()
-
- const apiOrigin = config.public.API_ORIGIN
- const pathname = url.pathname.replace(/^\/api/, '')
- const targetUrl = apiOrigin + pathname + (url.search || '')
+ const apiOrigin = config.public.API_ORIGIN
+ const apiVclaim = config.public.VCLAIM
+ const apiVclaimSwagger = config.public.VCLAIM_SWAGGER
+ const pathname = url.pathname.replace(/^\/api/, '')
+ const isVclaim = pathname.includes('/vclaim')
+
+ let targetUrl = apiOrigin + pathname + (url.search || '')
+ if (pathname.includes('/vclaim')) {
+ targetUrl = apiVclaim + pathname.replace('/vclaim', '') + (url.search || '')
+ }
+ if (pathname.includes('/vclaim-swagger')) {
+ targetUrl = apiVclaimSwagger + pathname.replace('/vclaim-swagger', '') + (url.search || '')
+ }
const verificationId = headers['verification-id'] as string | undefined
let bearer = ''
@@ -21,8 +30,10 @@ export default defineEventHandler(async (event) => {
}
const forwardHeaders = new Headers()
- if (headers['content-type']) forwardHeaders.set('Content-Type', headers['content-type'])
- forwardHeaders.set('Authorization', `Bearer ${bearer}`)
+ if (!isVclaim) {
+ if (headers['content-type']) forwardHeaders.set('Content-Type', headers['content-type'])
+ forwardHeaders.set('Authorization', `Bearer ${bearer}`)
+ }
let body: any
if (['POST', 'PATCH'].includes(method!)) {
@@ -41,5 +52,15 @@ export default defineEventHandler(async (event) => {
body,
})
+ if (isVclaim) {
+ const resClone = res.clone()
+ const responseBody = await resClone.json()
+ return {
+ status: resClone.status,
+ headers: resClone.headers,
+ ...responseBody,
+ }
+ }
+
return res
})