From ccefb69f0c7c5e883be438910184e4cf11e820f2 Mon Sep 17 00:00:00 2001 From: Khafid Prayoga Date: Fri, 28 Nov 2025 10:36:30 +0700 Subject: [PATCH] adjustment on picker dialog procedure refactor(procedure-picker): improve component structure and add readonly support - Reorganize imports and add type imports section - Replace custom Button with ButtonAction component - Add readonly state handling for fields and buttons - Improve type safety with ProcedureSrc type casting feat(usePaginatedList): add syncToUrl option for nested components Add syncToUrl option to disable URL synchronization when used in modals or nested components to prevent overriding parent page URL. Default remains true for backward compatibility. Also includes minor formatting improvements in procedure-list.vue template. --- .../arrangement-procedure/procedure-list.vue | 33 +++++----- .../procedure-picker.vue | 63 +++++++++---------- .../app/treatment-report/preview.vue | 0 app/composables/usePaginatedList.ts | 36 ++++++++--- 4 files changed, 77 insertions(+), 55 deletions(-) create mode 100644 app/components/app/treatment-report/preview.vue diff --git a/app/components/app/therapy-protocol/picker-dialog/arrangement-procedure/procedure-list.vue b/app/components/app/therapy-protocol/picker-dialog/arrangement-procedure/procedure-list.vue index e4836c7c..fabb0463 100644 --- a/app/components/app/therapy-protocol/picker-dialog/arrangement-procedure/procedure-list.vue +++ b/app/components/app/therapy-protocol/picker-dialog/arrangement-procedure/procedure-list.vue @@ -45,6 +45,7 @@ const { handleSearch, fetchData: getItemList, } = usePaginatedList({ + syncToUrl: false, fetchFn: async (params: any) => { const result = await getList({ search: params.search, @@ -102,19 +103,23 @@ onMounted(async () => { diff --git a/app/components/app/therapy-protocol/picker-dialog/arrangement-procedure/procedure-picker.vue b/app/components/app/therapy-protocol/picker-dialog/arrangement-procedure/procedure-picker.vue index e6ba7f2b..ec2aad35 100644 --- a/app/components/app/therapy-protocol/picker-dialog/arrangement-procedure/procedure-picker.vue +++ b/app/components/app/therapy-protocol/picker-dialog/arrangement-procedure/procedure-picker.vue @@ -1,23 +1,24 @@ @@ -26,19 +27,15 @@ provide(`isProcedurePickerDialogOpen`, isProcedurePickerDialogOpen)

{{ title }}

- + />
- {{ field.value?.name }} - {{ field.value?.code }} + + {{ (field.value as ProcedureSrc)?.name }} + + + {{ (field.value as ProcedureSrc)?.code }} + - + /> diff --git a/app/components/app/treatment-report/preview.vue b/app/components/app/treatment-report/preview.vue new file mode 100644 index 00000000..e69de29b diff --git a/app/composables/usePaginatedList.ts b/app/composables/usePaginatedList.ts index 71dd99b3..ce5dbb40 100644 --- a/app/composables/usePaginatedList.ts +++ b/app/composables/usePaginatedList.ts @@ -2,7 +2,6 @@ import type { DataTableLoader } from '~/components/pub/my-ui/data-table/type' import type { PaginationMeta } from '~/components/pub/my-ui/pagination/pagination.type' import { refDebounced, useUrlSearchParams } from '@vueuse/core' import * as z from 'zod' -import { is } from "date-fns/locale" // Default query schema yang bisa digunakan semua list export const defaultQuerySchema = z.object({ @@ -38,10 +37,23 @@ interface UsePaginatedListOptions { }> // Nama endpoint untuk logging error entityName: string + /** + * Apakah state harus disinkronkan ke URL Browser? + * Set `false` jika digunakan di dalam Modal, Drawer, atau Nested Component + * agar tidak menimpa URL halaman induk. + * @default true + */ + syncToUrl?: boolean } export function usePaginatedList(options: UsePaginatedListOptions) { - const { querySchema = defaultQuerySchema, defaultQuery = defaultQueryParams, fetchFn, entityName } = options + const { + querySchema = defaultQuerySchema, + defaultQuery = defaultQueryParams, + fetchFn, + entityName, + syncToUrl = true, // Default true agar behavior lama tetap jalan + } = options // State management const data = ref([]) @@ -49,11 +61,19 @@ export function usePaginatedList(options: UsePaginatedListOptions) { isTableLoading: false, }) - // URL state management - const queryParams = useUrlSearchParams('history', { - initialValue: defaultQuery, - removeFalsyValues: true, - }) + let queryParams: any + + if (syncToUrl) { + // Mode Halaman Utama: Sync ke URL + queryParams = useUrlSearchParams('history', { + initialValue: defaultQuery, + removeFalsyValues: true, + write: false, + }) + } else { + // Mode Nested/Modal: Local Reactive State + queryParams = reactive({ ...defaultQuery }) + } const params = computed(() => { const result = querySchema.safeParse(queryParams) @@ -168,7 +188,7 @@ export function usePaginatedList(options: UsePaginatedListOptions) { } } -export function transform(endpoint: string ,params: any): string { +export function transform(endpoint: string, params: any): string { const urlParams = new URLSearchParams() Object.entries(params).forEach(([key, value]) => {