From 4f61832f19ce627e3230362babded102dcfeaef7 Mon Sep 17 00:00:00 2001 From: faiztyanirh Date: Fri, 13 Feb 2026 22:05:08 +0700 Subject: [PATCH] bug fix + add feature fix salah url ketika sidebar collapsed menambahkan type select pada reusable searchparam --- .../composable/use-search.svelte.js | 30 ++++++- .../location/config/location-config.js | 3 +- .../location/page/master-page.svelte | 5 +- src/lib/components/nav-dictionary.svelte | 8 +- .../reusable/reusable-search-param.svelte | 85 +++++++++++++++++-- 5 files changed, 117 insertions(+), 14 deletions(-) diff --git a/src/lib/components/composable/use-search.svelte.js b/src/lib/components/composable/use-search.svelte.js index 8b1b38f..5a402d9 100644 --- a/src/lib/components/composable/use-search.svelte.js +++ b/src/lib/components/composable/use-search.svelte.js @@ -2,6 +2,8 @@ export function useSearch(searchFields, searchApiFunction) { let searchQuery = $state(initializeSearchQuery(searchFields)); let isLoading = $state(false); let searchData = $state([]); + let selectOptions = $state({}); + let loadingOptions = $state({}); function initializeSearchQuery(fields) { const query = {}; @@ -30,12 +32,38 @@ export function useSearch(searchFields, searchApiFunction) { searchQuery = initializeSearchQuery(searchFields); } + async function fetchOptions(field) { + if (!field.optionsEndpoint) return; + + if (selectOptions[field.key]?.length) return; + + loadingOptions[field.key] = true; + + try { + const response = await fetch(field.optionsEndpoint); + const json = await response.json(); + + selectOptions[field.key] = json.data.map(item => ({ + value: item[field.valueKey ?? 'value'], + label: item[field.labelKey ?? 'label'], + })); + } catch (err) { + console.error("Failed fetching options:", err); + selectOptions[field.key] = []; + } finally { + loadingOptions[field.key] = false; + } + } + return { get searchQuery() { return searchQuery; }, set searchQuery(value) { searchQuery = value; }, get searchData() { return searchData; }, get isLoading() { return isLoading; }, + get loadingOptions() { return loadingOptions; }, + get selectOptions() { return selectOptions; }, handleSearch, - handleReset + handleReset, + fetchOptions, }; } \ No newline at end of file diff --git a/src/lib/components/dictionary/location/config/location-config.js b/src/lib/components/dictionary/location/config/location-config.js index e638d5e..20d0a4f 100644 --- a/src/lib/components/dictionary/location/config/location-config.js +++ b/src/lib/components/dictionary/location/config/location-config.js @@ -16,7 +16,8 @@ export const searchFields = [ { key: "LocType", label: "Location Type", - type: "text" + type: "select", + optionsEndpoint: `https://clqms01-api.services-summit.my.id/api/valueset/location_type`, }, ]; diff --git a/src/lib/components/dictionary/location/page/master-page.svelte b/src/lib/components/dictionary/location/page/master-page.svelte index 28f8927..16622d9 100644 --- a/src/lib/components/dictionary/location/page/master-page.svelte +++ b/src/lib/components/dictionary/location/page/master-page.svelte @@ -20,7 +20,10 @@ {#snippet searchParamSnippet()} - + {/snippet}
{:else} - openPopovers[index] = open}> + openPopovers[item.url] = open}> {#snippet trigger(props)} @@ -89,8 +89,8 @@
{#each item.submenus || [] as submenu} - openPopovers[index] = false} + openPopovers[item.url] = false} class="flex items-center rounded-md px-2 py-1.5 text-sm hover:bg-accent" class:bg-accent={$page.url.pathname === submenu.url} > @@ -99,7 +99,7 @@ {/each} {:else} openPopovers[index] = false} + onclick={() => openPopovers[item.url] = false} class="flex items-center rounded-md px-2 py-1.5 text-sm font-semibold hover:bg-accent" class:bg-accent={$page.url.pathname === item.url} > diff --git a/src/lib/components/reusable/reusable-search-param.svelte b/src/lib/components/reusable/reusable-search-param.svelte index 637ada3..4c72f54 100644 --- a/src/lib/components/reusable/reusable-search-param.svelte +++ b/src/lib/components/reusable/reusable-search-param.svelte @@ -7,10 +7,20 @@ import * as Select from "$lib/components/ui/select/index.js"; let props = $props(); + + let loadedFields = $state(new Set()); + + function handleOpenSelect(field) { + if (loadedFields.has(field.key)) return; + + loadedFields.add(field.key); + props.fetchOptions(field); + } + $inspect(props.searchQuery)
-
+
{#each props.searchFields as field} {#if field.type === "text"}
@@ -22,20 +32,81 @@
{:else if field.type === "select"} -
+
- - - + { + props.fetchOptions(field) + }} + > + + { + props.selectOptions[field.key]?.find( + opt => opt.value === props.searchQuery[field.key] + )?.label ?? "Choose" + } - - {#each field.options as opt} + + - None - + {#each props.selectOptions[field.key] as opt} {opt.label} {/each} + + + +
{/if} {/each}