-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/app/components/app/medicine/list-cfg.ts b/app/components/app/medicine/list-cfg.ts
index e86a0646..3440e5f9 100644
--- a/app/components/app/medicine/list-cfg.ts
+++ b/app/components/app/medicine/list-cfg.ts
@@ -18,16 +18,15 @@ export const header: Th[][] = [
[
{ label: 'Kode' },
{ label: 'Name' },
- { label: 'Kategori' },
{ label: 'Golongan' },
{ label: 'Metode Pemberian' },
- { label: 'Bentuk' },
+ { label: "Satuan" },
{ label: 'Stok' },
{ label: 'Aksi' },
],
]
-export const keys = ['code', 'name', 'category', 'group', 'method', 'unit', 'total', 'action']
+export const keys = ['code', 'name', 'group', 'method', 'unit', 'stock', 'action']
export const delKeyNames: KeyLabel[] = [
{ key: 'code', label: 'Kode' },
@@ -35,17 +34,14 @@ export const delKeyNames: KeyLabel[] = [
]
export const funcParsed: RecStrFuncUnknown = {
- cateogry: (rec: unknown): unknown => {
- return (rec as SmallDetailDto).medicineCategory?.name || '-'
- },
group: (rec: unknown): unknown => {
- return (rec as SmallDetailDto).medicineGroup?.name || '-'
+ return (rec as SmallDetailDto).medicineGroup_code || '-'
},
method: (rec: unknown): unknown => {
- return (rec as SmallDetailDto).medicineMethod?.name || '-'
+ return (rec as SmallDetailDto).medicineMethod_code || '-'
},
unit: (rec: unknown): unknown => {
- return (rec as SmallDetailDto).medicineUnit?.name || '-'
+ return (rec as SmallDetailDto).uom_code || '-'
},
}
@@ -60,8 +56,4 @@ export const funcComponent: RecStrFuncComponent = {
},
}
-export const funcHtml: RecStrFuncUnknown = {
- // (_rec) {
- // return '-'
- // },
-}
+export const funcHtml: RecStrFuncUnknown = {}
diff --git a/app/components/app/medicine/list.vue b/app/components/app/medicine/list.vue
index 5b8778d9..d44aa4d8 100644
--- a/app/components/app/medicine/list.vue
+++ b/app/components/app/medicine/list.vue
@@ -1,19 +1,35 @@
-
+
diff --git a/app/components/app/specialist/entry-form-prev.vue b/app/components/app/specialist/entry-form-prev.vue
new file mode 100644
index 00000000..2dbfffc1
--- /dev/null
+++ b/app/components/app/specialist/entry-form-prev.vue
@@ -0,0 +1,181 @@
+
+
+
+
+
+
diff --git a/app/components/app/specialist/entry-form.vue b/app/components/app/specialist/entry-form.vue
index f9044f0e..7254ec98 100644
--- a/app/components/app/specialist/entry-form.vue
+++ b/app/components/app/specialist/entry-form.vue
@@ -1,182 +1,128 @@
-
-
+
diff --git a/app/components/app/specialist/list-cfg.ts b/app/components/app/specialist/list-cfg.ts
index 367d4d9f..2ddc5007 100644
--- a/app/components/app/specialist/list-cfg.ts
+++ b/app/components/app/specialist/list-cfg.ts
@@ -10,15 +10,13 @@ import { defineAsyncComponent } from 'vue'
type SmallDetailDto = any
-const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-ud.vue'))
+const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue'))
-export const cols: Col[] = [{ width: 100 }, {}, {}, {}, { width: 50 }]
+export const cols: Col[] = [{}, {}, {}, { width: 50 }]
-export const header: Th[][] = [
- [{ label: 'Id' }, { label: 'Name' }, { label: 'Code' }, { label: 'Unit' }, { label: '' }],
-]
+export const header: Th[][] = [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Unit' }, { label: '' }]]
-export const keys = ['id', 'name', 'cellphone', 'religion_code', 'action']
+export const keys = ['code', 'name', 'unit', 'action']
export const delKeyNames: KeyLabel[] = [
{ key: 'code', label: 'Kode' },
@@ -28,7 +26,11 @@ export const delKeyNames: KeyLabel[] = [
export const funcParsed: RecStrFuncUnknown = {
name: (rec: unknown): unknown => {
const recX = rec as SmallDetailDto
- return `${recX.firstName} ${recX.lastName || ''}`.trim()
+ return `${recX.name}`.trim()
+ },
+ unit: (rec: unknown): unknown => {
+ const recX = rec as SmallDetailDto
+ return recX.unit_id || '-'
},
}
@@ -38,13 +40,9 @@ export const funcComponent: RecStrFuncComponent = {
idx,
rec: rec as object,
component: action,
- props: {
- size: 'sm',
- },
}
return res
},
}
-export const funcHtml: RecStrFuncUnknown = {
-}
+export const funcHtml: RecStrFuncUnknown = {}
diff --git a/app/components/app/specialist/list.vue b/app/components/app/specialist/list.vue
index e9489ef1..cde2a4ce 100644
--- a/app/components/app/specialist/list.vue
+++ b/app/components/app/specialist/list.vue
@@ -22,10 +22,15 @@ function handlePageChange(page: number) {
diff --git a/app/components/app/subspecialist/entry-form-prev.vue b/app/components/app/subspecialist/entry-form-prev.vue
new file mode 100644
index 00000000..9d31fd3f
--- /dev/null
+++ b/app/components/app/subspecialist/entry-form-prev.vue
@@ -0,0 +1,213 @@
+
+
+
+
+
+
diff --git a/app/components/app/subspecialist/entry-form.vue b/app/components/app/subspecialist/entry-form.vue
index f5115504..6aea232d 100644
--- a/app/components/app/subspecialist/entry-form.vue
+++ b/app/components/app/subspecialist/entry-form.vue
@@ -1,214 +1,128 @@
-
-
+
diff --git a/app/components/app/subspecialist/list-cfg.ts b/app/components/app/subspecialist/list-cfg.ts
index eb25f5d0..c7ded48e 100644
--- a/app/components/app/subspecialist/list-cfg.ts
+++ b/app/components/app/subspecialist/list-cfg.ts
@@ -10,14 +10,13 @@ import { defineAsyncComponent } from 'vue'
type SmallDetailDto = any
-const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-ud.vue'))
+const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue'))
-export const cols: Col[] = [{ width: 100 }, {}, {}, {}, { width: 50 }]
+export const cols: Col[] = [{}, {}, {}, { width: 50 }]
-export const header: Th[][] = [
- [{ label: 'Id' }, { label: 'Nama' }, { label: 'Kode' }, { label: 'Specialist' }, { label: '' }],
-]
-export const keys = ['id', 'name', 'cellphone', 'religion_code', 'action']
+export const header: Th[][] = [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Specialis' }, { label: '' }]]
+
+export const keys = ['code', 'name', 'specialist', 'action']
export const delKeyNames: KeyLabel[] = [
{ key: 'code', label: 'Kode' },
@@ -27,15 +26,11 @@ export const delKeyNames: KeyLabel[] = [
export const funcParsed: RecStrFuncUnknown = {
name: (rec: unknown): unknown => {
const recX = rec as SmallDetailDto
- return `${recX.firstName} ${recX.lastName || ''}`.trim()
- },
- unit: (rec: unknown): unknown => {
- const recX = rec as SmallDetailDto
- return recX.unit?.name || '-'
+ return `${recX.name}`.trim()
},
specialist: (rec: unknown): unknown => {
const recX = rec as SmallDetailDto
- return recX.specialist?.name || '-'
+ return recX.specialist_id || '-'
},
}
@@ -45,9 +40,6 @@ export const funcComponent: RecStrFuncComponent = {
idx,
rec: rec as object,
component: action,
- props: {
- size: 'sm',
- },
}
return res
},
diff --git a/app/components/app/subspecialist/list.vue b/app/components/app/subspecialist/list.vue
index e9489ef1..cde2a4ce 100644
--- a/app/components/app/subspecialist/list.vue
+++ b/app/components/app/subspecialist/list.vue
@@ -22,10 +22,15 @@ function handlePageChange(page: number) {
diff --git a/app/components/app/tools/entry-form.vue b/app/components/app/tools/entry-form.vue
index f888c518..ac19794b 100644
--- a/app/components/app/tools/entry-form.vue
+++ b/app/components/app/tools/entry-form.vue
@@ -6,7 +6,7 @@ import Field from '~/components/pub/custom-ui/doc-entry/field.vue'
import Label from '~/components/pub/custom-ui/doc-entry/label.vue'
// Types
-import type { DeviceFormData } from '~/schemas/device.schema'
+import type { DeviceFormData } from '~/schemas/device.schema.ts'
// Helpers
import type z from 'zod'
diff --git a/app/components/app/unit/entry-form-prev.vue b/app/components/app/unit/entry-form-prev.vue
new file mode 100644
index 00000000..463a6683
--- /dev/null
+++ b/app/components/app/unit/entry-form-prev.vue
@@ -0,0 +1,125 @@
+
+
+
+
+
+
diff --git a/app/components/app/unit/entry-form.vue b/app/components/app/unit/entry-form.vue
index ae710a2b..7bad3552 100644
--- a/app/components/app/unit/entry-form.vue
+++ b/app/components/app/unit/entry-form.vue
@@ -1,126 +1,102 @@
-
-
+
diff --git a/app/components/app/unit/list-cfg.ts b/app/components/app/unit/list-cfg.ts
index 00423066..a6f5ffc7 100644
--- a/app/components/app/unit/list-cfg.ts
+++ b/app/components/app/unit/list-cfg.ts
@@ -10,33 +10,13 @@ import { defineAsyncComponent } from 'vue'
type SmallDetailDto = any
-const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-ud.vue'))
+const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue'))
-export const cols: Col[] = [
- { width: 100 },
- { },
- { },
- { },
- { width: 50 },
-]
+export const cols: Col[] = [{}, {}, {}, { width: 50 }]
-export const header: Th[][] = [
- [
- { label: 'Id' },
- { label: 'Nama' },
- { label: 'Kode' },
- { label: 'Instalasi' },
- { label: '' },
- ],
-]
+export const header: Th[][] = [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Instalasi' }, { label: '' }]]
-export const keys = [
- 'id',
- 'firstName',
- 'cellphone',
- 'birth_place',
- 'action',
-]
+export const keys = ['code', 'name', 'installation', 'action']
export const delKeyNames: KeyLabel[] = [
{ key: 'code', label: 'Kode' },
@@ -46,22 +26,10 @@ export const delKeyNames: KeyLabel[] = [
export const funcParsed: RecStrFuncUnknown = {
name: (rec: unknown): unknown => {
const recX = rec as SmallDetailDto
- return `${recX.frontTitle} ${recX.name} ${recX.endTitle}`.trim()
+ return `${recX.name}`.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')
+ installation: (_rec: unknown): unknown => {
+ return '-'
},
}
@@ -71,16 +39,9 @@ export const funcComponent: RecStrFuncComponent = {
idx,
rec: rec as object,
component: action,
- props: {
- size: 'sm',
- },
}
return res
},
}
-export const funcHtml: RecStrFuncUnknown = {
- patient_address(_rec) {
- return '-'
- },
-}
+export const funcHtml: RecStrFuncUnknown = {}
diff --git a/app/components/app/unit/list.vue b/app/components/app/unit/list.vue
index e9489ef1..cde2a4ce 100644
--- a/app/components/app/unit/list.vue
+++ b/app/components/app/unit/list.vue
@@ -22,10 +22,15 @@ function handlePageChange(page: number) {
diff --git a/app/components/app/uom/entry-form.vue b/app/components/app/uom/entry-form.vue
index 3bf95352..23c8ae0d 100644
--- a/app/components/app/uom/entry-form.vue
+++ b/app/components/app/uom/entry-form.vue
@@ -8,7 +8,7 @@ import Label from '~/components/pub/custom-ui/doc-entry/label.vue'
import Button from '~/components/pub/ui/button/Button.vue'
// Types
-import type { UomFormData } from '~/schemas/uom.schema'
+import type { UomFormData } from '~/schemas/uom.schema.ts'
// Helpers
import type z from 'zod'
diff --git a/app/components/content/device/entry.vue b/app/components/content/device/entry.vue
deleted file mode 100644
index 79a5b022..00000000
--- a/app/components/content/device/entry.vue
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-
-
-
- Tambah Alat Kesehatan
-
-
-
-
diff --git a/app/components/content/device/list.vue b/app/components/content/device/list.vue
deleted file mode 100644
index 8c7bd672..00000000
--- a/app/components/content/device/list.vue
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-
-
diff --git a/app/components/content/division/list-prev.vue b/app/components/content/division/list-prev.vue
new file mode 100644
index 00000000..f7bd1c8d
--- /dev/null
+++ b/app/components/content/division/list-prev.vue
@@ -0,0 +1,208 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
ID: {{ record?.id }}
+
Nama: {{ record.firstName }}
+
Kode: {{ record.cellphone }}
+
+
+
+
+
+
diff --git a/app/components/content/division/list.vue b/app/components/content/division/list.vue
index 856318b9..0acae66d 100644
--- a/app/components/content/division/list.vue
+++ b/app/components/content/division/list.vue
@@ -1,28 +1,39 @@
-
-
-
-
-
-
diff --git a/app/components/content/equipment/list.vue b/app/components/content/equipment/list.vue
index 37f2536a..b1b348d1 100644
--- a/app/components/content/equipment/list.vue
+++ b/app/components/content/equipment/list.vue
@@ -2,8 +2,9 @@
// Components
import Dialog from '~/components/pub/base/modal/dialog.vue'
import Header from '~/components/pub/custom-ui/nav-header/prep.vue'
-import AppEquipmentEntryForm from '~/components/app/equipment/entry-form.vue'
import RecordConfirmation from '~/components/pub/custom-ui/confirmation/record-confirmation.vue'
+import AppEquipmentList from '~/components/app/equipment/list.vue'
+import AppEquipmentEntryForm from '~/components/app/equipment/entry-form.vue'
// Helpers
import { usePaginatedList } from '~/composables/usePaginatedList'
@@ -60,15 +61,11 @@ const headerPrep: HeaderPrep = {
minLength: 3,
debounceMs: 500,
showValidationFeedback: true,
- onInput: (_val: string) => {
- // Handle search input - this will be triggered by the header component
- },
- onClick: () => {
- // Handle search button click if needed
- },
- onClear: () => {
- // Handle search clear
+ onInput: (value: string) => {
+ searchInput.value = value
},
+ onClick: () => {},
+ onClear: () => {},
},
addNav: {
label: 'Tambah Perlengkapan',
@@ -130,7 +127,13 @@ onMounted(async () => {
-
+
-// types
-import type { MaterialFormData } from '~/schemas/material.schema'
-import { MaterialSchema } from '~/schemas/material.schema'
-
-const isLoading = ref(false)
-const uoms = [
- { value: 'uom-1', label: 'Satuan 1' },
- { value: 'uom-2', label: 'Satuan 2' },
- { value: 'uom-3', label: 'Satuan 3' },
-]
-const items = [
- { value: 'item-1', label: 'Item 1' },
- { value: 'item-2', label: 'Item 2' },
- { value: 'item-3', label: 'Item 3' },
-]
-
-function onBack() {
- navigateTo('/tools-equipment-src/equipment')
-}
-
-async function onSubmit(data: MaterialFormData) {
- console.log(data)
-}
-
-
-
-
-
- Tambah Perlengkapan (BMHP)
-
-
-
diff --git a/app/components/content/material/list.vue b/app/components/content/material/list.vue
deleted file mode 100644
index fa719f46..00000000
--- a/app/components/content/material/list.vue
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-
-
diff --git a/app/components/content/medicine-group/list.vue b/app/components/content/medicine-group/list.vue
index 5d3240bc..d56c4c49 100644
--- a/app/components/content/medicine-group/list.vue
+++ b/app/components/content/medicine-group/list.vue
@@ -2,8 +2,9 @@
// Components
import Dialog from '~/components/pub/base/modal/dialog.vue'
import Header from '~/components/pub/custom-ui/nav-header/prep.vue'
-import AppMedicineGroupEntryForm from '~/components/app/medicine-group/entry-form.vue'
import RecordConfirmation from '~/components/pub/custom-ui/confirmation/record-confirmation.vue'
+import AppMedicineGroupList from '~/components/app/medicine-group/list.vue'
+import AppMedicineGroupEntryForm from '~/components/app/medicine-group/entry-form.vue'
// Helpers
import { usePaginatedList } from '~/composables/usePaginatedList'
@@ -11,7 +12,7 @@ import { toast } from '~/components/pub/ui/toast'
// Types
import { ActionEvents, type HeaderPrep } from '~/components/pub/custom-ui/data/types'
-import { MedicineBaseSchema, type MedicineBaseFormData } from '~/schemas/medicine.schema'
+import { BaseSchema, type BaseFormData } from '~/schemas/base.schema'
// Handlers
import {
@@ -57,7 +58,9 @@ const headerPrep: HeaderPrep = {
minLength: 3,
debounceMs: 500,
showValidationFeedback: true,
- onInput: (_val: string) => {},
+ onInput: (value: string) => {
+ searchInput.value = value
+ },
onClick: () => {},
onClear: () => {},
},
@@ -112,7 +115,13 @@ onMounted(async () => {
-
+
{
prevent-outside
>
, resetForm: () => void) => {
+ (values: BaseFormData | Record, resetForm: () => void) => {
if (recId > 0) {
handleActionEdit(recId, values, getMedicineGroupList, resetForm, toast)
return
diff --git a/app/components/content/medicine-method/list.vue b/app/components/content/medicine-method/list.vue
index c88920bf..1de41ddc 100644
--- a/app/components/content/medicine-method/list.vue
+++ b/app/components/content/medicine-method/list.vue
@@ -2,8 +2,9 @@
// Components
import Dialog from '~/components/pub/base/modal/dialog.vue'
import Header from '~/components/pub/custom-ui/nav-header/prep.vue'
-import AppMedicineMethodEntryForm from '~/components/app/medicine-method/entry-form.vue'
import RecordConfirmation from '~/components/pub/custom-ui/confirmation/record-confirmation.vue'
+import AppMedicineMethodList from '~/components/app/medicine-method/list.vue'
+import AppMedicineMethodEntryForm from '~/components/app/medicine-method/entry-form.vue'
// Helpers
import { usePaginatedList } from '~/composables/usePaginatedList'
@@ -11,7 +12,7 @@ import { toast } from '~/components/pub/ui/toast'
// Types
import { ActionEvents, type HeaderPrep } from '~/components/pub/custom-ui/data/types'
-import { MedicineBaseSchema, type MedicineBaseFormData } from '~/schemas/medicine.schema'
+import { BaseSchema, type BaseFormData } from '~/schemas/base.schema'
// Handlers
import {
@@ -57,7 +58,9 @@ const headerPrep: HeaderPrep = {
minLength: 3,
debounceMs: 500,
showValidationFeedback: true,
- onInput: (_val: string) => {},
+ onInput: (value: string) => {
+ searchInput.value = value
+ },
onClick: () => {},
onClear: () => {},
},
@@ -112,7 +115,13 @@ onMounted(async () => {
-
+
{
prevent-outside
>
, resetForm: () => void) => {
+ (values: BaseFormData | Record, resetForm: () => void) => {
if (recId > 0) {
handleActionEdit(recId, values, getMedicineMethodList, resetForm, toast)
return
diff --git a/app/components/content/medicine/list.vue b/app/components/content/medicine/list.vue
index 19497a7e..820931e8 100644
--- a/app/components/content/medicine/list.vue
+++ b/app/components/content/medicine/list.vue
@@ -1,63 +1,206 @@
-
-
+
+
+
+
+ , resetForm: () => void) => {
+ if (recId > 0) {
+ handleActionEdit(recId, values, getMedicineList, resetForm, toast)
+ return
+ }
+ handleActionSave(values, getMedicineList, resetForm, toast)
+ }
+ "
+ @cancel="handleCancelForm"
+ />
+
+
+
+ handleActionRemove(recId, getMedicineList, toast)"
+ @cancel=""
+ >
+
+
+
ID: {{ record?.id }}
+
Nama: {{ record.name }}
+
Kode: {{ record.code }}
+
+
+
diff --git a/app/components/content/specialist/list-prev.vue b/app/components/content/specialist/list-prev.vue
new file mode 100644
index 00000000..ee6d7f8b
--- /dev/null
+++ b/app/components/content/specialist/list-prev.vue
@@ -0,0 +1,240 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ID: {{ record?.id }}
+
Nama: {{ record.firstName }}
+
Kode: {{ record.cellphone }}
+
+
+
+
+
+
diff --git a/app/components/content/specialist/list.vue b/app/components/content/specialist/list.vue
index 7cf4e993..d1c3bb21 100644
--- a/app/components/content/specialist/list.vue
+++ b/app/components/content/specialist/list.vue
@@ -1,33 +1,41 @@
-
+
-
+
, resetForm: () => void) => {
+ if (recId > 0) {
+ handleActionEdit(recId, values, getSpecialistList, resetForm, toast)
+ return
+ }
+ handleActionSave(values, getSpecialistList, resetForm, toast)
+ }
+ "
+ @cancel="handleCancelForm"
/>
+
handleActionRemove(recId, getSpecialistList, toast)"
+ @cancel=""
>
ID: {{ record?.id }}
-
Nama: {{ record.firstName }}
-
Kode: {{ record.cellphone }}
+
Nama: {{ record.name }}
+
Kode: {{ record.code }}
-
-
diff --git a/app/components/content/subspecialist/list-prev.vue b/app/components/content/subspecialist/list-prev.vue
new file mode 100644
index 00000000..a5496df6
--- /dev/null
+++ b/app/components/content/subspecialist/list-prev.vue
@@ -0,0 +1,239 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ID: {{ record?.id }}
+
Nama: {{ record.name }}
+
Kode: {{ record.code }}
+
Specialist: {{ record.specialist?.name }}
+
+
+
+
diff --git a/app/components/content/subspecialist/list.vue b/app/components/content/subspecialist/list.vue
index a478ef22..ad38241f 100644
--- a/app/components/content/subspecialist/list.vue
+++ b/app/components/content/subspecialist/list.vue
@@ -1,34 +1,41 @@
-
-
+
+
-
-
+ , resetForm: () => void) => {
+ if (recId > 0) {
+ handleActionEdit(recId, values, getSubSpecialistList, resetForm, toast)
+ return
+ }
+ handleActionSave(values, getSubSpecialistList, resetForm, toast)
+ }
+ "
+ @cancel="handleCancelForm"
/>
+
handleActionRemove(recId, getSubSpecialistList, toast)"
+ @cancel=""
>
ID: {{ record?.id }}
Nama: {{ record.name }}
Kode: {{ record.code }}
-
Specialist: {{ record.specialist?.name }}
diff --git a/app/components/content/tools/list.vue b/app/components/content/tools/list.vue
index 0b270204..27e90f56 100644
--- a/app/components/content/tools/list.vue
+++ b/app/components/content/tools/list.vue
@@ -2,8 +2,9 @@
// Components
import Dialog from '~/components/pub/base/modal/dialog.vue'
import Header from '~/components/pub/custom-ui/nav-header/prep.vue'
-import AppToolsEntryForm from '~/components/app/tools/entry-form.vue'
import RecordConfirmation from '~/components/pub/custom-ui/confirmation/record-confirmation.vue'
+import AppToolsList from '~/components/app/tools/list.vue'
+import AppToolsEntryForm from '~/components/app/tools/entry-form.vue'
// Helpers
import { usePaginatedList } from '~/composables/usePaginatedList'
@@ -60,8 +61,8 @@ const headerPrep: HeaderPrep = {
minLength: 3,
debounceMs: 500,
showValidationFeedback: true,
- onInput: (_val: string) => {
- // Handle search input - this will be triggered by the header component
+ onInput: (value: string) => {
+ searchInput.value = value
},
onClick: () => {
// Handle search button click if needed
@@ -131,7 +132,13 @@ onMounted(async () => {
-
+
+import type { HeaderPrep } from '~/components/pub/custom-ui/data/types'
+import AppUnitEntryForm from '~/components/app/unit/entry-form.vue'
+import Dialog from '~/components/pub/base/modal/dialog.vue'
+import RecordConfirmation from '~/components/pub/custom-ui/confirmation/record-confirmation.vue'
+import { ActionEvents } from '~/components/pub/custom-ui/data/types'
+import Header from '~/components/pub/custom-ui/nav-header/header.vue'
+import { usePaginatedList } from '~/composables/usePaginatedList'
+import { schemaConf, unitConf } from './entry'
+
+// #region State & Computed
+// Dialog state
+const isFormEntryDialogOpen = ref(false)
+const isRecordConfirmationOpen = ref(false)
+
+// Table action rowId provider
+const recId = ref(0)
+const recAction = ref('')
+const recItem = ref(null)
+
+async function fetchUnitData(params: any) {
+ const endpoint = transform('/api/v1/patient', params)
+ return await xfetch(endpoint)
+}
+
+// Menggunakan composable untuk pagination
+const {
+ data,
+ isLoading,
+ paginationMeta,
+ searchInput,
+ handlePageChange,
+ handleSearch,
+ fetchData: getUnitList,
+} = usePaginatedList({
+ fetchFn: fetchUnitData,
+ entityName: 'unit',
+})
+
+const headerPrep: HeaderPrep = {
+ title: 'Unit',
+ icon: 'i-lucide-box',
+ refSearchNav: {
+ placeholder: 'Cari (min. 3 karakter)...',
+ minLength: 3,
+ debounceMs: 500,
+ showValidationFeedback: true,
+ onInput: (_val: string) => {
+ // Handle search input - this will be triggered by the header component
+ },
+ onClick: () => {
+ // Handle search button click if needed
+ },
+ onClear: () => {
+ // Handle search clear
+ },
+ },
+ addNav: {
+ label: 'Tambah Unit',
+ icon: 'i-lucide-send',
+ onClick: () => {
+ isFormEntryDialogOpen.value = true
+ },
+ },
+}
+
+provide('rec_id', recId)
+provide('rec_action', recAction)
+provide('rec_item', recItem)
+provide('table_data_loader', isLoading)
+// #endregion
+
+// #region Functions
+
+async function handleDeleteRow(record: any) {
+ try {
+ // TODO : hit backend request untuk delete
+ console.log('Deleting record:', record)
+
+ // Simulate API call
+ // const response = await xfetch(`/api/v1/unit/${record.id}`, {
+ // method: 'DELETE'
+ // })
+
+ // Refresh data setelah berhasil delete
+ await getUnitList()
+
+ // TODO: Show success message
+ console.log('Record deleted successfully')
+ } catch (error) {
+ console.error('Error deleting record:', error)
+ // TODO: Show error message
+ } finally {
+ // Reset record state
+ recId.value = 0
+ recAction.value = ''
+ recItem.value = null
+ }
+}
+
+// #endregion region
+
+// #region Form event handlers
+
+function onCancelForm(resetForm: () => void) {
+ isFormEntryDialogOpen.value = false
+ setTimeout(() => {
+ resetForm()
+ }, 500)
+}
+
+async function onSubmitForm(values: any, resetForm: () => void) {
+ let isSuccess = false
+ try {
+ // TODO: Implement form submission logic
+ console.log('Form submitted:', values)
+
+ // Simulate API call
+ // const response = await xfetch('/api/v1/unit', {
+ // method: 'POST',
+ // body: JSON.stringify(values)
+ // })
+
+ // If successful, mark as success and close dialog
+ isFormEntryDialogOpen.value = false
+ isSuccess = true
+
+ // Refresh data after successful submission
+ await getUnitList()
+
+ // TODO: Show success message
+ console.log('Unit created successfully')
+ } catch (error: unknown) {
+ console.warn('Error submitting form:', error)
+ isSuccess = false
+ // Don't close dialog or reset form on error
+ // TODO: Show error message to user
+ } finally {
+ if (isSuccess) {
+ setTimeout(() => {
+ resetForm()
+ }, 500)
+ }
+ }
+}
+// #endregion
+
+// #region Watchers
+
+// Watch for row actions
+watch(recId, () => {
+ switch (recAction.value) {
+ case ActionEvents.showEdit:
+ // TODO: Handle edit action
+ // isFormEntryDialogOpen.value = true
+ break
+ case ActionEvents.showConfirmDelete:
+ // Trigger confirmation modal open
+ isRecordConfirmationOpen.value = true
+ break
+ }
+})
+
+// Handle confirmation result
+function handleConfirmDelete(record: any, action: string) {
+ console.log('Confirmed action:', action, 'for record:', record)
+ handleDeleteRow(record)
+}
+
+function handleCancelConfirmation() {
+ // Reset record state when cancelled
+ recId.value = 0
+ recAction.value = ''
+ recItem.value = null
+}
+// #endregion
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ID: {{ record?.id }}
+
Nama: {{ record.firstName }}
+
Kode: {{ record.cellphone }}
+
+
+
+
+
+
diff --git a/app/components/content/unit/list.vue b/app/components/content/unit/list.vue
index b54b3c0c..3dcd184d 100644
--- a/app/components/content/unit/list.vue
+++ b/app/components/content/unit/list.vue
@@ -1,29 +1,39 @@
-
+
-
+
+ :schema="UnitSchema"
+ :values="recItem"
+ :is-loading="isProcessing"
+ :is-readonly="isReadonly"
+ @submit="
+ (values: UnitFormData | Record, resetForm: () => void) => {
+ if (recId > 0) {
+ handleActionEdit(recId, values, getUnitList, resetForm, toast)
+ return
+ }
+ handleActionSave(values, getUnitList, resetForm, toast)
+ }
+ "
+ @cancel="handleCancelForm"
+ />
+ v-model:open="isRecordConfirmationOpen"
+ action="delete"
+ :record="recItem"
+ @confirm="() => handleActionRemove(recId, getUnitList, toast)"
+ @cancel=""
+ >
ID: {{ record?.id }}
-
Nama: {{ record.firstName }}
-
Kode: {{ record.cellphone }}
+
Nama: {{ record.name }}
+
Kode: {{ record.code }}
-
-
diff --git a/app/components/content/uom/list.vue b/app/components/content/uom/list.vue
index bcb01444..6e6bda1b 100644
--- a/app/components/content/uom/list.vue
+++ b/app/components/content/uom/list.vue
@@ -2,8 +2,8 @@
// Components
import Dialog from '~/components/pub/base/modal/dialog.vue'
import Header from '~/components/pub/custom-ui/nav-header/prep.vue'
-import AppUomEntryForm from '~/components/app/uom/entry-form.vue'
import RecordConfirmation from '~/components/pub/custom-ui/confirmation/record-confirmation.vue'
+import AppUomEntryForm from '~/components/app/uom/entry-form.vue'
// Helpers
import { usePaginatedList } from '~/composables/usePaginatedList'
@@ -57,7 +57,9 @@ const headerPrep: HeaderPrep = {
minLength: 3,
debounceMs: 500,
showValidationFeedback: true,
- onInput: (_val: string) => {},
+ onInput: (value: string) => {
+ searchInput.value = value
+ },
onClick: () => {},
onClear: () => {},
},
@@ -113,17 +115,18 @@ onMounted(async () => {
-
+
-
+
(crud: {
+ post: (...args: any[]) => Promise
+ patch: (...args: any[]) => Promise
+ remove: (...args: any[]) => Promise
+}) {
+ const recId = ref(0)
+ const recAction = ref('')
+ const recItem = ref(null)
+ const isReadonly = ref(false)
+ const isProcessing = ref(false)
+ const isFormEntryDialogOpen = ref(false)
+ const isRecordConfirmationOpen = ref(false)
+
+ function onResetState() {
+ recId.value = 0
+ recAction.value = ''
+ recItem.value = null
+ }
+
+ async function handleActionSave(values: any, refresh: () => void, reset: () => void, toast: ToastFn) {
+ isProcessing.value = true
+ await handleAsyncAction<[any], any>({
+ action: crud.post,
+ args: [values],
+ toast,
+ successMessage: 'Data berhasil disimpan',
+ errorMessage: 'Gagal menyimpan data',
+ onSuccess: () => {
+ isFormEntryDialogOpen.value = false
+ if (refresh) refresh()
+ },
+ onFinally: (isSuccess: boolean) => {
+ if (isSuccess) setTimeout(reset, 500)
+ isProcessing.value = false
+ },
+ })
+ }
+
+ async function handleActionEdit(
+ id: number | string,
+ values: any,
+ refresh: () => void,
+ reset: () => void,
+ toast: ToastFn,
+ ) {
+ isProcessing.value = true
+ await handleAsyncAction<[number | string, any], any>({
+ action: crud.patch,
+ args: [id, values],
+ toast,
+ successMessage: 'Data berhasil diubah',
+ errorMessage: 'Gagal mengubah data',
+ onSuccess: () => {
+ isFormEntryDialogOpen.value = false
+ if (refresh) refresh()
+ },
+ onFinally: (isSuccess: boolean) => {
+ if (isSuccess) setTimeout(reset, 500)
+ isProcessing.value = false
+ },
+ })
+ }
+
+ async function handleActionRemove(id: number | string, refresh: () => void, toast: ToastFn) {
+ isProcessing.value = true
+ await handleAsyncAction<[number | string], any>({
+ action: crud.remove,
+ args: [id],
+ toast,
+ successMessage: 'Data berhasil dihapus',
+ errorMessage: 'Gagal menghapus data',
+ onSuccess: () => {
+ isRecordConfirmationOpen.value = false
+ if (refresh) refresh()
+ },
+ onFinally: () => {
+ isProcessing.value = false
+ },
+ })
+ }
+
+ function handleCancelForm(reset: () => void) {
+ isFormEntryDialogOpen.value = false
+ isReadonly.value = false
+ setTimeout(reset, 300)
+ }
+
+ return {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+ }
+}
+
// Reusable async handler for CRUD actions with toast and state management
export type ToastFn = (params: { title: string; description: string; variant: 'default' | 'destructive' }) => void
diff --git a/app/handlers/device.handler.ts b/app/handlers/device.handler.ts
index e269f61b..14de6830 100644
--- a/app/handlers/device.handler.ts
+++ b/app/handlers/device.handler.ts
@@ -1,101 +1,21 @@
-import { ref } from 'vue'
-
-// Handlers
-import { type ToastFn, handleAsyncAction } from '~/handlers/_handler'
-
-// Services
+import { createCrudHandler } from '~/handlers/_handler'
import { postDevice, patchDevice, removeDevice } from '~/services/device.service'
-const recId = ref(0)
-const recAction = ref('')
-const recItem = ref(null)
-const isReadonly = ref(false)
-const isProcessing = ref(false)
-const isFormEntryDialogOpen = ref(false)
-const isRecordConfirmationOpen = ref(false)
-
-function onResetState() {
- recId.value = 0
- recAction.value = ''
- recItem.value = null
-}
-
-export async function handleActionSave(
- values: any,
- refresh: () => void,
- reset: () => void,
- toast: ToastFn
-) {
- isProcessing.value = true;
- await handleAsyncAction<[any], any>({
- action: postDevice,
- args: [values],
- toast,
- successMessage: 'Data berhasil disimpan',
- errorMessage: 'Gagal menyimpan data',
- onSuccess: () => {
- isFormEntryDialogOpen.value = false;
- if (refresh) refresh();
- },
- onFinally: (isSuccess: boolean) => {
- if (isSuccess) setTimeout(reset, 500);
- isProcessing.value = false;
- },
- });
-}
-
-export async function handleActionEdit(
- id: number | string,
- values: any,
- refresh: () => void,
- reset: () => void,
- toast: ToastFn
-) {
- isProcessing.value = true;
- await handleAsyncAction<[number | string, any], any>({
- action: patchDevice,
- args: [id, values],
- toast,
- successMessage: 'Data berhasil diubah',
- errorMessage: 'Gagal mengubah data',
- onSuccess: () => {
- isFormEntryDialogOpen.value = false;
- if (refresh) refresh();
- },
- onFinally: (isSuccess: boolean) => {
- if (isSuccess) setTimeout(reset, 500);
- isProcessing.value = false;
- },
- });
-}
-
-export async function handleActionRemove(
- id: number | string,
- refresh: () => void,
- toast: ToastFn
-) {
- isProcessing.value = true;
- await handleAsyncAction<[number | string], any>({
- action: removeDevice,
- args: [id],
- toast,
- successMessage: 'Data berhasil dihapus',
- errorMessage: 'Gagal menghapus data',
- onSuccess: () => {
- if (refresh) refresh();
- },
- onFinally: () => {
- onResetState();
- isProcessing.value = false;
- },
- });
-}
-
-export function handleCancelForm(reset: () => void) {
- isFormEntryDialogOpen.value = false
- setTimeout(() => {
- reset()
- }, 500)
-}
-
-export { recId, recAction, recItem, isReadonly, isProcessing, isFormEntryDialogOpen, isRecordConfirmationOpen }
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = createCrudHandler({
+ post: postDevice,
+ patch: patchDevice,
+ remove: removeDevice,
+})
diff --git a/app/handlers/division-position.handler.ts b/app/handlers/division-position.handler.ts
new file mode 100644
index 00000000..dcbfc7fd
--- /dev/null
+++ b/app/handlers/division-position.handler.ts
@@ -0,0 +1,21 @@
+import { createCrudHandler } from '~/handlers/_handler'
+import { postDivisionPosition, patchDivisionPosition, removeDivisionPosition } from '~/services/division-position.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = createCrudHandler({
+ post: postDivisionPosition,
+ patch: patchDivisionPosition,
+ remove: removeDivisionPosition,
+})
diff --git a/app/handlers/division.handler.ts b/app/handlers/division.handler.ts
new file mode 100644
index 00000000..e830260f
--- /dev/null
+++ b/app/handlers/division.handler.ts
@@ -0,0 +1,21 @@
+import { createCrudHandler } from '~/handlers/_handler'
+import { postDivision, patchDivision, removeDivision } from '~/services/division.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = createCrudHandler({
+ post: postDivision,
+ patch: patchDivision,
+ remove: removeDivision,
+})
diff --git a/app/handlers/installation.handler.ts b/app/handlers/installation.handler.ts
new file mode 100644
index 00000000..d3a1d06e
--- /dev/null
+++ b/app/handlers/installation.handler.ts
@@ -0,0 +1,21 @@
+import { createCrudHandler } from '~/handlers/_handler'
+import { postInstallation, patchInstallation, removeInstallation } from '~/services/installation.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = createCrudHandler({
+ post: postInstallation,
+ patch: patchInstallation,
+ remove: removeInstallation,
+})
diff --git a/app/handlers/material.handler.ts b/app/handlers/material.handler.ts
index d61e5f01..750f7967 100644
--- a/app/handlers/material.handler.ts
+++ b/app/handlers/material.handler.ts
@@ -1,92 +1,21 @@
-import { ref } from 'vue'
-
-// Handlers
-import { type ToastFn, handleAsyncAction } from '~/handlers/_handler'
-
-// Services
+import { createCrudHandler } from '~/handlers/_handler'
import { postMaterial, patchMaterial, removeMaterial } from '~/services/material.service'
-const recId = ref(0)
-const recAction = ref('')
-const recItem = ref(null)
-const isReadonly = ref(false)
-const isProcessing = ref(false)
-const isFormEntryDialogOpen = ref(false)
-const isRecordConfirmationOpen = ref(false)
-
-function onResetState() {
- recId.value = 0
- recAction.value = ''
- recItem.value = null
-}
-
-export async function handleActionSave(values: any, refresh: () => void, reset: () => void, toast: ToastFn) {
- isProcessing.value = true
- await handleAsyncAction<[any], any>({
- action: postMaterial,
- args: [values],
- toast,
- successMessage: 'Data berhasil disimpan',
- errorMessage: 'Gagal menyimpan data',
- onSuccess: () => {
- isFormEntryDialogOpen.value = false
- if (refresh) refresh()
- },
- onFinally: (isSuccess: boolean) => {
- if (isSuccess) setTimeout(reset, 500)
- isProcessing.value = false
- },
- })
-}
-
-export async function handleActionEdit(
- id: number | string,
- values: any,
- refresh: () => void,
- reset: () => void,
- toast: ToastFn,
-) {
- isProcessing.value = true
- await handleAsyncAction<[number | string, any], any>({
- action: patchMaterial,
- args: [id, values],
- toast,
- successMessage: 'Data berhasil diubah',
- errorMessage: 'Gagal mengubah data',
- onSuccess: () => {
- isFormEntryDialogOpen.value = false
- if (refresh) refresh()
- },
- onFinally: (isSuccess: boolean) => {
- if (isSuccess) setTimeout(reset, 500)
- isProcessing.value = false
- },
- })
-}
-
-export async function handleActionRemove(id: number | string, refresh: () => void, toast: ToastFn) {
- isProcessing.value = true
- await handleAsyncAction<[number | string], any>({
- action: removeMaterial,
- args: [id],
- toast,
- successMessage: 'Data berhasil dihapus',
- errorMessage: 'Gagal menghapus data',
- onSuccess: () => {
- if (refresh) refresh()
- },
- onFinally: () => {
- onResetState()
- isProcessing.value = false
- },
- })
-}
-
-export function handleCancelForm(reset: () => void) {
- isFormEntryDialogOpen.value = false
- setTimeout(() => {
- reset()
- }, 500)
-}
-
-export { recId, recAction, recItem, isReadonly, isProcessing, isFormEntryDialogOpen, isRecordConfirmationOpen }
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = createCrudHandler({
+ post: postMaterial,
+ patch: patchMaterial,
+ remove: removeMaterial,
+})
diff --git a/app/handlers/medicine-group.handler.ts b/app/handlers/medicine-group.handler.ts
index f349355f..998ab285 100644
--- a/app/handlers/medicine-group.handler.ts
+++ b/app/handlers/medicine-group.handler.ts
@@ -1,101 +1,21 @@
-import { ref } from 'vue'
-
-// Handlers
-import { type ToastFn, handleAsyncAction } from '~/handlers/_handler'
-
-// Services
+import { createCrudHandler } from '~/handlers/_handler'
import { postMedicineGroup, patchMedicineGroup, removeMedicineGroup } from '~/services/medicine-group.service'
-const recId = ref(0)
-const recAction = ref('')
-const recItem = ref(null)
-const isReadonly = ref(false)
-const isProcessing = ref(false)
-const isFormEntryDialogOpen = ref(false)
-const isRecordConfirmationOpen = ref(false)
-
-function onResetState() {
- recId.value = 0
- recAction.value = ''
- recItem.value = null
-}
-
-export async function handleActionSave(
- values: any,
- refresh: () => void,
- reset: () => void,
- toast: ToastFn
-) {
- isProcessing.value = true;
- await handleAsyncAction<[any], any>({
- action: postMedicineGroup,
- args: [values],
- toast,
- successMessage: 'Data berhasil disimpan',
- errorMessage: 'Gagal menyimpan data',
- onSuccess: () => {
- isFormEntryDialogOpen.value = false;
- if (refresh) refresh();
- },
- onFinally: (isSuccess: boolean) => {
- if (isSuccess) setTimeout(reset, 500);
- isProcessing.value = false;
- },
- });
-}
-
-export async function handleActionEdit(
- id: number | string,
- values: any,
- refresh: () => void,
- reset: () => void,
- toast: ToastFn
-) {
- isProcessing.value = true;
- await handleAsyncAction<[number | string, any], any>({
- action: patchMedicineGroup,
- args: [id, values],
- toast,
- successMessage: 'Data berhasil diubah',
- errorMessage: 'Gagal mengubah data',
- onSuccess: () => {
- isFormEntryDialogOpen.value = false;
- if (refresh) refresh();
- },
- onFinally: (isSuccess: boolean) => {
- if (isSuccess) setTimeout(reset, 500);
- isProcessing.value = false;
- },
- });
-}
-
-export async function handleActionRemove(
- id: number | string,
- refresh: () => void,
- toast: ToastFn
-) {
- isProcessing.value = true;
- await handleAsyncAction<[number | string], any>({
- action: removeMedicineGroup,
- args: [id],
- toast,
- successMessage: 'Data berhasil dihapus',
- errorMessage: 'Gagal menghapus data',
- onSuccess: () => {
- if (refresh) refresh();
- },
- onFinally: () => {
- onResetState();
- isProcessing.value = false;
- },
- });
-}
-
-export function handleCancelForm(reset: () => void) {
- isFormEntryDialogOpen.value = false
- setTimeout(() => {
- reset()
- }, 500)
-}
-
-export { recId, recAction, recItem, isReadonly, isProcessing, isFormEntryDialogOpen, isRecordConfirmationOpen }
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = createCrudHandler({
+ post: postMedicineGroup,
+ patch: patchMedicineGroup,
+ remove: removeMedicineGroup,
+})
diff --git a/app/handlers/medicine-method.handler.ts b/app/handlers/medicine-method.handler.ts
index 2a681776..df4e0ff9 100644
--- a/app/handlers/medicine-method.handler.ts
+++ b/app/handlers/medicine-method.handler.ts
@@ -1,101 +1,21 @@
-import { ref } from 'vue'
-
-// Handlers
-import { type ToastFn, handleAsyncAction } from '~/handlers/_handler'
-
-// Services
+import { createCrudHandler } from '~/handlers/_handler'
import { postMedicineMethod, patchMedicineMethod, removeMedicineMethod } from '~/services/medicine-method.service'
-const recId = ref(0)
-const recAction = ref('')
-const recItem = ref(null)
-const isReadonly = ref(false)
-const isProcessing = ref(false)
-const isFormEntryDialogOpen = ref(false)
-const isRecordConfirmationOpen = ref(false)
-
-function onResetState() {
- recId.value = 0
- recAction.value = ''
- recItem.value = null
-}
-
-export async function handleActionSave(
- values: any,
- refresh: () => void,
- reset: () => void,
- toast: ToastFn
-) {
- isProcessing.value = true;
- await handleAsyncAction<[any], any>({
- action: postMedicineMethod,
- args: [values],
- toast,
- successMessage: 'Data berhasil disimpan',
- errorMessage: 'Gagal menyimpan data',
- onSuccess: () => {
- isFormEntryDialogOpen.value = false;
- if (refresh) refresh();
- },
- onFinally: (isSuccess: boolean) => {
- if (isSuccess) setTimeout(reset, 500);
- isProcessing.value = false;
- },
- });
-}
-
-export async function handleActionEdit(
- id: number | string,
- values: any,
- refresh: () => void,
- reset: () => void,
- toast: ToastFn
-) {
- isProcessing.value = true;
- await handleAsyncAction<[number | string, any], any>({
- action: patchMedicineMethod,
- args: [id, values],
- toast,
- successMessage: 'Data berhasil diubah',
- errorMessage: 'Gagal mengubah data',
- onSuccess: () => {
- isFormEntryDialogOpen.value = false;
- if (refresh) refresh();
- },
- onFinally: (isSuccess: boolean) => {
- if (isSuccess) setTimeout(reset, 500);
- isProcessing.value = false;
- },
- });
-}
-
-export async function handleActionRemove(
- id: number | string,
- refresh: () => void,
- toast: ToastFn
-) {
- isProcessing.value = true;
- await handleAsyncAction<[number | string], any>({
- action: removeMedicineMethod,
- args: [id],
- toast,
- successMessage: 'Data berhasil dihapus',
- errorMessage: 'Gagal menghapus data',
- onSuccess: () => {
- if (refresh) refresh();
- },
- onFinally: () => {
- onResetState();
- isProcessing.value = false;
- },
- });
-}
-
-export function handleCancelForm(reset: () => void) {
- isFormEntryDialogOpen.value = false
- setTimeout(() => {
- reset()
- }, 500)
-}
-
-export { recId, recAction, recItem, isReadonly, isProcessing, isFormEntryDialogOpen, isRecordConfirmationOpen }
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = createCrudHandler({
+ post: postMedicineMethod,
+ patch: patchMedicineMethod,
+ remove: removeMedicineMethod,
+})
diff --git a/app/handlers/medicine.handler.ts b/app/handlers/medicine.handler.ts
new file mode 100644
index 00000000..d550f11b
--- /dev/null
+++ b/app/handlers/medicine.handler.ts
@@ -0,0 +1,21 @@
+import { createCrudHandler } from '~/handlers/_handler'
+import { postMedicine, patchMedicine, removeMedicine } from '~/services/medicine.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = createCrudHandler({
+ post: postMedicine,
+ patch: patchMedicine,
+ remove: removeMedicine,
+})
diff --git a/app/handlers/specialist.handler.ts b/app/handlers/specialist.handler.ts
new file mode 100644
index 00000000..445f8c15
--- /dev/null
+++ b/app/handlers/specialist.handler.ts
@@ -0,0 +1,21 @@
+import { createCrudHandler } from '~/handlers/_handler'
+import { postSpecialist, patchSpecialist, removeSpecialist } from '~/services/specialist.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = createCrudHandler({
+ post: postSpecialist,
+ patch: patchSpecialist,
+ remove: removeSpecialist,
+})
diff --git a/app/handlers/subspecialist.handler.ts b/app/handlers/subspecialist.handler.ts
new file mode 100644
index 00000000..9fc7a67e
--- /dev/null
+++ b/app/handlers/subspecialist.handler.ts
@@ -0,0 +1,21 @@
+import { createCrudHandler } from '~/handlers/_handler'
+import { postSubspecialist, patchSubspecialist, removeSubspecialist } from '~/services/subspecialist.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = createCrudHandler({
+ post: postSubspecialist,
+ patch: patchSubspecialist,
+ remove: removeSubspecialist,
+})
diff --git a/app/handlers/unit.handler.ts b/app/handlers/unit.handler.ts
new file mode 100644
index 00000000..ff235bb4
--- /dev/null
+++ b/app/handlers/unit.handler.ts
@@ -0,0 +1,21 @@
+import { createCrudHandler } from '~/handlers/_handler'
+import { postUnit, patchUnit, removeUnit } from '~/services/unit.service'
+
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = createCrudHandler({
+ post: postUnit,
+ patch: patchUnit,
+ remove: removeUnit,
+})
diff --git a/app/handlers/uom.handler.ts b/app/handlers/uom.handler.ts
index e24fbcfa..dd018400 100644
--- a/app/handlers/uom.handler.ts
+++ b/app/handlers/uom.handler.ts
@@ -1,92 +1,21 @@
-import { ref } from 'vue'
-
-// Handlers
-import { type ToastFn, handleAsyncAction } from '~/handlers/_handler'
-
-// Services
+import { createCrudHandler } from '~/handlers/_handler'
import { postUom, patchUom, removeUom } from '~/services/uom.service'
-const recId = ref(0)
-const recAction = ref('')
-const recItem = ref(null)
-const isReadonly = ref(false)
-const isProcessing = ref(false)
-const isFormEntryDialogOpen = ref(false)
-const isRecordConfirmationOpen = ref(false)
-
-function onResetState() {
- recId.value = 0
- recAction.value = ''
- recItem.value = null
-}
-
-export async function handleActionSave(values: any, refresh: () => void, reset: () => void, toast: ToastFn) {
- isProcessing.value = true
- await handleAsyncAction<[any], any>({
- action: postUom,
- args: [values],
- toast,
- successMessage: 'Data berhasil disimpan',
- errorMessage: 'Gagal menyimpan data',
- onSuccess: () => {
- isFormEntryDialogOpen.value = false
- if (refresh) refresh()
- },
- onFinally: (isSuccess: boolean) => {
- if (isSuccess) setTimeout(reset, 500)
- isProcessing.value = false
- },
- })
-}
-
-export async function handleActionEdit(
- id: number | string,
- values: any,
- refresh: () => void,
- reset: () => void,
- toast: ToastFn,
-) {
- isProcessing.value = true
- await handleAsyncAction<[number | string, any], any>({
- action: patchUom,
- args: [id, values],
- toast,
- successMessage: 'Data berhasil diubah',
- errorMessage: 'Gagal mengubah data',
- onSuccess: () => {
- isFormEntryDialogOpen.value = false
- if (refresh) refresh()
- },
- onFinally: (isSuccess: boolean) => {
- if (isSuccess) setTimeout(reset, 500)
- isProcessing.value = false
- },
- })
-}
-
-export async function handleActionRemove(id: number | string, refresh: () => void, toast: ToastFn) {
- isProcessing.value = true
- await handleAsyncAction<[number | string], any>({
- action: removeUom,
- args: [id],
- toast,
- successMessage: 'Data berhasil dihapus',
- errorMessage: 'Gagal menghapus data',
- onSuccess: () => {
- if (refresh) refresh()
- },
- onFinally: () => {
- onResetState()
- isProcessing.value = false
- },
- })
-}
-
-export function handleCancelForm(reset: () => void) {
- isFormEntryDialogOpen.value = false
- setTimeout(() => {
- reset()
- }, 500)
-}
-
-export { recId, recAction, recItem, isReadonly, isProcessing, isFormEntryDialogOpen, isRecordConfirmationOpen }
+export const {
+ recId,
+ recAction,
+ recItem,
+ isReadonly,
+ isProcessing,
+ isFormEntryDialogOpen,
+ isRecordConfirmationOpen,
+ onResetState,
+ handleActionSave,
+ handleActionEdit,
+ handleActionRemove,
+ handleCancelForm,
+} = createCrudHandler({
+ post: postUom,
+ patch: patchUom,
+ remove: removeUom,
+})
diff --git a/app/models/division.ts b/app/models/division.ts
new file mode 100644
index 00000000..e52e2cf6
--- /dev/null
+++ b/app/models/division.ts
@@ -0,0 +1,10 @@
+export interface Division {
+ code: string
+ name: string
+}
+
+export interface DivisionPosition {
+ code: string
+ name: string
+ division_id: number
+}
diff --git a/app/models/installation.ts b/app/models/installation.ts
new file mode 100644
index 00000000..c662714e
--- /dev/null
+++ b/app/models/installation.ts
@@ -0,0 +1,5 @@
+export interface Installation {
+ code: string
+ name: string
+ encounterClass_code: string
+}
diff --git a/app/models/medicine.ts b/app/models/medicine.ts
index 1d01991b..e49076fa 100644
--- a/app/models/medicine.ts
+++ b/app/models/medicine.ts
@@ -4,30 +4,21 @@ export interface MedicineBase {
}
export interface Medicine {
- id: string
- name: string
code: string
+ name: string
medicineGroup_code: string
medicineMethod_code: string
uom_code: string
- type: string
- dose: string
- infra_id: string
- stock: string
- status: string
+ infra_id?: string | null
+ stock: number
}
-export interface CreateDto {
- name: string
- code: string
- medicineGroup_code: string
- medicineMethod_code: string
- uom_code: string
- type: string
- dose: string
- infra_id: string
- stock: string
- status: string
+export interface CreateMedicineDto extends Medicine {
+
+}
+
+export interface UpdateMedicineDto extends CreateMedicineDto {
+ id: string | number
}
export interface GetListDto {
@@ -49,7 +40,7 @@ export interface GetDetailDto {
id?: string
}
-export interface UpdateDto extends CreateDto {
+export interface UpdateDto extends CreateMedicineDto {
id?: number
}
@@ -57,17 +48,14 @@ export interface DeleteDto {
id?: string
}
-export function genMedicine(): CreateDto {
+export function genMedicine(): CreateMedicineDto {
return {
name: 'name',
code: 'code',
medicineGroup_code: 'medicineGroup_code',
medicineMethod_code: 'medicineMethod_code',
uom_code: 'uom_code',
- type: 'type',
- dose: 'dose',
- infra_id: 'infra_id',
- stock: 'stock',
- status: 'status',
+ infra_id: null,
+ stock: 0
}
}
diff --git a/app/models/specialist.ts b/app/models/specialist.ts
new file mode 100644
index 00000000..39b23390
--- /dev/null
+++ b/app/models/specialist.ts
@@ -0,0 +1,6 @@
+export interface Specialist {
+ id?: number
+ code: string
+ name: string
+ unit_id: number | string
+}
diff --git a/app/models/subspecialist.ts b/app/models/subspecialist.ts
new file mode 100644
index 00000000..32591ab3
--- /dev/null
+++ b/app/models/subspecialist.ts
@@ -0,0 +1,5 @@
+export interface Subspecialist {
+ code: string
+ name: string
+ specialist_id: number | string
+}
diff --git a/app/models/unit.ts b/app/models/unit.ts
new file mode 100644
index 00000000..27348354
--- /dev/null
+++ b/app/models/unit.ts
@@ -0,0 +1,6 @@
+export interface Unit {
+ id?: number
+ code: string
+ name: string
+ installation?: string | number
+}
diff --git a/app/pages/(features)/org-src/division/index.vue b/app/pages/(features)/org-src/division/index.vue
index e0a8a1fc..ed5f1c3b 100644
--- a/app/pages/(features)/org-src/division/index.vue
+++ b/app/pages/(features)/org-src/division/index.vue
@@ -7,7 +7,7 @@ definePageMeta({
// middleware: ['rbac'],
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
title: 'Daftar Divisi',
- contentFrame: 'cf-full-width',
+ contentFrame: 'cf-container-lg',
})
const route = useRoute()
diff --git a/app/pages/(features)/org-src/specialist/index.vue b/app/pages/(features)/org-src/specialist/index.vue
index e3e47d72..2f01b48b 100644
--- a/app/pages/(features)/org-src/specialist/index.vue
+++ b/app/pages/(features)/org-src/specialist/index.vue
@@ -6,8 +6,8 @@ import Error from '~/components/pub/base/error/error.vue'
definePageMeta({
// middleware: ['rbac'],
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
- title: 'List Specialist',
- contentFrame: 'cf-full-width',
+ title: 'Daftar Specialist',
+ contentFrame: 'cf-container-lg',
})
const route = useRoute()
diff --git a/app/pages/(features)/org-src/subspecialist/index.vue b/app/pages/(features)/org-src/subspecialist/index.vue
index 7065ca77..9b29d034 100644
--- a/app/pages/(features)/org-src/subspecialist/index.vue
+++ b/app/pages/(features)/org-src/subspecialist/index.vue
@@ -6,8 +6,8 @@ import Error from '~/components/pub/base/error/error.vue'
definePageMeta({
// middleware: ['rbac'],
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
- title: 'List Specialist',
- contentFrame: 'cf-full-width',
+ title: 'Daftar Subspecialist',
+ contentFrame: 'cf-container-lg',
})
const route = useRoute()
diff --git a/app/pages/(features)/org-src/unit/index.vue b/app/pages/(features)/org-src/unit/index.vue
index b4a96759..baa77d6b 100644
--- a/app/pages/(features)/org-src/unit/index.vue
+++ b/app/pages/(features)/org-src/unit/index.vue
@@ -6,8 +6,8 @@ import Error from '~/components/pub/base/error/error.vue'
definePageMeta({
// middleware: ['rbac'],
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
- title: 'List Unit',
- contentFrame: 'cf-full-width',
+ title: 'Daftar Unit',
+ contentFrame: 'cf-container-lg',
})
const route = useRoute()
diff --git a/app/schemas/division.schema.ts b/app/schemas/division.schema.ts
new file mode 100644
index 00000000..1aecb3c6
--- /dev/null
+++ b/app/schemas/division.schema.ts
@@ -0,0 +1,12 @@
+import { z } from 'zod'
+import type { Division, DivisionPosition } from '~/models/division'
+
+const DivisionSchema = 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'),
+})
+
+type DivisionFormData = z.infer & (Division | DivisionPosition)
+
+export { DivisionSchema }
+export type { DivisionFormData }
diff --git a/app/schemas/medicine.schema.ts b/app/schemas/medicine.schema.ts
index 13f01d15..44113777 100644
--- a/app/schemas/medicine.schema.ts
+++ b/app/schemas/medicine.schema.ts
@@ -1,12 +1,13 @@
import { z } from 'zod'
-import type { MedicineBase } from '~/models/medicine'
-const MedicineBaseSchema = 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')
+export const MedicineSchema = z.object({
+ code: z.string({ required_error: 'Kode harus diisi' }).min(1, 'Kode minimal 1 karakter'),
+ name: z.string({ required_error: 'Nama harus diisi' }).min(1, 'Nama minimal 1 karakter'),
+ medicineGroup_code: z.string({ required_error: 'Kelompok obat harus diisi' }).min(1, 'Kelompok obat harus diisi'),
+ medicineMethod_code: z.string({ required_error: 'Metode pemberian harus diisi' }).min(1, 'Metode pemberian harus diisi'),
+ uom_code: z.string({ required_error: 'Satuan harus diisi' }).min(1, 'Satuan harus diisi'),
+ infra_id: z.number().nullable().optional(),
+ stock: z.preprocess((val) => Number(val), z.number({ invalid_type_error: 'Stok harus berupa angka' }).min(1, 'Stok harus lebih besar dari 0')),
})
-type MedicineBaseFormData = z.infer & MedicineBase
-
-export { MedicineBaseSchema }
-export type { MedicineBaseFormData }
+export type MedicineFormData = z.infer
diff --git a/app/schemas/specialist.schema.ts b/app/schemas/specialist.schema.ts
new file mode 100644
index 00000000..10715d20
--- /dev/null
+++ b/app/schemas/specialist.schema.ts
@@ -0,0 +1,13 @@
+import { z } from 'zod'
+import type { Specialist } from '~/models/specialist'
+
+const SpecialistSchema = 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'),
+ unit_id: z.number().positive('Unit harus diisi'),
+})
+
+type SpecialistFormData = z.infer & Specialist
+
+export { SpecialistSchema }
+export type { SpecialistFormData }
diff --git a/app/schemas/subspecialist.schema.ts b/app/schemas/subspecialist.schema.ts
new file mode 100644
index 00000000..d485c95c
--- /dev/null
+++ b/app/schemas/subspecialist.schema.ts
@@ -0,0 +1,13 @@
+import { z } from 'zod'
+import type { Subspecialist } from '~/models/subspecialist'
+
+const SubspecialistSchema = 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'),
+ specialist_id: z.number().positive('Spesialis harus diisi'),
+})
+
+type SubspecialistFormData = z.infer & Subspecialist
+
+export { SubspecialistSchema }
+export type { SubspecialistFormData }
diff --git a/app/schemas/unit.schema.ts b/app/schemas/unit.schema.ts
new file mode 100644
index 00000000..30a5a075
--- /dev/null
+++ b/app/schemas/unit.schema.ts
@@ -0,0 +1,12 @@
+import { z } from 'zod'
+import type { Unit } from '~/models/unit'
+
+const UnitSchema = 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'),
+})
+
+type UnitFormData = z.infer & Unit
+
+export { UnitSchema }
+export type { UnitFormData }
diff --git a/app/services/division-position.service.ts b/app/services/division-position.service.ts
new file mode 100644
index 00000000..07cfbd15
--- /dev/null
+++ b/app/services/division-position.service.ts
@@ -0,0 +1,79 @@
+import { xfetch } from '~/composables/useXfetch'
+
+const mainUrl = '/api/v1/division-position'
+
+export async function getDivisionPositions(params: any = null) {
+ try {
+ let url = mainUrl
+ if (params && typeof params === 'object' && Object.keys(params).length > 0) {
+ const searchParams = new URLSearchParams()
+ for (const key in params) {
+ if (params[key] !== null && params[key] !== undefined && params[key] !== '') {
+ searchParams.append(key, params[key])
+ }
+ }
+ const queryString = searchParams.toString()
+ if (queryString) url += `?${queryString}`
+ }
+ const resp = await xfetch(mainUrl, 'GET')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error fetching division-positions:', error)
+ throw new Error('Failed to fetch division-positions')
+ }
+}
+
+export async function getDivisionPositionDetail(id: number | string) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'GET')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error fetching division-position detail:', error)
+ throw new Error('Failed to get division-position detail')
+ }
+}
+
+export async function postDivisionPosition(record: any) {
+ try {
+ const resp = await xfetch(mainUrl, 'POST', record)
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error posting division-position:', error)
+ throw new Error('Failed to post division-position')
+ }
+}
+
+export async function patchDivisionPosition(id: number | string, record: any) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'PATCH', record)
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error putting division-position:', error)
+ throw new Error('Failed to put division-position')
+ }
+}
+
+export async function removeDivisionPosition(id: number | string) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'DELETE')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error deleting record:', error)
+ throw new Error('Failed to delete division-position')
+ }
+}
diff --git a/app/services/division.service.ts b/app/services/division.service.ts
new file mode 100644
index 00000000..38cd6118
--- /dev/null
+++ b/app/services/division.service.ts
@@ -0,0 +1,79 @@
+import { xfetch } from '~/composables/useXfetch'
+
+const mainUrl = '/api/v1/division'
+
+export async function getDivisions(params: any = null) {
+ try {
+ let url = mainUrl
+ if (params && typeof params === 'object' && Object.keys(params).length > 0) {
+ const searchParams = new URLSearchParams()
+ for (const key in params) {
+ if (params[key] !== null && params[key] !== undefined && params[key] !== '') {
+ searchParams.append(key, params[key])
+ }
+ }
+ const queryString = searchParams.toString()
+ if (queryString) url += `?${queryString}`
+ }
+ const resp = await xfetch(mainUrl, 'GET')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error fetching divisions:', error)
+ throw new Error('Failed to fetch divisions')
+ }
+}
+
+export async function getDivisionDetail(id: number | string) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'GET')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error fetching division detail:', error)
+ throw new Error('Failed to get division detail')
+ }
+}
+
+export async function postDivision(record: any) {
+ try {
+ const resp = await xfetch(mainUrl, 'POST', record)
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error posting division:', error)
+ throw new Error('Failed to post division')
+ }
+}
+
+export async function patchDivision(id: number | string, record: any) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'PATCH', record)
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error putting division:', error)
+ throw new Error('Failed to put division')
+ }
+}
+
+export async function removeDivision(id: number | string) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'DELETE')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error deleting record:', error)
+ throw new Error('Failed to delete division')
+ }
+}
diff --git a/app/services/installation.service.ts b/app/services/installation.service.ts
new file mode 100644
index 00000000..8fd9e858
--- /dev/null
+++ b/app/services/installation.service.ts
@@ -0,0 +1,79 @@
+import { xfetch } from '~/composables/useXfetch'
+
+const mainUrl = '/api/v1/installation'
+
+export async function getInstallations(params: any = null) {
+ try {
+ let url = mainUrl
+ if (params && typeof params === 'object' && Object.keys(params).length > 0) {
+ const searchParams = new URLSearchParams()
+ for (const key in params) {
+ if (params[key] !== null && params[key] !== undefined && params[key] !== '') {
+ searchParams.append(key, params[key])
+ }
+ }
+ const queryString = searchParams.toString()
+ if (queryString) url += `?${queryString}`
+ }
+ const resp = await xfetch(mainUrl, 'GET')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error fetching installations:', error)
+ throw new Error('Failed to fetch installations')
+ }
+}
+
+export async function getInstallationDetail(id: number | string) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'GET')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error fetching installation detail:', error)
+ throw new Error('Failed to get installation detail')
+ }
+}
+
+export async function postInstallation(record: any) {
+ try {
+ const resp = await xfetch(mainUrl, 'POST', record)
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error posting installation:', error)
+ throw new Error('Failed to post installation')
+ }
+}
+
+export async function patchInstallation(id: number | string, record: any) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'PATCH', record)
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error putting installation:', error)
+ throw new Error('Failed to put installation')
+ }
+}
+
+export async function removeInstallation(id: number | string) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'DELETE')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error deleting record:', error)
+ throw new Error('Failed to delete installation')
+ }
+}
diff --git a/app/services/medicine.service.ts b/app/services/medicine.service.ts
new file mode 100644
index 00000000..04860455
--- /dev/null
+++ b/app/services/medicine.service.ts
@@ -0,0 +1,79 @@
+import { xfetch } from '~/composables/useXfetch'
+
+const mainUrl = '/api/v1/medicine'
+
+export async function getMedicines(params: any = null) {
+ try {
+ let url = mainUrl
+ if (params && typeof params === 'object' && Object.keys(params).length > 0) {
+ const searchParams = new URLSearchParams()
+ for (const key in params) {
+ if (params[key] !== null && params[key] !== undefined && params[key] !== '') {
+ searchParams.append(key, params[key])
+ }
+ }
+ const queryString = searchParams.toString()
+ if (queryString) url += `?${queryString}`
+ }
+ const resp = await xfetch(url, 'GET')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error fetching medicines:', error)
+ throw new Error('Failed to fetch medicines')
+ }
+}
+
+export async function getMedicineDetail(id: number | string) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'GET')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error fetching medicine detail:', error)
+ throw new Error('Failed to get medicine detail')
+ }
+}
+
+export async function postMedicine(record: any) {
+ try {
+ const resp = await xfetch(mainUrl, 'POST', record)
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error posting medicine:', error)
+ throw new Error('Failed to post medicine')
+ }
+}
+
+export async function patchMedicine(id: number | string, record: any) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'PATCH', record)
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error patching medicine:', error)
+ throw new Error('Failed to patch medicine')
+ }
+}
+
+export async function removeMedicine(id: number | string) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'DELETE')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error deleting medicine:', error)
+ throw new Error('Failed to delete medicine')
+ }
+}
diff --git a/app/services/specialist.service.ts b/app/services/specialist.service.ts
new file mode 100644
index 00000000..bd359918
--- /dev/null
+++ b/app/services/specialist.service.ts
@@ -0,0 +1,79 @@
+import { xfetch } from '~/composables/useXfetch'
+
+const mainUrl = '/api/v1/specialist'
+
+export async function getSpecialists(params: any = null) {
+ try {
+ let url = mainUrl
+ if (params && typeof params === 'object' && Object.keys(params).length > 0) {
+ const searchParams = new URLSearchParams()
+ for (const key in params) {
+ if (params[key] !== null && params[key] !== undefined && params[key] !== '') {
+ searchParams.append(key, params[key])
+ }
+ }
+ const queryString = searchParams.toString()
+ if (queryString) url += `?${queryString}`
+ }
+ const resp = await xfetch(mainUrl, 'GET')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error fetching specialists:', error)
+ throw new Error('Failed to fetch specialists')
+ }
+}
+
+export async function getSpecialistDetail(id: number | string) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'GET')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error fetching specialist detail:', error)
+ throw new Error('Failed to get specialist detail')
+ }
+}
+
+export async function postSpecialist(record: any) {
+ try {
+ const resp = await xfetch(mainUrl, 'POST', record)
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error posting specialist:', error)
+ throw new Error('Failed to post specialist')
+ }
+}
+
+export async function patchSpecialist(id: number | string, record: any) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'PATCH', record)
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error putting specialist:', error)
+ throw new Error('Failed to put specialist')
+ }
+}
+
+export async function removeSpecialist(id: number | string) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'DELETE')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error deleting record:', error)
+ throw new Error('Failed to delete specialist')
+ }
+}
diff --git a/app/services/subspecialist.service.ts b/app/services/subspecialist.service.ts
new file mode 100644
index 00000000..c218b748
--- /dev/null
+++ b/app/services/subspecialist.service.ts
@@ -0,0 +1,79 @@
+import { xfetch } from '~/composables/useXfetch'
+
+const mainUrl = '/api/v1/subspecialist'
+
+export async function getSubspecialists(params: any = null) {
+ try {
+ let url = mainUrl
+ if (params && typeof params === 'object' && Object.keys(params).length > 0) {
+ const searchParams = new URLSearchParams()
+ for (const key in params) {
+ if (params[key] !== null && params[key] !== undefined && params[key] !== '') {
+ searchParams.append(key, params[key])
+ }
+ }
+ const queryString = searchParams.toString()
+ if (queryString) url += `?${queryString}`
+ }
+ const resp = await xfetch(mainUrl, 'GET')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error fetching subspecialists:', error)
+ throw new Error('Failed to fetch subspecialists')
+ }
+}
+
+export async function getSubspecialistDetail(id: number | string) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'GET')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error fetching subspecialist detail:', error)
+ throw new Error('Failed to get subspecialist detail')
+ }
+}
+
+export async function postSubspecialist(record: any) {
+ try {
+ const resp = await xfetch(mainUrl, 'POST', record)
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error posting subspecialist:', error)
+ throw new Error('Failed to post subspecialist')
+ }
+}
+
+export async function patchSubspecialist(id: number | string, record: any) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'PATCH', record)
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error putting subspecialist:', error)
+ throw new Error('Failed to put subspecialist')
+ }
+}
+
+export async function removeSubspecialist(id: number | string) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'DELETE')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error deleting record:', error)
+ throw new Error('Failed to delete subspecialist')
+ }
+}
diff --git a/app/services/unit.service.ts b/app/services/unit.service.ts
new file mode 100644
index 00000000..82d565db
--- /dev/null
+++ b/app/services/unit.service.ts
@@ -0,0 +1,79 @@
+import { xfetch } from '~/composables/useXfetch'
+
+const mainUrl = '/api/v1/unit'
+
+export async function getUnits(params: any = null) {
+ try {
+ let url = mainUrl
+ if (params && typeof params === 'object' && Object.keys(params).length > 0) {
+ const searchParams = new URLSearchParams()
+ for (const key in params) {
+ if (params[key] !== null && params[key] !== undefined && params[key] !== '') {
+ searchParams.append(key, params[key])
+ }
+ }
+ const queryString = searchParams.toString()
+ if (queryString) url += `?${queryString}`
+ }
+ const resp = await xfetch(mainUrl, 'GET')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error fetching units:', error)
+ throw new Error('Failed to fetch units')
+ }
+}
+
+export async function getUnitDetail(id: number | string) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'GET')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error fetching unit detail:', error)
+ throw new Error('Failed to get unit detail')
+ }
+}
+
+export async function postUnit(record: any) {
+ try {
+ const resp = await xfetch(mainUrl, 'POST', record)
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error posting unit:', error)
+ throw new Error('Failed to post unit')
+ }
+}
+
+export async function patchUnit(id: number | string, record: any) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'PATCH', record)
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error putting unit:', error)
+ throw new Error('Failed to put unit')
+ }
+}
+
+export async function removeUnit(id: number | string) {
+ try {
+ const resp = await xfetch(`${mainUrl}/${id}`, 'DELETE')
+ const result: any = {}
+ result.success = resp.success
+ result.body = (resp.body as Record) || {}
+ return result
+ } catch (error) {
+ console.error('Error deleting record:', error)
+ throw new Error('Failed to delete unit')
+ }
+}