From ea1369f69bc594260041bb925ce4e8c85041bf13 Mon Sep 17 00:00:00 2001 From: faiztyanirh Date: Tue, 14 Apr 2026 10:46:47 +0700 Subject: [PATCH] change all page (add indicator spinner rowclick, popover autoclose after search) --- .../account/config/account-config.js | 8 +- .../account/page/create-page.svelte | 10 +- .../account/page/master-page.svelte | 22 ++-- .../dictionary/account/page/view-page.svelte | 7 +- .../contact/page/master-page.svelte | 4 +- .../dictionary/contact/page/view-page.svelte | 7 +- .../container/config/container-config.js | 8 +- .../container/page/create-page.svelte | 10 +- .../container/page/master-page.svelte | 22 ++-- .../container/page/view-page.svelte | 7 +- .../department/config/department-config.js | 8 +- .../department/page/create-page.svelte | 10 +- .../department/page/master-page.svelte | 22 ++-- .../department/page/view-page.svelte | 7 +- .../discipline/config/discipline-config.js | 8 +- .../discipline/page/create-page.svelte | 10 +- .../discipline/page/master-page.svelte | 22 ++-- .../discipline/page/view-page.svelte | 7 +- .../location/page/master-page.svelte | 4 +- .../dictionary/location/page/view-page.svelte | 7 +- .../occupation/page/create-page.svelte | 10 +- .../dictionary/site/config/site-config.js | 8 +- .../dictionary/site/page/create-page.svelte | 10 +- .../dictionary/site/page/master-page.svelte | 22 ++-- .../dictionary/site/page/view-page.svelte | 7 +- .../dictionary/test/config/test-config.js | 8 +- .../dictionary/test/page/create-page.svelte | 10 +- .../dictionary/test/page/edit-page.svelte | 11 +- .../dictionary/test/page/master-page.svelte | 22 ++-- .../dictionary/test/page/view-page.svelte | 7 +- .../testmap/config/testmap-config.js | 8 +- .../testmap/page/create-page.svelte | 10 +- .../testmap/page/master-page.svelte | 12 +- .../testmap/page/view-page copy.svelte | 123 ------------------ .../dictionary/testmap/page/view-page.svelte | 7 +- .../workstation/config/workstation-config.js | 8 +- .../workstation/page/create-page.svelte | 10 +- .../workstation/page/master-page.svelte | 22 ++-- .../workstation/page/view-page.svelte | 7 +- .../patient/list/page/master-page.svelte | 4 +- .../patient/list/page/view-page.svelte | 7 +- .../components/topbar/topbar-action.svelte | 1 - 42 files changed, 314 insertions(+), 230 deletions(-) delete mode 100644 src/lib/components/dictionary/testmap/page/view-page copy.svelte diff --git a/src/lib/components/dictionary/account/config/account-config.js b/src/lib/components/dictionary/account/config/account-config.js index de85664..c7942e1 100644 --- a/src/lib/components/dictionary/account/config/account-config.js +++ b/src/lib/components/dictionary/account/config/account-config.js @@ -2,6 +2,7 @@ import PlusIcon from "@lucide/svelte/icons/plus"; import Settings2Icon from "@lucide/svelte/icons/settings-2"; import PencilIcon from "@lucide/svelte/icons/pencil"; import { API } from "$lib/config/api"; +import RefreshIcon from "@lucide/svelte/icons/refresh-cw"; export const searchFields = [ { @@ -72,8 +73,13 @@ export const detailSections = [ }, ]; -export function accountActions(masterDetail) { +export function accountActions(masterDetail, handlers) { return [ + { + Icon: RefreshIcon, + label: 'Refresh Data', + onClick: handlers.refresh, + }, { Icon: PlusIcon, label: 'Add Account', diff --git a/src/lib/components/dictionary/account/page/create-page.svelte b/src/lib/components/dictionary/account/page/create-page.svelte index 1ec3666..dc61d98 100644 --- a/src/lib/components/dictionary/account/page/create-page.svelte +++ b/src/lib/components/dictionary/account/page/create-page.svelte @@ -26,8 +26,14 @@ async function handleSave() { const result = await formState.save(masterDetail.mode); - toast('Account Created!'); - masterDetail?.exitForm(true); + if (result.status === 'success') { + toast('Account Created!'); + masterDetail?.exitForm(true); + } else { + console.error('Failed to save account'); + const errorMessages = result.messages ? Object.values(result.messages).join('\n') : 'Failed to save account'; + toast.error(errorMessages) + } } const primaryAction = $derived({ diff --git a/src/lib/components/dictionary/account/page/master-page.svelte b/src/lib/components/dictionary/account/page/master-page.svelte index ad12e27..c6972e3 100644 --- a/src/lib/components/dictionary/account/page/master-page.svelte +++ b/src/lib/components/dictionary/account/page/master-page.svelte @@ -8,20 +8,23 @@ import ReusableEmpty from "$lib/components/reusable/reusable-empty.svelte"; import ReusableDataTable from "$lib/components/reusable/reusable-data-table.svelte"; import UserRoundXIcon from "@lucide/svelte/icons/user-round-x"; + import MoveLeftIcon from "@lucide/svelte/icons/move-left"; let props = $props(); const search = useSearch(searchFields, getAccounts); - const initialForm = props.masterDetail.formState.form; - const actions = accountActions(props.masterDetail, initialForm) + const handlers = { + refresh: () => {search.handleSearch()}, + }; + const actions = accountActions(props.masterDetail, handlers) actions.find(a => a.label === 'Search Parameters').popoverContent = searchParamSnippet; let activeRowId = $state(null); -{#snippet searchParamSnippet()} +{#snippet searchParamSnippet(close)} search.handleSearch(close)} onReset={search.handleReset} isLoading={search.isLoading} selectOptions={search.selectOptions} loadingOptions={search.loadingOptions} fetchOptions={search.fetchOptions} /> {/snippet} @@ -38,10 +41,13 @@ >
{#if props.masterDetail.isFormMode} - - {#each "ACCOUNT".split("") as c} - {c} - {/each} + + +
+ {#each "ACCOUNT".split("") as c} + {c} + {/each} +
{/if} diff --git a/src/lib/components/dictionary/account/page/view-page.svelte b/src/lib/components/dictionary/account/page/view-page.svelte index 42435df..16e6b44 100644 --- a/src/lib/components/dictionary/account/page/view-page.svelte +++ b/src/lib/components/dictionary/account/page/view-page.svelte @@ -4,6 +4,7 @@ import TopbarWrapper from "$lib/components/topbar/topbar-wrapper.svelte"; import ReusableEmpty from "$lib/components/reusable/reusable-empty.svelte"; import UserRoundXIcon from "@lucide/svelte/icons/user-round-x"; + import { Spinner } from "$lib/components/ui/spinner/index.js"; let props = $props(); @@ -46,7 +47,11 @@
{/snippet} -{#if masterDetail.selectedItem} +{#if masterDetail.isLoadingDetail} +
+ +
+{:else if masterDetail.selectedItem}
-{#snippet searchParamSnippet()} +{#snippet searchParamSnippet(close)} search.handleSearch(close)} onReset={search.handleReset} isLoading={search.isLoading} selectOptions={search.selectOptions} loadingOptions={search.loadingOptions} fetchOptions={search.fetchOptions} /> {/snippet} diff --git a/src/lib/components/dictionary/contact/page/view-page.svelte b/src/lib/components/dictionary/contact/page/view-page.svelte index 188f10d..0ae7b3a 100644 --- a/src/lib/components/dictionary/contact/page/view-page.svelte +++ b/src/lib/components/dictionary/contact/page/view-page.svelte @@ -9,6 +9,7 @@ import * as Card from "$lib/components/ui/card/index.js"; import { Badge } from "$lib/components/ui/badge/index.js"; import * as Table from "$lib/components/ui/table/index.js"; + import { Spinner } from "$lib/components/ui/spinner/index.js"; let props = $props(); @@ -97,7 +98,11 @@
{/snippet} -{#if masterDetail.selectedItem} +{#if masterDetail.isLoadingDetail} +
+ +
+{:else if masterDetail.selectedItem}
{search.handleSearch()}, + }; + const actions = containerActions(props.masterDetail, handlers) actions.find(a => a.label === 'Search Parameters').popoverContent = searchParamSnippet; let activeRowId = $state(null); -{#snippet searchParamSnippet()} +{#snippet searchParamSnippet(close)} search.handleSearch(close)} onReset={search.handleReset} isLoading={search.isLoading} selectOptions={search.selectOptions} loadingOptions={search.loadingOptions} fetchOptions={search.fetchOptions} /> {/snippet} @@ -38,10 +41,13 @@ >
{#if props.masterDetail.isFormMode} - - {#each "CONTAINER".split("") as c} - {c} - {/each} + + +
+ {#each "CONTAINER".split("") as c} + {c} + {/each} +
{/if} diff --git a/src/lib/components/dictionary/container/page/view-page.svelte b/src/lib/components/dictionary/container/page/view-page.svelte index 7b9985b..1bf7fa0 100644 --- a/src/lib/components/dictionary/container/page/view-page.svelte +++ b/src/lib/components/dictionary/container/page/view-page.svelte @@ -4,6 +4,7 @@ import TopbarWrapper from "$lib/components/topbar/topbar-wrapper.svelte"; import ReusableEmpty from "$lib/components/reusable/reusable-empty.svelte"; import ArchiveXIcon from "@lucide/svelte/icons/archive-x"; + import { Spinner } from "$lib/components/ui/spinner/index.js"; let props = $props(); @@ -46,7 +47,11 @@
{/snippet} -{#if masterDetail.selectedItem} +{#if masterDetail.isLoadingDetail} +
+ +
+{:else if masterDetail.selectedItem}
{search.handleSearch()}, + }; + const actions = departmentActions(props.masterDetail, handlers) actions.find(a => a.label === 'Search Parameters').popoverContent = searchParamSnippet; let activeRowId = $state(null); -{#snippet searchParamSnippet()} +{#snippet searchParamSnippet(close)} search.handleSearch(close)} onReset={search.handleReset} isLoading={search.isLoading} selectOptions={search.selectOptions} loadingOptions={search.loadingOptions} fetchOptions={search.fetchOptions} /> {/snippet} @@ -38,10 +41,13 @@ >
{#if props.masterDetail.isFormMode} - - {#each "DEPARTMENT".split("") as c} - {c} - {/each} + + +
+ {#each "DEPARTMENT".split("") as c} + {c} + {/each} +
{/if} diff --git a/src/lib/components/dictionary/department/page/view-page.svelte b/src/lib/components/dictionary/department/page/view-page.svelte index d849226..090483e 100644 --- a/src/lib/components/dictionary/department/page/view-page.svelte +++ b/src/lib/components/dictionary/department/page/view-page.svelte @@ -4,6 +4,7 @@ import TopbarWrapper from "$lib/components/topbar/topbar-wrapper.svelte"; import ReusableEmpty from "$lib/components/reusable/reusable-empty.svelte"; import FileXIcon from "@lucide/svelte/icons/file-x"; + import { Spinner } from "$lib/components/ui/spinner/index.js"; let props = $props(); @@ -46,7 +47,11 @@
{/snippet} -{#if masterDetail.selectedItem} +{#if masterDetail.isLoadingDetail} +
+ +
+{:else if masterDetail.selectedItem}
{search.handleSearch()}, + }; + const actions = disciplineActions(props.masterDetail, handlers) actions.find(a => a.label === 'Search Parameters').popoverContent = searchParamSnippet; let activeRowId = $state(null); -{#snippet searchParamSnippet()} +{#snippet searchParamSnippet(close)} search.handleSearch(close)} onReset={search.handleReset} isLoading={search.isLoading} selectOptions={search.selectOptions} loadingOptions={search.loadingOptions} fetchOptions={search.fetchOptions} /> {/snippet} @@ -38,10 +41,13 @@ >
{#if props.masterDetail.isFormMode} - - {#each "DISCIPLINE".split("") as c} - {c} - {/each} + + +
+ {#each "DISCIPLINE".split("") as c} + {c} + {/each} +
{/if} diff --git a/src/lib/components/dictionary/discipline/page/view-page.svelte b/src/lib/components/dictionary/discipline/page/view-page.svelte index fd53235..c1ecaef 100644 --- a/src/lib/components/dictionary/discipline/page/view-page.svelte +++ b/src/lib/components/dictionary/discipline/page/view-page.svelte @@ -4,6 +4,7 @@ import TopbarWrapper from "$lib/components/topbar/topbar-wrapper.svelte"; import ReusableEmpty from "$lib/components/reusable/reusable-empty.svelte"; import BookXIcon from "@lucide/svelte/icons/book-x"; + import { Spinner } from "$lib/components/ui/spinner/index.js"; let props = $props(); @@ -46,7 +47,11 @@
{/snippet} -{#if masterDetail.selectedItem} +{#if masterDetail.isLoadingDetail} +
+ +
+{:else if masterDetail.selectedItem}
-{#snippet searchParamSnippet()} +{#snippet searchParamSnippet(close)} search.handleSearch(close)} onReset={search.handleReset} isLoading={search.isLoading} selectOptions={search.selectOptions} loadingOptions={search.loadingOptions} fetchOptions={search.fetchOptions} /> {/snippet} diff --git a/src/lib/components/dictionary/location/page/view-page.svelte b/src/lib/components/dictionary/location/page/view-page.svelte index 2bc89a6..6ee7958 100644 --- a/src/lib/components/dictionary/location/page/view-page.svelte +++ b/src/lib/components/dictionary/location/page/view-page.svelte @@ -4,6 +4,7 @@ import TopbarWrapper from "$lib/components/topbar/topbar-wrapper.svelte"; import ReusableEmpty from "$lib/components/reusable/reusable-empty.svelte"; import MapPinXIcon from "@lucide/svelte/icons/map-pin-x"; + import { Spinner } from "$lib/components/ui/spinner/index.js"; let props = $props(); @@ -46,7 +47,11 @@
{/snippet} -{#if masterDetail.selectedItem} +{#if masterDetail.isLoadingDetail} +
+ +
+{:else if masterDetail.selectedItem}
{search.handleSearch()}, + }; + const actions = siteActions(props.masterDetail, handlers) actions.find(a => a.label === 'Search Parameters').popoverContent = searchParamSnippet; let activeRowId = $state(null); -{#snippet searchParamSnippet()} +{#snippet searchParamSnippet(close)} search.handleSearch(close)} onReset={search.handleReset} isLoading={search.isLoading} selectOptions={search.selectOptions} loadingOptions={search.loadingOptions} fetchOptions={search.fetchOptions} /> {/snippet} @@ -38,10 +41,13 @@ >
{#if props.masterDetail.isFormMode} - - {#each "SITE".split("") as c} - {c} - {/each} + + +
+ {#each "SITE".split("") as c} + {c} + {/each} +
{/if} diff --git a/src/lib/components/dictionary/site/page/view-page.svelte b/src/lib/components/dictionary/site/page/view-page.svelte index d7dbe7e..e100b70 100644 --- a/src/lib/components/dictionary/site/page/view-page.svelte +++ b/src/lib/components/dictionary/site/page/view-page.svelte @@ -4,6 +4,7 @@ import TopbarWrapper from "$lib/components/topbar/topbar-wrapper.svelte"; import ReusableEmpty from "$lib/components/reusable/reusable-empty.svelte"; import ClipboardXIcon from "@lucide/svelte/icons/clipboard-x"; + import { Spinner } from "$lib/components/ui/spinner/index.js"; let props = $props(); @@ -46,7 +47,11 @@
{/snippet} -{#if masterDetail.selectedItem} +{#if masterDetail.isLoadingDetail} +
+ +
+{:else if masterDetail.selectedItem}
{search.handleSearch()}, + }; + const actions = testActions(props.masterDetail, handlers) actions.find(a => a.label === 'Search Parameters').popoverContent = searchParamSnippet; let activeRowId = $state(null); -{#snippet searchParamSnippet()} +{#snippet searchParamSnippet(close)} search.handleSearch(close)} onReset={search.handleReset} isLoading={search.isLoading} selectOptions={search.selectOptions} loadingOptions={search.loadingOptions} fetchOptions={search.fetchOptions} /> {/snippet} @@ -38,10 +41,13 @@ >
{#if props.masterDetail.isFormMode} - - {#each "TEST".split("") as c} - {c} - {/each} + + +
+ {#each "TEST".split("") as c} + {c} + {/each} +
{/if} diff --git a/src/lib/components/dictionary/test/page/view-page.svelte b/src/lib/components/dictionary/test/page/view-page.svelte index 32d1140..28915a1 100644 --- a/src/lib/components/dictionary/test/page/view-page.svelte +++ b/src/lib/components/dictionary/test/page/view-page.svelte @@ -4,6 +4,7 @@ import TopbarWrapper from "$lib/components/topbar/topbar-wrapper.svelte"; import ReusableEmpty from "$lib/components/reusable/reusable-empty.svelte"; import FlaskConicalOffIcon from "@lucide/svelte/icons/flask-conical-off"; + import { Spinner } from "$lib/components/ui/spinner/index.js"; let props = $props(); @@ -46,7 +47,11 @@
{/snippet} -{#if masterDetail.selectedItem} +{#if masterDetail.isLoadingDetail} +
+ +
+{:else if masterDetail.selectedItem}
{search.handleSearch()}, + }; + const actions = testMapActions(props.masterDetail, handlers) actions.find(a => a.label === 'Search Parameters').popoverContent = searchParamSnippet; let activeRowId = $state(null); -{#snippet searchParamSnippet()} +{#snippet searchParamSnippet(close)} search.handleSearch(close)} onReset={search.handleReset} isLoading={search.isLoading} selectOptions={search.selectOptions} loadingOptions={search.loadingOptions} fetchOptions={search.fetchOptions} /> {/snippet} @@ -42,7 +44,7 @@
- {#each "BACK TO TEST MAP".split("") as c} + {#each "TEST MAP".split("") as c} {c} {/each}
diff --git a/src/lib/components/dictionary/testmap/page/view-page copy.svelte b/src/lib/components/dictionary/testmap/page/view-page copy.svelte deleted file mode 100644 index c074b07..0000000 --- a/src/lib/components/dictionary/testmap/page/view-page copy.svelte +++ /dev/null @@ -1,123 +0,0 @@ - - -{#snippet DetailsTable({ value, label })} -
-
- {label} -
-
- {#if value && Array.isArray(value) && value.length > 0} - - - - - - - - - - - {#each value as row, i} - - - - - - - {/each} - -
Host Test CodeHost Test NameClient Test CodeClient Test Name
{row.HostTestCode ?? '-'}{row.HostTestName ?? '-'}{row.ClientTestCode ?? '-'}{row.ClientTestName ?? '-'}
- {:else} - - - {/if} -
-
-{/snippet} - -{#snippet Fieldset({ value, label, isUTCDate = false })} -
-
- {label} -
-
- {#if isUTCDate} - {formatUTCDate(value)} - {:else} - {value ?? "-"} - {/if} -
-
-{/snippet} - -{#if masterDetail.selectedItem} -
- -
- {#each detailSections as section} -
-
- {#each section.fields as field} - {#if field.fullWidth} -
- {#if field.key === "details"} - {@render DetailsTable({ label: field.label, value: getFieldValue(field) })} - {:else} - {@render Fieldset({ label: field.label, value: getFieldValue(field), isUTCDate: field.isUTCDate })} - {/if} -
- {:else if field.key === "details"} - {@render DetailsTable({ - label: field.label, - value: getFieldValue(field), - })} - {:else} - {@render Fieldset({ - label: field.label, - value: getFieldValue(field), - isUTCDate: field.isUTCDate - })} - {/if} - {/each} -
-
- {/each} -
-
-{:else} - -{/if} \ No newline at end of file diff --git a/src/lib/components/dictionary/testmap/page/view-page.svelte b/src/lib/components/dictionary/testmap/page/view-page.svelte index 68560d9..6e9cd1b 100644 --- a/src/lib/components/dictionary/testmap/page/view-page.svelte +++ b/src/lib/components/dictionary/testmap/page/view-page.svelte @@ -5,6 +5,7 @@ import ReusableEmpty from "$lib/components/reusable/reusable-empty.svelte"; import MapIcon from "@lucide/svelte/icons/map"; import * as Table from "$lib/components/ui/table/index.js"; + import { Spinner } from "$lib/components/ui/spinner/index.js"; let props = $props(); @@ -85,7 +86,11 @@
{/snippet} -{#if masterDetail.selectedItem} +{#if masterDetail.isLoadingDetail} +
+ +
+{:else if masterDetail.selectedItem}
{search.handleSearch()}, + }; + const actions = workstationActions(props.masterDetail, handlers) actions.find(a => a.label === 'Search Parameters').popoverContent = searchParamSnippet; let activeRowId = $state(null); -{#snippet searchParamSnippet()} +{#snippet searchParamSnippet(close)} search.handleSearch(close)} onReset={search.handleReset} isLoading={search.isLoading} selectOptions={search.selectOptions} loadingOptions={search.loadingOptions} fetchOptions={search.fetchOptions} /> {/snippet} @@ -38,10 +41,13 @@ >
{#if props.masterDetail.isFormMode} - - {#each "WORKSTATION".split("") as c} - {c} - {/each} + + +
+ {#each "WORKSTATION".split("") as c} + {c} + {/each} +
{/if} diff --git a/src/lib/components/dictionary/workstation/page/view-page.svelte b/src/lib/components/dictionary/workstation/page/view-page.svelte index 9399af3..0eaf8b1 100644 --- a/src/lib/components/dictionary/workstation/page/view-page.svelte +++ b/src/lib/components/dictionary/workstation/page/view-page.svelte @@ -4,6 +4,7 @@ import TopbarWrapper from "$lib/components/topbar/topbar-wrapper.svelte"; import ReusableEmpty from "$lib/components/reusable/reusable-empty.svelte"; import MonitorXIcon from "@lucide/svelte/icons/monitor-x"; + import { Spinner } from "$lib/components/ui/spinner/index.js"; let props = $props(); @@ -46,7 +47,11 @@
{/snippet} -{#if masterDetail.selectedItem} +{#if masterDetail.isLoadingDetail} +
+ +
+{:else if masterDetail.selectedItem}
-{#snippet searchParamSnippet()} - +{#snippet searchParamSnippet(close)} + search.handleSearch(close)} onReset={search.handleReset} isLoading={search.isLoading}/> {/snippet}
{/snippet} -{#if masterDetail.selectedItem} +{#if masterDetail.isLoadingDetail} +
+ +
+{:else if masterDetail.selectedItem}
diff --git a/src/lib/components/topbar/topbar-action.svelte b/src/lib/components/topbar/topbar-action.svelte index a2a4b87..b4c309c 100644 --- a/src/lib/components/topbar/topbar-action.svelte +++ b/src/lib/components/topbar/topbar-action.svelte @@ -30,7 +30,6 @@ {/snippet} - {@render props.popoverContent(() => open = false)}