diff --git a/README.md b/README.md index 694ddf34..40601187 100644 --- a/README.md +++ b/README.md @@ -20,16 +20,20 @@ RSSA - Front End - `app.vue`: Main layout - `components` : Contains all reusable UI components. -- `components/flow` : Entry point for business logic and workflows. Pages or routes call these flow components to handle API requests and process application logic -- `components/app` : View-layer components that manage and present data. These are used within `flow/` to render or handle specific parts of the UI, and return results back to the flow +- `components/content` : Entry point for business logic and workflows. Pages or routes call these content components to handle API requests and process application logic +- `components/app` : View-layer components that manage and present data. These are used within `content/` to render or handle specific parts of the UI, and return results back to the content - `components/pub` : Public/shared components used across different parts of the app. - `composables` : Contains reusable logic and utility functions (e.g. composables, hooks).. - `layouts` : Reusable UI layout patterns used across pages. +- `models` : Contains data definitions or interfaces. +- `schemas` : Contains JSON schemas used for validation. +- `services` : Contains reusable API calls and business logic. + ## Directory Structure for `app/pages` - `pages/auth` : Authentication related pages. -- `pages/(features)` : Grouped feature modules that reflect specific business flow or domains. +- `pages/(features)` : Grouped feature modules that reflect specific business content or domains. ## Directory Structure for `server/` @@ -50,16 +54,16 @@ The basic development workflow follows these steps: - Keep components pure, avoid making HTTP requests directly within them. - They receive data via props and emit events upward. -### Business Logic in `components/flow` +### Business Logic in `components/content` - This layer connects the UI with the logic (API calls, validations, navigation). -- It composes components from `components/app/`, `components/pub/`, and other flow. +- It composes components from `components/app/`, `components/pub/`, and other content. - Also responsible for managing state, side effects, and interactions. ### Create Pages in `pages/` - Define permissions and guards for each page. -- Pages load the appropriate flow from `components/flow/`. +- Pages load the appropriate content from `components/content/`. - They do not contain UI or logic directly, just route level layout or guards. ## Code Conventions diff --git a/app/assets/css/main.css b/app/assets/css/main.css index 1c7eaef2..4c488385 100644 --- a/app/assets/css/main.css +++ b/app/assets/css/main.css @@ -327,4 +327,14 @@ body { .rounded-sm { border-radius: var(--radius-sm); } + +/* Form Error Styling */ +.field-error-info { + @apply text-xs ml-1; + color: hsl(var(--destructive)); + /* font-size: 0.875rem; */ + margin-top: 0.25rem; + line-height: 1.25; +} + /* .rounded-md { border-radius: var */ diff --git a/app/components/app/device/entry-form.vue b/app/components/app/device/entry-form.vue new file mode 100644 index 00000000..38b4aea0 --- /dev/null +++ b/app/components/app/device/entry-form.vue @@ -0,0 +1,64 @@ + + + diff --git a/app/components/app/device/list-cfg.ts b/app/components/app/device/list-cfg.ts new file mode 100644 index 00000000..71ca97f6 --- /dev/null +++ b/app/components/app/device/list-cfg.ts @@ -0,0 +1,52 @@ +import type { + Col, + KeyLabel, + RecComponent, + RecStrFuncComponent, + RecStrFuncUnknown, + Th, +} from '~/components/pub/custom-ui/data/types' +import { defineAsyncComponent } from 'vue' + +type SmallDetailDto = any + +const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue')) + +export const cols: Col[] = [{ width: 100 }, { width: 250 }, { width: 100 }, { width: 100 }, { width: 50 }] + +export const header: Th[][] = [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Item' }, { label: 'Satuan' }]] + +export const keys = ['code', 'name', 'item_id', 'uom_code', 'action'] + +export const delKeyNames: KeyLabel[] = [ + { key: 'code', label: 'Kode' }, + { key: 'name', label: 'Nama' }, +] + +export const funcParsed: Record any> = { + name: (rec: unknown): unknown => { + const recX = rec as SmallDetailDto + return `${recX.name}`.trim() + }, + item_id: (rec: unknown): unknown => { + const recX = rec as SmallDetailDto + return recX.item_id + }, + uom_code: (rec: unknown): unknown => { + const recX = rec as SmallDetailDto + return recX.uom_code + }, +} + +export const funcComponent: RecStrFuncComponent = { + action(rec, idx) { + const res: RecComponent = { + idx, + rec: rec as object, + component: action, + } + return res + }, +} + +export const funcHtml: Record any> = {} diff --git a/app/components/app/device/list.vue b/app/components/app/device/list.vue new file mode 100644 index 00000000..5b8778d9 --- /dev/null +++ b/app/components/app/device/list.vue @@ -0,0 +1,19 @@ + + + diff --git a/app/components/app/divison/entry-form.vue b/app/components/app/divison/entry-form.vue new file mode 100644 index 00000000..3008d3c8 --- /dev/null +++ b/app/components/app/divison/entry-form.vue @@ -0,0 +1,125 @@ + + + diff --git a/app/components/app/divison/list-cfg.ts b/app/components/app/divison/list-cfg.ts new file mode 100644 index 00000000..58094521 --- /dev/null +++ b/app/components/app/divison/list-cfg.ts @@ -0,0 +1,86 @@ +import type { + Col, + KeyLabel, + RecComponent, + RecStrFuncComponent, + RecStrFuncUnknown, + Th, +} from '~/components/pub/custom-ui/data/types' +import { defineAsyncComponent } from 'vue' + +type SmallDetailDto = any + +const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-ud.vue')) + +export const cols: Col[] = [ + { width: 100 }, + { }, + { }, + { }, + { width: 50 }, +] + +export const header: Th[][] = [ + [ + { label: 'Id' }, + { label: 'Nama' }, + { label: 'Kode' }, + { label: 'Kelompok' }, + { label: '' }, + ], +] + +export const keys = [ + 'id', + 'firstName', + 'cellphone', + 'birth_place', + 'action', +] + +export const delKeyNames: KeyLabel[] = [ + { key: 'code', label: 'Kode' }, + { key: 'name', label: 'Nama' }, +] + +export const funcParsed: RecStrFuncUnknown = { + name: (rec: unknown): unknown => { + const recX = rec as SmallDetailDto + return `${recX.frontTitle} ${recX.name} ${recX.endTitle}`.trim() + }, + identity_number: (rec: unknown): unknown => { + const recX = rec as SmallDetailDto + if (recX.identity_number?.substring(0, 5) === 'BLANK') { + return '(TANPA NIK)' + } + return recX.identity_number + }, + inPatient_itemPrice: (rec: unknown): unknown => { + const recX = rec as SmallDetailDto + return Number(recX.inPatient_itemPrice.price).toLocaleString('id-ID') + }, + outPatient_itemPrice: (rec: unknown): unknown => { + const recX = rec as SmallDetailDto + return Number(recX.outPatient_itemPrice.price).toLocaleString('id-ID') + }, +} + +export const funcComponent: RecStrFuncComponent = { + action(rec, idx) { + const res: RecComponent = { + idx, + rec: rec as object, + component: action, + props: { + size: 'sm', + }, + } + return res + }, +} + +export const funcHtml: RecStrFuncUnknown = { + patient_address(_rec) { + return '-' + }, +} diff --git a/app/components/app/divison/list.vue b/app/components/app/divison/list.vue new file mode 100644 index 00000000..cf0d5ea2 --- /dev/null +++ b/app/components/app/divison/list.vue @@ -0,0 +1,35 @@ + + + diff --git a/app/components/app/installation/entry-form.vue b/app/components/app/installation/entry-form.vue new file mode 100644 index 00000000..0b3a0049 --- /dev/null +++ b/app/components/app/installation/entry-form.vue @@ -0,0 +1,124 @@ + + + diff --git a/app/components/app/installation/list-cfg.ts b/app/components/app/installation/list-cfg.ts new file mode 100644 index 00000000..6b8dc5ea --- /dev/null +++ b/app/components/app/installation/list-cfg.ts @@ -0,0 +1,68 @@ +import type { + Col, + KeyLabel, + RecComponent, + RecStrFuncComponent, + RecStrFuncUnknown, + Th, +} from '~/components/pub/custom-ui/data/types' +import { defineAsyncComponent } from 'vue' + +type SmallDetailDto = any + +const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-ud.vue')) + +export const cols: Col[] = [{ width: 100 }, {}, {}, {}, { width: 50 }] + +export const header: Th[][] = [ + [{ label: 'Id' }, { label: 'Nama' }, { label: 'Kode' }, { label: 'Encounter Class' }, { label: '' }], +] + +export const keys = ['id', 'name', 'cellphone', 'religion_code', 'action'] + +export const delKeyNames: KeyLabel[] = [ + { key: 'code', label: 'Kode' }, + { key: 'name', label: 'Nama' }, +] + +export const funcParsed: RecStrFuncUnknown = { + name: (rec: unknown): unknown => { + const recX = rec as SmallDetailDto + return `${recX.firstName} ${recX.lastName || ''}`.trim() + }, + identity_number: (rec: unknown): unknown => { + const recX = rec as SmallDetailDto + if (recX.identity_number?.substring(0, 5) === 'BLANK') { + return '(TANPA NIK)' + } + return recX.identity_number + }, + inPatient_itemPrice: (rec: unknown): unknown => { + const recX = rec as SmallDetailDto + return Number(recX.inPatient_itemPrice.price).toLocaleString('id-ID') + }, + outPatient_itemPrice: (rec: unknown): unknown => { + const recX = rec as SmallDetailDto + return Number(recX.outPatient_itemPrice.price).toLocaleString('id-ID') + }, +} + +export const funcComponent: RecStrFuncComponent = { + action(rec, idx) { + const res: RecComponent = { + idx, + rec: rec as object, + component: action, + props: { + size: 'sm', + }, + } + return res + }, +} + +export const funcHtml: RecStrFuncUnknown = { + patient_address(_rec) { + return '-' + }, +} diff --git a/app/components/app/installation/list.vue b/app/components/app/installation/list.vue new file mode 100644 index 00000000..a6b19eb2 --- /dev/null +++ b/app/components/app/installation/list.vue @@ -0,0 +1,36 @@ + + + diff --git a/app/components/app/item-price/entry-form.vue b/app/components/app/item-price/entry-form.vue new file mode 100644 index 00000000..e0c97dc8 --- /dev/null +++ b/app/components/app/item-price/entry-form.vue @@ -0,0 +1,50 @@ + + + diff --git a/app/components/app/item-price/list-cfg.ts b/app/components/app/item-price/list-cfg.ts new file mode 100644 index 00000000..e2c72f9c --- /dev/null +++ b/app/components/app/item-price/list-cfg.ts @@ -0,0 +1,46 @@ +import type { + Col, + KeyLabel, + RecComponent, + RecStrFuncComponent, + RecStrFuncUnknown, + Th, +} from '~/components/pub/custom-ui/data/types' +import { defineAsyncComponent } from 'vue' + +const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue')) + +const _doctorStatus = { + 0: 'Tidak Aktif', + 1: 'Aktif', +} + +export const cols: Col[] = [{}, {}, { width: 50 }] + +export const header: Th[][] = [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Aksi' }]] + +export const keys = ['code', 'name', 'action'] + +export const delKeyNames: KeyLabel[] = [ + { key: 'code', label: 'Kode' }, + { key: 'name', label: 'Nama' }, +] + +export const funcParsed: RecStrFuncUnknown = {} + +export const funcComponent: RecStrFuncComponent = { + action(rec, idx) { + const res: RecComponent = { + idx, + rec: rec as object, + component: action, + } + return res + }, +} + +export const funcHtml: RecStrFuncUnknown = { + patient_address(_rec) { + return '-' + }, +} diff --git a/app/components/app/item-price/list.vue b/app/components/app/item-price/list.vue new file mode 100644 index 00000000..5b8778d9 --- /dev/null +++ b/app/components/app/item-price/list.vue @@ -0,0 +1,19 @@ + + + diff --git a/app/components/app/item-price/picker.vue b/app/components/app/item-price/picker.vue new file mode 100644 index 00000000..e69de29b diff --git a/app/components/app/item-price/search.vue b/app/components/app/item-price/search.vue new file mode 100644 index 00000000..e69de29b diff --git a/app/components/app/item-price/status-badge.vue b/app/components/app/item-price/status-badge.vue new file mode 100644 index 00000000..32cdfbca --- /dev/null +++ b/app/components/app/item-price/status-badge.vue @@ -0,0 +1,29 @@ + + + diff --git a/app/components/app/item/entry-form.vue b/app/components/app/item/entry-form.vue new file mode 100644 index 00000000..8f6d3abf --- /dev/null +++ b/app/components/app/item/entry-form.vue @@ -0,0 +1,68 @@ + + + diff --git a/app/components/app/item/list-cfg.ts b/app/components/app/item/list-cfg.ts new file mode 100644 index 00000000..e2c72f9c --- /dev/null +++ b/app/components/app/item/list-cfg.ts @@ -0,0 +1,46 @@ +import type { + Col, + KeyLabel, + RecComponent, + RecStrFuncComponent, + RecStrFuncUnknown, + Th, +} from '~/components/pub/custom-ui/data/types' +import { defineAsyncComponent } from 'vue' + +const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue')) + +const _doctorStatus = { + 0: 'Tidak Aktif', + 1: 'Aktif', +} + +export const cols: Col[] = [{}, {}, { width: 50 }] + +export const header: Th[][] = [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Aksi' }]] + +export const keys = ['code', 'name', 'action'] + +export const delKeyNames: KeyLabel[] = [ + { key: 'code', label: 'Kode' }, + { key: 'name', label: 'Nama' }, +] + +export const funcParsed: RecStrFuncUnknown = {} + +export const funcComponent: RecStrFuncComponent = { + action(rec, idx) { + const res: RecComponent = { + idx, + rec: rec as object, + component: action, + } + return res + }, +} + +export const funcHtml: RecStrFuncUnknown = { + patient_address(_rec) { + return '-' + }, +} diff --git a/app/components/app/item/list.vue b/app/components/app/item/list.vue new file mode 100644 index 00000000..5b8778d9 --- /dev/null +++ b/app/components/app/item/list.vue @@ -0,0 +1,19 @@ + + + diff --git a/app/components/app/item/picker.vue b/app/components/app/item/picker.vue new file mode 100644 index 00000000..e69de29b diff --git a/app/components/app/item/search.vue b/app/components/app/item/search.vue new file mode 100644 index 00000000..e69de29b diff --git a/app/components/app/item/status-badge.vue b/app/components/app/item/status-badge.vue new file mode 100644 index 00000000..32cdfbca --- /dev/null +++ b/app/components/app/item/status-badge.vue @@ -0,0 +1,29 @@ + + + diff --git a/app/components/app/medicine-group/entry-form.vue b/app/components/app/medicine-group/entry-form.vue new file mode 100644 index 00000000..e4f0b60a --- /dev/null +++ b/app/components/app/medicine-group/entry-form.vue @@ -0,0 +1,37 @@ + + + diff --git a/app/components/app/medicine-group/list-cfg.ts b/app/components/app/medicine-group/list-cfg.ts new file mode 100644 index 00000000..e2c72f9c --- /dev/null +++ b/app/components/app/medicine-group/list-cfg.ts @@ -0,0 +1,46 @@ +import type { + Col, + KeyLabel, + RecComponent, + RecStrFuncComponent, + RecStrFuncUnknown, + Th, +} from '~/components/pub/custom-ui/data/types' +import { defineAsyncComponent } from 'vue' + +const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue')) + +const _doctorStatus = { + 0: 'Tidak Aktif', + 1: 'Aktif', +} + +export const cols: Col[] = [{}, {}, { width: 50 }] + +export const header: Th[][] = [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Aksi' }]] + +export const keys = ['code', 'name', 'action'] + +export const delKeyNames: KeyLabel[] = [ + { key: 'code', label: 'Kode' }, + { key: 'name', label: 'Nama' }, +] + +export const funcParsed: RecStrFuncUnknown = {} + +export const funcComponent: RecStrFuncComponent = { + action(rec, idx) { + const res: RecComponent = { + idx, + rec: rec as object, + component: action, + } + return res + }, +} + +export const funcHtml: RecStrFuncUnknown = { + patient_address(_rec) { + return '-' + }, +} diff --git a/app/components/app/medicine-group/list.vue b/app/components/app/medicine-group/list.vue new file mode 100644 index 00000000..5b8778d9 --- /dev/null +++ b/app/components/app/medicine-group/list.vue @@ -0,0 +1,19 @@ + + + diff --git a/app/components/app/medicine-group/picker.vue b/app/components/app/medicine-group/picker.vue new file mode 100644 index 00000000..e69de29b diff --git a/app/components/app/medicine-group/search.vue b/app/components/app/medicine-group/search.vue new file mode 100644 index 00000000..e69de29b diff --git a/app/components/app/medicine-group/status-badge.vue b/app/components/app/medicine-group/status-badge.vue new file mode 100644 index 00000000..32cdfbca --- /dev/null +++ b/app/components/app/medicine-group/status-badge.vue @@ -0,0 +1,29 @@ + + + diff --git a/app/components/app/medicine-method/entry-form.vue b/app/components/app/medicine-method/entry-form.vue new file mode 100644 index 00000000..e4f0b60a --- /dev/null +++ b/app/components/app/medicine-method/entry-form.vue @@ -0,0 +1,37 @@ + + + diff --git a/app/components/app/medicine-method/list-cfg.ts b/app/components/app/medicine-method/list-cfg.ts new file mode 100644 index 00000000..e2c72f9c --- /dev/null +++ b/app/components/app/medicine-method/list-cfg.ts @@ -0,0 +1,46 @@ +import type { + Col, + KeyLabel, + RecComponent, + RecStrFuncComponent, + RecStrFuncUnknown, + Th, +} from '~/components/pub/custom-ui/data/types' +import { defineAsyncComponent } from 'vue' + +const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue')) + +const _doctorStatus = { + 0: 'Tidak Aktif', + 1: 'Aktif', +} + +export const cols: Col[] = [{}, {}, { width: 50 }] + +export const header: Th[][] = [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Aksi' }]] + +export const keys = ['code', 'name', 'action'] + +export const delKeyNames: KeyLabel[] = [ + { key: 'code', label: 'Kode' }, + { key: 'name', label: 'Nama' }, +] + +export const funcParsed: RecStrFuncUnknown = {} + +export const funcComponent: RecStrFuncComponent = { + action(rec, idx) { + const res: RecComponent = { + idx, + rec: rec as object, + component: action, + } + return res + }, +} + +export const funcHtml: RecStrFuncUnknown = { + patient_address(_rec) { + return '-' + }, +} diff --git a/app/components/app/medicine-method/list.vue b/app/components/app/medicine-method/list.vue new file mode 100644 index 00000000..5b8778d9 --- /dev/null +++ b/app/components/app/medicine-method/list.vue @@ -0,0 +1,19 @@ + + + diff --git a/app/components/app/medicine-method/picker.vue b/app/components/app/medicine-method/picker.vue new file mode 100644 index 00000000..e69de29b diff --git a/app/components/app/medicine-method/search.vue b/app/components/app/medicine-method/search.vue new file mode 100644 index 00000000..e69de29b diff --git a/app/components/app/medicine/entry-form.vue b/app/components/app/medicine/entry-form.vue new file mode 100644 index 00000000..5d3c495d --- /dev/null +++ b/app/components/app/medicine/entry-form.vue @@ -0,0 +1,80 @@ + + + diff --git a/app/components/app/medicine/list-cfg.ts b/app/components/app/medicine/list-cfg.ts new file mode 100644 index 00000000..e86a0646 --- /dev/null +++ b/app/components/app/medicine/list-cfg.ts @@ -0,0 +1,67 @@ +import type { + Col, + KeyLabel, + RecComponent, + RecStrFuncComponent, + RecStrFuncUnknown, + Th, +} from '~/components/pub/custom-ui/data/types' +import { defineAsyncComponent } from 'vue' + +type SmallDetailDto = any + +const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue')) + +export const cols: Col[] = [{}, {}, {}, {}, {}, {}, { width: 50 }] + +export const header: Th[][] = [ + [ + { label: 'Kode' }, + { label: 'Name' }, + { label: 'Kategori' }, + { label: 'Golongan' }, + { label: 'Metode Pemberian' }, + { label: 'Bentuk' }, + { label: 'Stok' }, + { label: 'Aksi' }, + ], +] + +export const keys = ['code', 'name', 'category', 'group', 'method', 'unit', 'total', 'action'] + +export const delKeyNames: KeyLabel[] = [ + { key: 'code', label: 'Kode' }, + { key: 'name', label: 'Nama' }, +] + +export const funcParsed: RecStrFuncUnknown = { + cateogry: (rec: unknown): unknown => { + return (rec as SmallDetailDto).medicineCategory?.name || '-' + }, + group: (rec: unknown): unknown => { + return (rec as SmallDetailDto).medicineGroup?.name || '-' + }, + method: (rec: unknown): unknown => { + return (rec as SmallDetailDto).medicineMethod?.name || '-' + }, + unit: (rec: unknown): unknown => { + return (rec as SmallDetailDto).medicineUnit?.name || '-' + }, +} + +export const funcComponent: RecStrFuncComponent = { + action: (rec: unknown, idx: number): RecComponent => { + const res: RecComponent = { + idx, + rec: rec as object, + component: action, + } + return res + }, +} + +export const funcHtml: RecStrFuncUnknown = { + // (_rec) { + // return '-' + // }, +} diff --git a/app/components/app/medicine/list.vue b/app/components/app/medicine/list.vue new file mode 100644 index 00000000..5b8778d9 --- /dev/null +++ b/app/components/app/medicine/list.vue @@ -0,0 +1,19 @@ + + + diff --git a/app/components/app/medicine/picker.vue b/app/components/app/medicine/picker.vue new file mode 100644 index 00000000..e69de29b diff --git a/app/components/app/medicine/search.vue b/app/components/app/medicine/search.vue new file mode 100644 index 00000000..e69de29b diff --git a/app/components/app/medicine/status-badge.vue b/app/components/app/medicine/status-badge.vue new file mode 100644 index 00000000..32cdfbca --- /dev/null +++ b/app/components/app/medicine/status-badge.vue @@ -0,0 +1,29 @@ + + + diff --git a/app/components/app/unit/entry-form.vue b/app/components/app/unit/entry-form.vue new file mode 100644 index 00000000..463a6683 --- /dev/null +++ b/app/components/app/unit/entry-form.vue @@ -0,0 +1,125 @@ + + + diff --git a/app/components/app/unit/list-cfg.ts b/app/components/app/unit/list-cfg.ts new file mode 100644 index 00000000..00423066 --- /dev/null +++ b/app/components/app/unit/list-cfg.ts @@ -0,0 +1,86 @@ +import type { + Col, + KeyLabel, + RecComponent, + RecStrFuncComponent, + RecStrFuncUnknown, + Th, +} from '~/components/pub/custom-ui/data/types' +import { defineAsyncComponent } from 'vue' + +type SmallDetailDto = any + +const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-ud.vue')) + +export const cols: Col[] = [ + { width: 100 }, + { }, + { }, + { }, + { width: 50 }, +] + +export const header: Th[][] = [ + [ + { label: 'Id' }, + { label: 'Nama' }, + { label: 'Kode' }, + { label: 'Instalasi' }, + { label: '' }, + ], +] + +export const keys = [ + 'id', + 'firstName', + 'cellphone', + 'birth_place', + 'action', +] + +export const delKeyNames: KeyLabel[] = [ + { key: 'code', label: 'Kode' }, + { key: 'name', label: 'Nama' }, +] + +export const funcParsed: RecStrFuncUnknown = { + name: (rec: unknown): unknown => { + const recX = rec as SmallDetailDto + return `${recX.frontTitle} ${recX.name} ${recX.endTitle}`.trim() + }, + identity_number: (rec: unknown): unknown => { + const recX = rec as SmallDetailDto + if (recX.identity_number?.substring(0, 5) === 'BLANK') { + return '(TANPA NIK)' + } + return recX.identity_number + }, + inPatient_itemPrice: (rec: unknown): unknown => { + const recX = rec as SmallDetailDto + return Number(recX.inPatient_itemPrice.price).toLocaleString('id-ID') + }, + outPatient_itemPrice: (rec: unknown): unknown => { + const recX = rec as SmallDetailDto + return Number(recX.outPatient_itemPrice.price).toLocaleString('id-ID') + }, +} + +export const funcComponent: RecStrFuncComponent = { + action(rec, idx) { + const res: RecComponent = { + idx, + rec: rec as object, + component: action, + props: { + size: 'sm', + }, + } + return res + }, +} + +export const funcHtml: RecStrFuncUnknown = { + patient_address(_rec) { + return '-' + }, +} diff --git a/app/components/app/unit/list.vue b/app/components/app/unit/list.vue new file mode 100644 index 00000000..1baaa6ba --- /dev/null +++ b/app/components/app/unit/list.vue @@ -0,0 +1,35 @@ + + + diff --git a/app/components/flow/auth/login.vue b/app/components/content/auth/login.vue similarity index 100% rename from app/components/flow/auth/login.vue rename to app/components/content/auth/login.vue diff --git a/app/components/flow/dashboard/index.vue b/app/components/content/dashboard/index.vue similarity index 100% rename from app/components/flow/dashboard/index.vue rename to app/components/content/dashboard/index.vue diff --git a/app/components/content/item-price/list.vue b/app/components/content/item-price/list.vue new file mode 100644 index 00000000..9a5f567b --- /dev/null +++ b/app/components/content/item-price/list.vue @@ -0,0 +1,71 @@ + + + diff --git a/app/components/content/item/list.vue b/app/components/content/item/list.vue new file mode 100644 index 00000000..41c7311f --- /dev/null +++ b/app/components/content/item/list.vue @@ -0,0 +1,71 @@ + + + diff --git a/app/components/content/medicine-group/list.vue b/app/components/content/medicine-group/list.vue new file mode 100644 index 00000000..93afabff --- /dev/null +++ b/app/components/content/medicine-group/list.vue @@ -0,0 +1,75 @@ + + + diff --git a/app/components/content/medicine-method/list.vue b/app/components/content/medicine-method/list.vue new file mode 100644 index 00000000..43d7a03f --- /dev/null +++ b/app/components/content/medicine-method/list.vue @@ -0,0 +1,74 @@ + + + diff --git a/app/components/content/medicine/entry.vue b/app/components/content/medicine/entry.vue new file mode 100644 index 00000000..3c3b4cfd --- /dev/null +++ b/app/components/content/medicine/entry.vue @@ -0,0 +1,16 @@ + + + diff --git a/app/components/content/medicine/list.vue b/app/components/content/medicine/list.vue new file mode 100644 index 00000000..19497a7e --- /dev/null +++ b/app/components/content/medicine/list.vue @@ -0,0 +1,63 @@ + + + diff --git a/app/components/flow/patient/add.vue b/app/components/content/patient/add.vue similarity index 100% rename from app/components/flow/patient/add.vue rename to app/components/content/patient/add.vue diff --git a/app/components/flow/patient/list.vue b/app/components/content/patient/list.vue similarity index 100% rename from app/components/flow/patient/list.vue rename to app/components/content/patient/list.vue diff --git a/app/components/flow/rehab/registration/home.vue b/app/components/content/rehab/registration/home.vue similarity index 100% rename from app/components/flow/rehab/registration/home.vue rename to app/components/content/rehab/registration/home.vue diff --git a/app/components/flow/rehab/registration/sep-prosedur/add.vue b/app/components/content/rehab/registration/sep-prosedur/add.vue similarity index 100% rename from app/components/flow/rehab/registration/sep-prosedur/add.vue rename to app/components/content/rehab/registration/sep-prosedur/add.vue diff --git a/app/components/flow/rehab/registration/sep-prosedur/list.vue b/app/components/content/rehab/registration/sep-prosedur/list.vue similarity index 100% rename from app/components/flow/rehab/registration/sep-prosedur/list.vue rename to app/components/content/rehab/registration/sep-prosedur/list.vue diff --git a/app/components/flow/satusehat/const.ts b/app/components/content/satusehat/const.ts similarity index 100% rename from app/components/flow/satusehat/const.ts rename to app/components/content/satusehat/const.ts diff --git a/app/components/flow/satusehat/list.vue b/app/components/content/satusehat/list.vue similarity index 100% rename from app/components/flow/satusehat/list.vue rename to app/components/content/satusehat/list.vue diff --git a/app/components/flow/satusehat/schema.query.ts b/app/components/content/satusehat/schema.query.ts similarity index 100% rename from app/components/flow/satusehat/schema.query.ts rename to app/components/content/satusehat/schema.query.ts diff --git a/app/components/flow/user/entry.vue b/app/components/content/user/entry.vue similarity index 100% rename from app/components/flow/user/entry.vue rename to app/components/content/user/entry.vue diff --git a/app/components/flow/user/list.vue b/app/components/content/user/list.vue similarity index 100% rename from app/components/flow/user/list.vue rename to app/components/content/user/list.vue diff --git a/app/components/flow/device/entry.vue b/app/components/flow/device/entry.vue new file mode 100644 index 00000000..d53afb5c --- /dev/null +++ b/app/components/flow/device/entry.vue @@ -0,0 +1,62 @@ + + + diff --git a/app/components/flow/device/list.vue b/app/components/flow/device/list.vue new file mode 100644 index 00000000..8c7bd672 --- /dev/null +++ b/app/components/flow/device/list.vue @@ -0,0 +1,65 @@ + + + diff --git a/app/components/flow/division/entry.ts b/app/components/flow/division/entry.ts new file mode 100644 index 00000000..60617c45 --- /dev/null +++ b/app/components/flow/division/entry.ts @@ -0,0 +1,58 @@ +import * as z from 'zod' + +export const division = { + msg: { + placeholder: '---pilih divisi utama', + search: 'kode, nama divisi', + empty: 'divisi tidak ditemukan', + }, + items: [ + { value: '1', label: 'Medical', code: 'MED' }, + { value: '2', label: 'Nursing', code: 'NUR' }, + { value: '3', label: 'Admin', code: 'ADM' }, + { value: '4', label: 'Support', code: 'SUP' }, + { value: '5', label: 'Education', code: 'EDU' }, + { value: '6', label: 'Pharmacy', code: 'PHA' }, + { value: '7', label: 'Radiology', code: 'RAD' }, + { value: '8', label: 'Laboratory', code: 'LAB' }, + { value: '9', label: 'Finance', code: 'FIN' }, + { value: '10', label: 'Human Resources', code: 'HR' }, + { value: '11', label: 'IT Services', code: 'ITS' }, + { value: '12', label: 'Maintenance', code: 'MNT' }, + { value: '13', label: 'Catering', code: 'CAT' }, + { value: '14', label: 'Security', code: 'SEC' }, + { value: '15', label: 'Emergency', code: 'EMR' }, + { value: '16', label: 'Surgery', code: 'SUR' }, + { value: '17', label: 'Outpatient', code: 'OUT' }, + { value: '18', label: 'Inpatient', code: 'INP' }, + { value: '19', label: 'Rehabilitation', code: 'REB' }, + { value: '20', label: 'Research', code: 'RSH' }, + ], +} + +export const schema = z.object({ + name: z.string({ + required_error: 'Nama wajib diisi', + }).min(1, 'Nama divisi wajib diisi'), + + code: z.string({ + required_error: 'Kode wajib diisi', + }).min(1, 'Kode divisi wajib diisi'), + + parentId: z.preprocess( + (input: unknown) => { + if (typeof input === 'string') { + // Handle empty string case + if (input.trim() === '') { + return undefined + } + return Number(input) + } + + return input + }, + z.number({ + required_error: 'Kelompok wajib dipilih', + }).min(1, 'Kelompok wajib dipilih'), + ), +}) diff --git a/app/components/flow/division/list.vue b/app/components/flow/division/list.vue new file mode 100644 index 00000000..f4bf78e6 --- /dev/null +++ b/app/components/flow/division/list.vue @@ -0,0 +1,219 @@ + + + + + diff --git a/app/components/flow/installation/entry.ts b/app/components/flow/installation/entry.ts new file mode 100644 index 00000000..c003a029 --- /dev/null +++ b/app/components/flow/installation/entry.ts @@ -0,0 +1,37 @@ +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/flow/installation/list.vue b/app/components/flow/installation/list.vue new file mode 100644 index 00000000..01a05baf --- /dev/null +++ b/app/components/flow/installation/list.vue @@ -0,0 +1,220 @@ + + + + + diff --git a/app/components/flow/unit/entry.ts b/app/components/flow/unit/entry.ts new file mode 100644 index 00000000..bf85a0ed --- /dev/null +++ b/app/components/flow/unit/entry.ts @@ -0,0 +1,63 @@ +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/flow/unit/list.vue b/app/components/flow/unit/list.vue new file mode 100644 index 00000000..404da13e --- /dev/null +++ b/app/components/flow/unit/list.vue @@ -0,0 +1,219 @@ + + + + + diff --git a/app/components/pub/base/data-table/data-table.vue b/app/components/pub/base/data-table/data-table.vue index 6524aaa8..eb59b9b9 100644 --- a/app/components/pub/base/data-table/data-table.vue +++ b/app/components/pub/base/data-table/data-table.vue @@ -1,19 +1,39 @@ diff --git a/app/components/pub/custom-ui/form/label.vue b/app/components/pub/custom-ui/form/label.vue index 179cee89..f8272352 100644 --- a/app/components/pub/custom-ui/form/label.vue +++ b/app/components/pub/custom-ui/form/label.vue @@ -1,6 +1,7 @@ + + diff --git a/app/components/pub/custom-ui/nav-header/header.vue b/app/components/pub/custom-ui/nav-header/header.vue index 2f8ebb4e..621691d2 100644 --- a/app/components/pub/custom-ui/nav-header/header.vue +++ b/app/components/pub/custom-ui/nav-header/header.vue @@ -1,18 +1,142 @@