From 6dd9b2514523727881c133b948556669f0eb41d1 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Fri, 3 Oct 2025 15:10:46 +0700 Subject: [PATCH 1/7] dev: hotfix, enconter process --- app/assets/css/main.css | 2 +- app/components/app/encounter/process.vue | 73 +++++++++++++ app/components/content/encounter/home.vue | 100 ------------------ app/components/content/encounter/process.vue | 47 ++++++++ .../rehab/encounter/[id]/process.vue | 2 +- 5 files changed, 122 insertions(+), 102 deletions(-) create mode 100644 app/components/app/encounter/process.vue delete mode 100644 app/components/content/encounter/home.vue create mode 100644 app/components/content/encounter/process.vue diff --git a/app/assets/css/main.css b/app/assets/css/main.css index b04b1eac..8f547641 100644 --- a/app/assets/css/main.css +++ b/app/assets/css/main.css @@ -174,7 +174,7 @@ body { } body, table, label { - @apply md:!text-xs xl:!text-sm 2xl:!text-base; + @apply md:!text-xs xl:!text-sm 2xl:!text-sm; } /* Container */ diff --git a/app/components/app/encounter/process.vue b/app/components/app/encounter/process.vue new file mode 100644 index 00000000..237c04c2 --- /dev/null +++ b/app/components/app/encounter/process.vue @@ -0,0 +1,73 @@ + + + diff --git a/app/components/content/encounter/home.vue b/app/components/content/encounter/home.vue deleted file mode 100644 index 2a4be548..00000000 --- a/app/components/content/encounter/home.vue +++ /dev/null @@ -1,100 +0,0 @@ - - - diff --git a/app/components/content/encounter/process.vue b/app/components/content/encounter/process.vue new file mode 100644 index 00000000..cdadbd63 --- /dev/null +++ b/app/components/content/encounter/process.vue @@ -0,0 +1,47 @@ + + + diff --git a/app/pages/(features)/rehab/encounter/[id]/process.vue b/app/pages/(features)/rehab/encounter/[id]/process.vue index c1b8b716..8918318d 100644 --- a/app/pages/(features)/rehab/encounter/[id]/process.vue +++ b/app/pages/(features)/rehab/encounter/[id]/process.vue @@ -35,7 +35,7 @@ const canCreate = hasCreateAccess(roleAccess) From d9cedf8d42a49bc77af20645f94bb080e1944020 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Fri, 3 Oct 2025 21:47:28 +0700 Subject: [PATCH 2/7] dev: hotfix, avoid ts warning --- app/pages/(features)/patient/add.vue | 2 +- app/pages/(features)/rehab/encounter/[id]/detail.vue | 2 +- app/pages/(features)/rehab/encounter/[id]/edit.vue | 2 +- app/pages/(features)/rehab/encounter/[id]/process.vue | 2 +- app/pages/(features)/rehab/encounter/add.vue | 2 +- app/pages/(features)/rehab/registration/[id]/detail.vue | 2 +- app/pages/(features)/rehab/registration/[id]/edit.vue | 2 +- app/pages/(features)/rehab/registration/add.vue | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/pages/(features)/patient/add.vue b/app/pages/(features)/patient/add.vue index 6532240a..321ec460 100644 --- a/app/pages/(features)/patient/add.vue +++ b/app/pages/(features)/patient/add.vue @@ -13,7 +13,7 @@ definePageMeta({ const route = useRoute() useHead({ - title: () => route.meta.title, + title: () => `${route.meta.title}`, // backtick to avoid the ts-plugin(2322) warning }) const roleAccess: PagePermission = PAGE_PERMISSIONS['/patient'] diff --git a/app/pages/(features)/rehab/encounter/[id]/detail.vue b/app/pages/(features)/rehab/encounter/[id]/detail.vue index e26b566c..d76dc1e7 100644 --- a/app/pages/(features)/rehab/encounter/[id]/detail.vue +++ b/app/pages/(features)/rehab/encounter/[id]/detail.vue @@ -13,7 +13,7 @@ definePageMeta({ const route = useRoute() useHead({ - title: () => route.meta.title, + title: () => `${route.meta.title}`, // backtick to avoid the ts-plugin(2322) warning }) const roleAccess: PagePermission = PAGE_PERMISSIONS['/rehab/encounter'] diff --git a/app/pages/(features)/rehab/encounter/[id]/edit.vue b/app/pages/(features)/rehab/encounter/[id]/edit.vue index 9391a12d..237a5d2f 100644 --- a/app/pages/(features)/rehab/encounter/[id]/edit.vue +++ b/app/pages/(features)/rehab/encounter/[id]/edit.vue @@ -13,7 +13,7 @@ definePageMeta({ const route = useRoute() useHead({ - title: () => route.meta.title, + title: () => `${route.meta.title}`, // backtick to avoid the ts-plugin(2322) warning }) const roleAccess: PagePermission = PAGE_PERMISSIONS['/rehab/encounter'] diff --git a/app/pages/(features)/rehab/encounter/[id]/process.vue b/app/pages/(features)/rehab/encounter/[id]/process.vue index 8918318d..5ae6fb89 100644 --- a/app/pages/(features)/rehab/encounter/[id]/process.vue +++ b/app/pages/(features)/rehab/encounter/[id]/process.vue @@ -13,7 +13,7 @@ definePageMeta({ const route = useRoute() useHead({ - title: () => route.meta.title, + title: () => `${route.meta.title}`, }) const roleAccess: PagePermission = PAGE_PERMISSIONS['/rehab/encounter'] diff --git a/app/pages/(features)/rehab/encounter/add.vue b/app/pages/(features)/rehab/encounter/add.vue index 1558f645..37b6bde1 100644 --- a/app/pages/(features)/rehab/encounter/add.vue +++ b/app/pages/(features)/rehab/encounter/add.vue @@ -13,7 +13,7 @@ definePageMeta({ const route = useRoute() useHead({ - title: () => route.meta.title, + title: () => `${route.meta.title}`, // backtick to avoid the ts-plugin(2322) warning }) const roleAccess: PagePermission = PAGE_PERMISSIONS['/rehab/encounter'] diff --git a/app/pages/(features)/rehab/registration/[id]/detail.vue b/app/pages/(features)/rehab/registration/[id]/detail.vue index fe91932a..553aa383 100644 --- a/app/pages/(features)/rehab/registration/[id]/detail.vue +++ b/app/pages/(features)/rehab/registration/[id]/detail.vue @@ -13,7 +13,7 @@ definePageMeta({ const route = useRoute() useHead({ - title: () => route.meta.title, + title: () => `${route.meta.title}`, // backtick to avoid the ts-plugin(2322) warning }) const roleAccess: PagePermission = PAGE_PERMISSIONS['/rehab/registration'] diff --git a/app/pages/(features)/rehab/registration/[id]/edit.vue b/app/pages/(features)/rehab/registration/[id]/edit.vue index a2cfab84..b99fb50d 100644 --- a/app/pages/(features)/rehab/registration/[id]/edit.vue +++ b/app/pages/(features)/rehab/registration/[id]/edit.vue @@ -13,7 +13,7 @@ definePageMeta({ const route = useRoute() useHead({ - title: () => route.meta.title, + title: () => `${route.meta.title}`, // backtick to avoid the ts-plugin(2322) warning }) const roleAccess: PagePermission = PAGE_PERMISSIONS['/rehab/registration'] diff --git a/app/pages/(features)/rehab/registration/add.vue b/app/pages/(features)/rehab/registration/add.vue index 1ef3e3fa..73ebe70b 100644 --- a/app/pages/(features)/rehab/registration/add.vue +++ b/app/pages/(features)/rehab/registration/add.vue @@ -13,7 +13,7 @@ definePageMeta({ const route = useRoute() useHead({ - title: () => route.meta.title, + title: () => `${route.meta.title}`, // backtick to avoid the ts-plugin(2322) warning }) const roleAccess: PagePermission = PAGE_PERMISSIONS['/rehab/registration'] From ce785f20929459d2dba9231cc6a2a22cad31e932 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Sat, 4 Oct 2025 06:55:12 +0700 Subject: [PATCH 3/7] dev: hotfix + data table + genCrudHandler + crud-base --- .../pub/base/data-table/data-table.vue | 14 +-- app/handlers/_handler.ts | 104 ++++++++++++++++++ app/services/_crud-base.ts | 77 +++++++++++++ 3 files changed, 188 insertions(+), 7 deletions(-) create mode 100644 app/services/_crud-base.ts diff --git a/app/components/pub/base/data-table/data-table.vue b/app/components/pub/base/data-table/data-table.vue index 1127b4e4..9acd021b 100644 --- a/app/components/pub/base/data-table/data-table.vue +++ b/app/components/pub/base/data-table/data-table.vue @@ -10,9 +10,9 @@ const props = defineProps<{ cols: Col[] header: Th[][] keys: string[] - funcParsed: RecStrFuncUnknown - funcHtml: RecStrFuncUnknown - funcComponent: RecStrFuncComponent + funcParsed?: RecStrFuncUnknown + funcHtml?: RecStrFuncUnknown + funcComponent?: RecStrFuncComponent selectMode?: 'single' | 'multiple' modelValue?: any[] | any }>() @@ -118,16 +118,16 @@ function handleActionCellClick(event: Event, _cellRef: string) { diff --git a/app/handlers/_handler.ts b/app/handlers/_handler.ts index 4148c726..bcb1f808 100644 --- a/app/handlers/_handler.ts +++ b/app/handlers/_handler.ts @@ -104,6 +104,110 @@ export function createCrudHandler(crud: { } } +// Factory for CRUD handler state and actions +export function genCrudHandler(crud: { + create: (...args: any[]) => Promise + update: (...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.create, + 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.update, + 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/services/_crud-base.ts b/app/services/_crud-base.ts new file mode 100644 index 00000000..f9d33744 --- /dev/null +++ b/app/services/_crud-base.ts @@ -0,0 +1,77 @@ +import { xfetch } from '~/composables/useXfetch' + +export async function create(path: string, data: any) { + try { + const resp = await xfetch(path, 'POST', data) + 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 getList(path: string, params: any = null) { + try { + let url = path + 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(path, '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 getDetail(path: string, id: number | string) { + try { + const resp = await xfetch(`${path}/${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 update(path: string, id: number | string, data: any) { + try { + const resp = await xfetch(`${path}/${id}`, 'PATCH', data) + 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 remove(path: string, id: number | string) { + try { + const resp = await xfetch(`${path}/${id}`, 'DELETE') + const result: any = {} + result.success = resp.success + result.body = (resp.body as Record) || {} + return result + } catch (error) { + console.error('Error deleting data:', error) + throw new Error('Failed to delete division') + } +} From 72627b8a37e11f3c8d4cef1565fd4748843120ff Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Sun, 5 Oct 2025 03:32:48 +0700 Subject: [PATCH 4/7] dev: hotfix + dropped quick-info patient + added quick-info encounter + text-area styling --- app/components/app/encounter/quick-info.vue | 83 ++++++++++++++++++++ app/components/app/patient/quick-info.vue | 75 ------------------ app/components/content/encounter/process.vue | 2 +- app/components/pub/ui/textarea/Textarea.vue | 2 +- 4 files changed, 85 insertions(+), 77 deletions(-) create mode 100644 app/components/app/encounter/quick-info.vue delete mode 100644 app/components/app/patient/quick-info.vue diff --git a/app/components/app/encounter/quick-info.vue b/app/components/app/encounter/quick-info.vue new file mode 100644 index 00000000..95fe57d1 --- /dev/null +++ b/app/components/app/encounter/quick-info.vue @@ -0,0 +1,83 @@ + + + diff --git a/app/components/app/patient/quick-info.vue b/app/components/app/patient/quick-info.vue deleted file mode 100644 index 1f8943c2..00000000 --- a/app/components/app/patient/quick-info.vue +++ /dev/null @@ -1,75 +0,0 @@ - - - diff --git a/app/components/content/encounter/process.vue b/app/components/content/encounter/process.vue index cdadbd63..eb69f690 100644 --- a/app/components/content/encounter/process.vue +++ b/app/components/content/encounter/process.vue @@ -40,7 +40,7 @@ const data = { - + diff --git a/app/components/pub/ui/textarea/Textarea.vue b/app/components/pub/ui/textarea/Textarea.vue index a6b182a3..a946b49a 100644 --- a/app/components/pub/ui/textarea/Textarea.vue +++ b/app/components/pub/ui/textarea/Textarea.vue @@ -20,5 +20,5 @@ const modelValue = useVModel(props, 'modelValue', emits, {