mirror of
https://github.com/faiztyanirh/clqms-shadcn-v1.git
synced 2026-04-22 09:35:34 +07:00
16022025
fix ubah url parameter dari parent jadi ProvinceID fix tampilan input bisa fullWidth atau tidak dari form config
This commit is contained in:
parent
8f9e9ddffd
commit
671a360c4c
@ -29,6 +29,7 @@ const optionsMode = {
|
||||
|
||||
cascade: async (field, selectOptions, loadingOptions, form, lastFetched) => {
|
||||
const parentValue = field.dependsOn ? form?.[field.dependsOn] : null;
|
||||
// console.log(parentValue);
|
||||
|
||||
// If has dependency and parent changed, or not fetched yet
|
||||
if (field.dependsOn) {
|
||||
|
||||
18
src/lib/components/dictionary/account/api/account-api.js
Normal file
18
src/lib/components/dictionary/account/api/account-api.js
Normal file
@ -0,0 +1,18 @@
|
||||
import { API } from '$lib/config/api.js';
|
||||
import { getById, searchWithParams, create, update } from '$lib/api/api-client';
|
||||
|
||||
export async function getAccounts(searchQuery) {
|
||||
return await searchWithParams(API.ACCOUNT, searchQuery)
|
||||
}
|
||||
|
||||
export async function getAccount(searchQuery) {
|
||||
return await getById(API.ACCOUNT, searchQuery)
|
||||
}
|
||||
|
||||
export async function createAccount(newAccountForm) {
|
||||
return await create(API.ACCOUNT, newAccountForm)
|
||||
}
|
||||
|
||||
export async function editAccount(editAccountForm) {
|
||||
return await update(API.ACCOUNT, editAccountForm)
|
||||
}
|
||||
@ -38,7 +38,13 @@ export const containerFormFields = [
|
||||
optionsEndpoint: `${API.BASE_URL}${API.SITE}`,
|
||||
valueKey: "SiteID",
|
||||
labelKey: (item) => `${item.SiteCode} - ${item.SiteName}`,
|
||||
fullWidth: false,
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "row",
|
||||
columns: [
|
||||
{
|
||||
key: "ConCode",
|
||||
label: "Container Code",
|
||||
@ -46,18 +52,18 @@ export const containerFormFields = [
|
||||
type: "text",
|
||||
validateOn: ["input"]
|
||||
},
|
||||
{
|
||||
key: "ConName",
|
||||
label: "Container Name",
|
||||
required: true,
|
||||
type: "text",
|
||||
validateOn: ["input"]
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "row",
|
||||
columns: [
|
||||
{
|
||||
key: "ConName",
|
||||
label: "Container Name",
|
||||
required: true,
|
||||
type: "text",
|
||||
validateOn: ["input"]
|
||||
},
|
||||
{
|
||||
key: "ConDesc",
|
||||
label: "Description",
|
||||
@ -99,6 +105,7 @@ export const containerFormFields = [
|
||||
required: false,
|
||||
type: "select",
|
||||
optionsEndpoint: `${API.BASE_URL}${API.VALUESET}/additive`,
|
||||
fullWidth: false
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@ -112,7 +112,7 @@ export const locationFormFields = [
|
||||
type: "select",
|
||||
optionsEndpoint: `${API.BASE_URL}${API.CITY}`,
|
||||
dependsOn: "Province",
|
||||
endpointParamKey: "Parent"
|
||||
endpointParamKey: "ProvinceID"
|
||||
},
|
||||
{
|
||||
key: "Street2",
|
||||
@ -130,7 +130,8 @@ export const locationFormFields = [
|
||||
label: "ZIP",
|
||||
required: false,
|
||||
type: "text",
|
||||
validateOn: ["input"]
|
||||
validateOn: ["input"],
|
||||
fullWidth: false
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
@ -44,10 +44,10 @@ export const patientInitialForm = {
|
||||
Citizenship: "",
|
||||
Street_1: "",
|
||||
City: "",
|
||||
CityID: "",
|
||||
// CityID: "",
|
||||
Street_2: "",
|
||||
Province: "",
|
||||
ProvinceID: "",
|
||||
// ProvinceID: "",
|
||||
Street_3: "",
|
||||
ZIP: "",
|
||||
Country: "",
|
||||
@ -205,7 +205,7 @@ export const patientFormFields = [
|
||||
columns: [
|
||||
{ key: "Street_1", label: "Street 1", required: false, type: "text" },
|
||||
{
|
||||
key: "ProvinceID",
|
||||
key: "Province",
|
||||
label: "Province",
|
||||
required: false,
|
||||
type: "select",
|
||||
@ -218,13 +218,13 @@ export const patientFormFields = [
|
||||
columns: [
|
||||
{ key: "Street_2", label: "Street 2", required: false, type: "text" },
|
||||
{
|
||||
key: "CityID",
|
||||
key: "City",
|
||||
label: "City",
|
||||
required: false,
|
||||
type: "select",
|
||||
optionsEndpoint: `${API.BASE_URL}${API.CITY}`,
|
||||
dependsOn: "ProvinceID",
|
||||
endpointParamKey: "Parent"
|
||||
dependsOn: "Province",
|
||||
endpointParamKey: "ProvinceID"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@ -63,6 +63,7 @@
|
||||
disabled: formState.isSaving.current
|
||||
}
|
||||
];
|
||||
// $inspect(formState.selectOptions)
|
||||
</script>
|
||||
|
||||
<FormPageContainer title="Create Patient" {primaryAction} {secondaryActions} {actions}>
|
||||
|
||||
@ -84,8 +84,8 @@
|
||||
{
|
||||
key: "City",
|
||||
optionsEndpoint: `${API.BASE_URL}${API.CITY}`,
|
||||
dependsOn: "ProvinceID",
|
||||
endpointParamKey: "Parent"
|
||||
dependsOn: "Province",
|
||||
endpointParamKey: "ProvinceID"
|
||||
},
|
||||
formState.form
|
||||
);
|
||||
|
||||
@ -204,19 +204,31 @@
|
||||
{/if}
|
||||
|
||||
{#each group.rows as row}
|
||||
<div
|
||||
<!-- <div
|
||||
class="grid grid-cols-1 space-y-2 gap-6 md:gap-4"
|
||||
class:md:grid-cols-1={row.columns.length === 1}
|
||||
class:md:grid-cols-2={row.columns.length === 2}
|
||||
class:md:grid-cols-3={row.columns.length === 3}
|
||||
> -->
|
||||
<div
|
||||
class="grid grid-cols-1 space-y-2 gap-6 md:gap-4"
|
||||
class:md:grid-cols-1={row.columns.length === 1 && row.columns[0].fullWidth !== false}
|
||||
class:md:grid-cols-2={row.columns.length === 2 || (row.columns.length === 1 && row.columns[0].fullWidth === false)}
|
||||
class:md:grid-cols-3={row.columns.length === 3}
|
||||
>
|
||||
{#each row.columns as col}
|
||||
{#if col.type === "group"}
|
||||
<div
|
||||
<!-- <div
|
||||
class="grid grid-cols-1 gap-6 md:gap-2"
|
||||
class:md:grid-cols-1={col.columns.length === 1}
|
||||
class:md:grid-cols-2={col.columns.length === 2}
|
||||
class:md:grid-cols-3={col.columns.length === 3}
|
||||
> -->
|
||||
<div
|
||||
class="grid grid-cols-1 gap-6 md:gap-2"
|
||||
class:md:grid-cols-1={col.columns.length === 1 && col.columns[0].fullWidth !== false}
|
||||
class:md:grid-cols-2={col.columns.length === 2 || (col.columns.length === 1 && col.columns[0].fullWidth === false)}
|
||||
class:md:grid-cols-3={col.columns.length === 3}
|
||||
>
|
||||
{#each col.columns as child}
|
||||
{@render Fieldset(child)}
|
||||
|
||||
210
src/lib/components/reusable/reusable-data-table copy.svelte
Normal file
210
src/lib/components/reusable/reusable-data-table copy.svelte
Normal file
@ -0,0 +1,210 @@
|
||||
<script>
|
||||
import { getCoreRowModel, getPaginationRowModel, getFilteredRowModel } from "@tanstack/table-core";
|
||||
import {
|
||||
createSvelteTable,
|
||||
FlexRender,
|
||||
} from "$lib/components/ui/data-table/index.js";
|
||||
import * as Table from "$lib/components/ui/table/index.js";
|
||||
import { Button } from "$lib/components/ui/button/index.js";
|
||||
import * as Select from "$lib/components/ui/select/index.js";
|
||||
import ChevronRightIcon from "@lucide/svelte/icons/chevron-right";
|
||||
import ChevronLeftIcon from "@lucide/svelte/icons/chevron-left";
|
||||
import ChevronsRightIcon from "@lucide/svelte/icons/chevrons-right";
|
||||
import ChevronsLeftIcon from "@lucide/svelte/icons/chevrons-left";
|
||||
import { Input } from "$lib/components/ui/input/index.js";
|
||||
|
||||
let props = $props();
|
||||
|
||||
let pagination = $state({ pageIndex: 0, pageSize: 10 });
|
||||
let columnFilters = $state([]);
|
||||
let globalFilter = $state("");
|
||||
let activeRowId = $state(null);
|
||||
|
||||
let table = createSvelteTable({
|
||||
get data() {
|
||||
return props.data;
|
||||
},
|
||||
get columns() {
|
||||
return props.columns;
|
||||
},
|
||||
state: {
|
||||
get pagination() {
|
||||
return pagination;
|
||||
},
|
||||
get columnFilters() {
|
||||
return columnFilters;
|
||||
},
|
||||
get globalFilter() {
|
||||
return globalFilter;
|
||||
},
|
||||
},
|
||||
onPaginationChange: (updater) => {
|
||||
if (typeof updater === "function") {
|
||||
pagination = updater(pagination);
|
||||
} else {
|
||||
pagination = updater;
|
||||
}
|
||||
},
|
||||
onColumnFiltersChange: (updater) => {
|
||||
if (typeof updater === "function") {
|
||||
columnFilters = updater(columnFilters);
|
||||
} else {
|
||||
columnFilters = updater;
|
||||
}
|
||||
},
|
||||
onGlobalFilterChange: (value) => {
|
||||
globalFilter = value;
|
||||
},
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- ✅ Updated with scrollable body -->
|
||||
<div class="h-full flex flex-col relative w-full">
|
||||
{#if props.searchable ?? true}
|
||||
<div class="flex items-center absolute top-[-2rem]">
|
||||
<Input
|
||||
placeholder="Filter all columns..."
|
||||
value={globalFilter}
|
||||
oninput={(e) => {
|
||||
globalFilter = e.currentTarget.value;
|
||||
}}
|
||||
class="h-7 w-64 text-xs px-2"
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- ✅ Container with flex column -->
|
||||
<div class="rounded-md border h-full flex flex-col w-full overflow-hidden">
|
||||
|
||||
<!-- ✅ Wrapper untuk table dengan overflow -->
|
||||
<div class="flex-1 overflow-auto">
|
||||
<Table.Root>
|
||||
<!-- ✅ Sticky Header -->
|
||||
<Table.Header class="sticky top-0 bg-background z-10">
|
||||
{#each table.getHeaderGroups() as headerGroup (headerGroup.id)}
|
||||
<Table.Row>
|
||||
{#each headerGroup.headers as header (header.id)}
|
||||
<Table.Head colspan={header.colSpan}>
|
||||
{#if !header.isPlaceholder}
|
||||
<FlexRender
|
||||
content={header.column.columnDef.header}
|
||||
context={header.getContext()}
|
||||
/>
|
||||
{/if}
|
||||
</Table.Head>
|
||||
{/each}
|
||||
</Table.Row>
|
||||
{/each}
|
||||
</Table.Header>
|
||||
|
||||
<!-- ✅ Scrollable Body -->
|
||||
<Table.Body>
|
||||
{#each table.getRowModel().rows as row (row.id)}
|
||||
<Table.Row
|
||||
data-state={row.getIsSelected() && "selected"}
|
||||
onclick={() => props.handleRowClick(row.original)}
|
||||
class="cursor-pointer"
|
||||
>
|
||||
{#each row.getVisibleCells() as cell, i (cell.id)}
|
||||
<Table.Cell class={`${i === 0 ? "border-l-4" : ""} ${i === 0 && activeRowId == row.original[props.rowIdKey] ? "border-primary" : "border-transparent"}`}>
|
||||
<FlexRender
|
||||
content={cell.column.columnDef.cell}
|
||||
context={cell.getContext()}
|
||||
/>
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
</Table.Row>
|
||||
{:else}
|
||||
<Table.Row>
|
||||
<Table.Cell colspan={props.columns.length} class="h-24 text-center">
|
||||
No results.
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
{/each}
|
||||
</Table.Body>
|
||||
</Table.Root>
|
||||
</div>
|
||||
|
||||
<!-- ✅ Sticky Pagination Footer -->
|
||||
<div class="flex items-center justify-between p-2 border-t bg-background">
|
||||
<div class="flex items-center space-x-2">
|
||||
<p class="text-sm font-medium">Rows</p>
|
||||
<Select.Root
|
||||
allowDeselect={false}
|
||||
type="single"
|
||||
value={`${table.getState().pagination.pageSize}`}
|
||||
onValueChange={(value) => {
|
||||
table.setPageSize(Number(value));
|
||||
}}
|
||||
>
|
||||
<Select.Trigger class="h-7 w-[70px]">
|
||||
{String(table.getState().pagination.pageSize)}
|
||||
</Select.Trigger>
|
||||
<Select.Content side="top">
|
||||
{#each [5, 10, 15, 20, 25] as pageSize (pageSize)}
|
||||
<Select.Item value={`${pageSize}`}>
|
||||
{pageSize}
|
||||
</Select.Item>
|
||||
{/each}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="flex w-[100px] items-center justify-center text-sm font-medium">
|
||||
Page {table.getState().pagination.pageIndex + 1} of
|
||||
{table.getPageCount()}
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
class="hidden size-7 p-0 lg:flex"
|
||||
onclick={() => table.setPageIndex(0)}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
>
|
||||
<span class="sr-only">Go to first page</span>
|
||||
<ChevronsLeftIcon />
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
class="size-7 p-0"
|
||||
onclick={() => table.previousPage()}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
>
|
||||
<span class="sr-only">Go to previous page</span>
|
||||
<ChevronLeftIcon />
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
class="size-7 p-0"
|
||||
onclick={() => table.nextPage()}
|
||||
disabled={!table.getCanNextPage()}
|
||||
>
|
||||
<span class="sr-only">Go to next page</span>
|
||||
<ChevronRightIcon />
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
class="hidden size-7 p-0 lg:flex"
|
||||
onclick={() => table.setPageIndex(table.getPageCount() - 1)}
|
||||
disabled={!table.getCanNextPage()}
|
||||
>
|
||||
<span class="sr-only">Go to last page</span>
|
||||
<ChevronsRightIcon />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
/* ✅ Ensure sticky header works properly */
|
||||
:global(.sticky) {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
</style>
|
||||
1
src/routes/dictionary/account/+page.svelte
Normal file
1
src/routes/dictionary/account/+page.svelte
Normal file
@ -0,0 +1 @@
|
||||
acc
|
||||
Loading…
x
Reference in New Issue
Block a user