mirror of
https://github.com/faiztyanirh/clqms-shadcn-v1.git
synced 2026-04-22 09:35:34 +07:00
bug fix + add feature
fix sidebar icon 1x click show all add dict container
This commit is contained in:
parent
c834876d49
commit
8f9e9ddffd
@ -72,45 +72,45 @@
|
||||
},
|
||||
{
|
||||
title: "Sample",
|
||||
url: "#",
|
||||
url: "/dictionary",
|
||||
icon: BookOpenIcon,
|
||||
submenus: [
|
||||
{
|
||||
title: "Container",
|
||||
url: "#",
|
||||
url: "/container",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Organization",
|
||||
url: "#",
|
||||
url: "/dictionary",
|
||||
icon: BookOpenIcon,
|
||||
submenus: [
|
||||
{
|
||||
title: "Account",
|
||||
url: "#",
|
||||
url: "/account",
|
||||
},
|
||||
{
|
||||
title: "Site",
|
||||
url: "#",
|
||||
url: "/site",
|
||||
},
|
||||
{
|
||||
title: "Discipline",
|
||||
url: "#",
|
||||
url: "/discipline",
|
||||
},
|
||||
{
|
||||
title: "Department",
|
||||
url: "#",
|
||||
url: "/department",
|
||||
},
|
||||
{
|
||||
title: "Workstation",
|
||||
url: "#",
|
||||
url: "/workstation",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Test",
|
||||
url: "/testdef",
|
||||
url: "/dictionary/test",
|
||||
icon: BookOpenIcon,
|
||||
},
|
||||
]
|
||||
|
||||
18
src/lib/components/dictionary/container/api/container-api.js
Normal file
18
src/lib/components/dictionary/container/api/container-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 getContainers(searchQuery) {
|
||||
return await searchWithParams(API.CONTAINER, searchQuery)
|
||||
}
|
||||
|
||||
export async function getContainer(searchQuery) {
|
||||
return await getById(API.CONTAINER, searchQuery)
|
||||
}
|
||||
|
||||
export async function createContainer(newContainerForm) {
|
||||
return await create(API.CONTAINER, newContainerForm)
|
||||
}
|
||||
|
||||
export async function editContainer(editContainerForm) {
|
||||
return await update(API.CONTAINER, editContainerForm)
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
import PlusIcon from "@lucide/svelte/icons/plus";
|
||||
import Settings2Icon from "@lucide/svelte/icons/settings-2";
|
||||
import PencilIcon from "@lucide/svelte/icons/pencil";
|
||||
|
||||
export const searchFields = [
|
||||
{
|
||||
key: "ConCode",
|
||||
label: "Container Code",
|
||||
type: "text",
|
||||
},
|
||||
{
|
||||
key: "ConName",
|
||||
label: "Container Name",
|
||||
type: "text",
|
||||
},
|
||||
];
|
||||
|
||||
export const detailSections = [
|
||||
{
|
||||
class: "grid grid-cols-2 gap-4 items-center",
|
||||
fields: [
|
||||
{ key: "SiteID", label: "Site" },
|
||||
{ key: "ConCode", label: "Container Code" },
|
||||
{ key: "ConName", label: "Container Name" },
|
||||
{ key: "ConDesc", label: "Description" },
|
||||
]
|
||||
},
|
||||
{
|
||||
class: "grid grid-cols-2 gap-4 items-center",
|
||||
fields: [
|
||||
{ key: "ConClass", label: "Container Class" },
|
||||
{ key: "Color", label: "Color" },
|
||||
{ key: "Additive", label: "Additive" },
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
export function containerActions(masterDetail) {
|
||||
return [
|
||||
{
|
||||
Icon: PlusIcon,
|
||||
label: 'Add Location',
|
||||
onClick: () => masterDetail.enterCreate(),
|
||||
},
|
||||
{
|
||||
Icon: Settings2Icon,
|
||||
label: 'Search Parameters',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function viewActions(handlers){
|
||||
return [
|
||||
{
|
||||
Icon: PencilIcon,
|
||||
label: 'Edit Container',
|
||||
onClick: handlers.editContainer,
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
import { API } from "$lib/config/api";
|
||||
import EraserIcon from "@lucide/svelte/icons/eraser";
|
||||
import { z } from "zod";
|
||||
|
||||
export const containerSchema = z.object({
|
||||
ConCode: z.string().min(1, "Required"),
|
||||
ConName: z.string().min(1, "Required"),
|
||||
});
|
||||
|
||||
export const containerInitialForm = {
|
||||
ConDefID: '',
|
||||
SiteID: '',
|
||||
ConCode: '',
|
||||
ConName: '',
|
||||
ConDesc: '',
|
||||
Additive: '',
|
||||
ConClass: '',
|
||||
Color: '',
|
||||
};
|
||||
|
||||
export const containerDefaultErrors = {
|
||||
ConCode: "Required",
|
||||
ConName: "Required",
|
||||
};
|
||||
|
||||
export const containerFormFields = [
|
||||
{
|
||||
title: "Basic Information",
|
||||
rows: [
|
||||
{
|
||||
type: "row",
|
||||
columns: [
|
||||
{
|
||||
key: "SiteID",
|
||||
label: "Site",
|
||||
required: false,
|
||||
type: "select",
|
||||
optionsEndpoint: `${API.BASE_URL}${API.SITE}`,
|
||||
valueKey: "SiteID",
|
||||
labelKey: (item) => `${item.SiteCode} - ${item.SiteName}`,
|
||||
},
|
||||
{
|
||||
key: "ConCode",
|
||||
label: "Container Code",
|
||||
required: true,
|
||||
type: "text",
|
||||
validateOn: ["input"]
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "row",
|
||||
columns: [
|
||||
{
|
||||
key: "ConName",
|
||||
label: "Container Name",
|
||||
required: true,
|
||||
type: "text",
|
||||
validateOn: ["input"]
|
||||
},
|
||||
{
|
||||
key: "ConDesc",
|
||||
label: "Description",
|
||||
required: false,
|
||||
type: "textarea",
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Container Properties",
|
||||
rows: [
|
||||
{
|
||||
type: "row",
|
||||
columns: [
|
||||
{
|
||||
key: "ConClass",
|
||||
label: "Container Class",
|
||||
required: false,
|
||||
type: "select",
|
||||
optionsEndpoint: `${API.BASE_URL}${API.VALUESET}/container_class`,
|
||||
},
|
||||
{
|
||||
key: "Color",
|
||||
label: "Color",
|
||||
required: false,
|
||||
type: "select",
|
||||
optionsEndpoint: `${API.BASE_URL}${API.VALUESET}/container_cap_color`,
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "row",
|
||||
columns: [
|
||||
{
|
||||
key: "Additive",
|
||||
label: "Additive",
|
||||
required: false,
|
||||
type: "select",
|
||||
optionsEndpoint: `${API.BASE_URL}${API.VALUESET}/additive`,
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
export function getContainerFormActions(handlers) {
|
||||
return [
|
||||
{
|
||||
Icon: EraserIcon,
|
||||
label: 'Clear Form',
|
||||
onClick: handlers.clearForm,
|
||||
},
|
||||
];
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
<script>
|
||||
import { useDictionaryForm } from "$lib/components/composable/use-dictionary-form.svelte";
|
||||
import FormPageContainer from "$lib/components/reusable/form/form-page-container.svelte";
|
||||
import DictionaryFormRenderer from "$lib/components/reusable/form/dictionary-form-renderer.svelte";
|
||||
import { toast } from "svelte-sonner";
|
||||
import ReusableAlertDialog from "$lib/components/reusable/reusable-alert-dialog.svelte";
|
||||
|
||||
let props = $props();
|
||||
|
||||
const { masterDetail, formFields, formActions, schema } = props.context;
|
||||
|
||||
const { formState } = masterDetail;
|
||||
|
||||
const helpers = useDictionaryForm(formState);
|
||||
|
||||
const handlers = {
|
||||
clearForm: () => {
|
||||
formState.reset();
|
||||
}
|
||||
};
|
||||
|
||||
const actions = formActions(handlers);
|
||||
|
||||
let showConfirm = $state(false);
|
||||
|
||||
async function handleSave() {
|
||||
const result = await formState.save(masterDetail.mode);
|
||||
|
||||
toast('Container Created!');
|
||||
masterDetail?.exitForm(true);
|
||||
}
|
||||
|
||||
const primaryAction = $derived({
|
||||
label: 'Save',
|
||||
onClick: handleSave,
|
||||
disabled: helpers.hasErrors || formState.isSaving.current,
|
||||
loading: formState.isSaving.current
|
||||
});
|
||||
|
||||
const secondaryActions = [];
|
||||
</script>
|
||||
|
||||
<FormPageContainer title="Create Container" {primaryAction} {secondaryActions} {actions}>
|
||||
<DictionaryFormRenderer
|
||||
{formState}
|
||||
formFields={formFields}
|
||||
mode="create"
|
||||
/>
|
||||
</FormPageContainer>
|
||||
|
||||
<ReusableAlertDialog
|
||||
bind:open={masterDetail.showExitConfirm}
|
||||
onConfirm={masterDetail.confirmExit}
|
||||
/>
|
||||
@ -0,0 +1,73 @@
|
||||
<script>
|
||||
import { useDictionaryForm } from "$lib/components/composable/use-dictionary-form.svelte";
|
||||
import FormPageContainer from "$lib/components/reusable/form/form-page-container.svelte";
|
||||
import DictionaryFormRenderer from "$lib/components/reusable/form/dictionary-form-renderer.svelte";
|
||||
import { toast } from "svelte-sonner";
|
||||
import { untrack } from "svelte";
|
||||
import { API } from "$lib/config/api";
|
||||
import ReusableAlertDialog from "$lib/components/reusable/reusable-alert-dialog.svelte";
|
||||
|
||||
let props = $props();
|
||||
|
||||
const { masterDetail, formFields, formActions, schema, initialForm } = props.context;
|
||||
|
||||
const { formState } = masterDetail;
|
||||
|
||||
const helpers = useDictionaryForm(formState);
|
||||
|
||||
let showConfirm = $state(false);
|
||||
|
||||
$effect(() => {
|
||||
untrack(() => {
|
||||
formFields.forEach(group => {
|
||||
group.rows.forEach(row => {
|
||||
row.columns.forEach(col => {
|
||||
if (col.type === "group") {
|
||||
col.columns.forEach(child => {
|
||||
if (child.type === "select" && child.optionsEndpoint) {
|
||||
formState.fetchOptions(child, formState.form);
|
||||
}
|
||||
});
|
||||
} else if ((col.type === "select") && col.optionsEndpoint) {
|
||||
formState.fetchOptions(col, formState.form);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
async function handleEdit() {
|
||||
const result = await formState.save(masterDetail.mode);
|
||||
|
||||
if (result.status === 'success') {
|
||||
console.log('Container updated successfully');
|
||||
toast('Container Updated!');
|
||||
masterDetail.exitForm(true);
|
||||
} else {
|
||||
console.error('Failed to update container:', result.message);
|
||||
}
|
||||
}
|
||||
|
||||
const primaryAction = $derived({
|
||||
label: 'Edit',
|
||||
onClick: handleEdit,
|
||||
disabled: helpers.hasErrors || formState.isSaving.current,
|
||||
loading: formState.isSaving.current
|
||||
});
|
||||
|
||||
const secondaryActions = [];
|
||||
</script>
|
||||
|
||||
<FormPageContainer title="Edit Container" {primaryAction} {secondaryActions}>
|
||||
<DictionaryFormRenderer
|
||||
{formState}
|
||||
formFields={formFields}
|
||||
mode="edit"
|
||||
/>
|
||||
</FormPageContainer>
|
||||
|
||||
<ReusableAlertDialog
|
||||
bind:open={masterDetail.showExitConfirm}
|
||||
onConfirm={masterDetail.confirmExit}
|
||||
/>
|
||||
@ -0,0 +1,68 @@
|
||||
<script>
|
||||
import { containerColumns } from "$lib/components/dictionary/container/table/container-columns";
|
||||
import { getContainers, getContainer } from "$lib/components/dictionary/container/api/container-api";
|
||||
import { useSearch } from "$lib/components/composable/use-search.svelte";
|
||||
import { searchFields, containerActions } from "$lib/components/dictionary/container/config/container-config";
|
||||
import TopbarWrapper from "$lib/components/topbar/topbar-wrapper.svelte";
|
||||
import ReusableSearchParam from "$lib/components/reusable/reusable-search-param.svelte";
|
||||
import ReusableEmpty from "$lib/components/reusable/reusable-empty.svelte";
|
||||
import ReusableDataTable from "$lib/components/reusable/reusable-data-table.svelte";
|
||||
import ArchiveXIcon from "@lucide/svelte/icons/archive-x";
|
||||
|
||||
let props = $props();
|
||||
|
||||
const search = useSearch(searchFields, getContainers);
|
||||
const initialForm = props.masterDetail.formState.form;
|
||||
const actions = containerActions(props.masterDetail, initialForm)
|
||||
actions.find(a => a.label === 'Search Parameters').popoverContent = searchParamSnippet;
|
||||
|
||||
let activeRowId = $state(null);
|
||||
</script>
|
||||
|
||||
{#snippet searchParamSnippet()}
|
||||
<ReusableSearchParam {searchFields}
|
||||
bind:searchQuery={search.searchQuery} onSearch={search.handleSearch} onReset={search.handleReset} isLoading={search.isLoading}
|
||||
selectOptions={search.selectOptions} loadingOptions={search.loadingOptions} fetchOptions={search.fetchOptions}
|
||||
/>
|
||||
{/snippet}
|
||||
|
||||
<div
|
||||
role="button"
|
||||
tabindex="0"
|
||||
onclick={() => props.masterDetail.isFormMode && props.masterDetail.exitForm()}
|
||||
onkeydown={(e) => e.key === 'Enter' && props.masterDetail.isFormMode && props.masterDetail.exitForm()}
|
||||
class={`
|
||||
${props.masterDetail.isMobile ? "w-full" : props.masterDetail.isFormMode ? "w-[3%] cursor-pointer" : "w-[35%]"}
|
||||
transition-all duration-300 flex flex-col items-center p-2 h-full overflow-y-auto
|
||||
`}
|
||||
>
|
||||
<div class={`flex w-full ${props.masterDetail.isFormMode ? "flex-col justify-center h-full items-center" : "flex-col justify-start h-full"}`} >
|
||||
{#if props.masterDetail.isFormMode}
|
||||
<span class="flex flex-col items-center justify-center gap-4 tracking-widest font-semibold select-none">
|
||||
{#each "CONTAINER".split("") as c}
|
||||
<span class="leading-none">{c}</span>
|
||||
{/each}
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
{#if !props.masterDetail.isFormMode}
|
||||
<div role="button" tabindex="0" class="flex flex-1 flex-col" onclick={(e) => e.stopPropagation()} onkeydown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
}}>
|
||||
<TopbarWrapper {actions}/>
|
||||
<div class="flex-1 w-full h-full">
|
||||
{#if search.searchData.length > 0}
|
||||
<ReusableDataTable data={search.searchData} columns={containerColumns} handleRowClick={props.masterDetail.select} {activeRowId} rowIdKey="ConDefID"/>
|
||||
{:else}
|
||||
<div class="flex h-full">
|
||||
<ReusableEmpty icon={ArchiveXIcon} desc="Try searching from search parameters"/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
@ -0,0 +1,91 @@
|
||||
<script>
|
||||
import { formatUTCDate } from "$lib/utils/formatUTCDate";
|
||||
import { detailSections, viewActions } from "$lib/components/dictionary/container/config/container-config";
|
||||
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";
|
||||
|
||||
let props = $props();
|
||||
|
||||
const { masterDetail, formFields, formActions, schema } = props.context;
|
||||
|
||||
let container = $derived(masterDetail?.selectedItem?.data);
|
||||
|
||||
const handlers = {
|
||||
editContainer: () => masterDetail.enterEdit("data"),
|
||||
};
|
||||
|
||||
const actions = viewActions(handlers);
|
||||
|
||||
function getFieldValue(field) {
|
||||
if (!container) return "-";
|
||||
|
||||
if (field.keys) {
|
||||
return field.keys
|
||||
.map(k => field.parentKey ? container[field.parentKey]?.[k] : container[k])
|
||||
.filter(val => val && val.trim() !== "")
|
||||
.join(" / ");
|
||||
}
|
||||
|
||||
return field.parentKey ? container[field.parentKey]?.[field.key] : container[field.key];
|
||||
}
|
||||
</script>
|
||||
|
||||
{#snippet Fieldset({ value, label, isUTCDate = false })}
|
||||
<div class="space-y-1.5">
|
||||
<dt class="text-xs font-medium text-muted-foreground uppercase tracking-wider">
|
||||
{label}
|
||||
</dt>
|
||||
<dd class="text-sm font-medium">
|
||||
{#if isUTCDate}
|
||||
{formatUTCDate(value)}
|
||||
{:else}
|
||||
{value ?? "-"}
|
||||
{/if}
|
||||
</dd>
|
||||
</div>
|
||||
{/snippet}
|
||||
|
||||
{#if masterDetail.selectedItem}
|
||||
<div class="flex flex-col px-2 py-1 gap-2 h-full w-full">
|
||||
<TopbarWrapper
|
||||
title={masterDetail.selectedItem.data.ConName}
|
||||
{actions}
|
||||
/>
|
||||
<div class="flex-1 min-h-0 overflow-y-auto space-y-4">
|
||||
{#each detailSections as section}
|
||||
<div class="p-4">
|
||||
{#if section.groups}
|
||||
<div class={section.class}>
|
||||
{#each section.groups as group}
|
||||
<div>
|
||||
<div class={group.class}>
|
||||
{#each group.fields as field}
|
||||
{@render Fieldset({
|
||||
label: field.label,
|
||||
value: getFieldValue(field),
|
||||
isUTCDate: field.isUTCDate
|
||||
})}
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<div class={section.class}>
|
||||
{#each section.fields as field}
|
||||
{@render Fieldset({
|
||||
label: field.label,
|
||||
value: getFieldValue(field),
|
||||
isUTCDate: field.isUTCDate
|
||||
})}
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<ReusableEmpty icon={ArchiveXIcon} desc="Select a container to see details"/>
|
||||
{/if}
|
||||
@ -0,0 +1,10 @@
|
||||
export const containerColumns = [
|
||||
{
|
||||
accessorKey: "ConCode",
|
||||
header: "Container Code",
|
||||
},
|
||||
{
|
||||
accessorKey: "ConName",
|
||||
header: "Container Name",
|
||||
},
|
||||
];
|
||||
@ -66,7 +66,7 @@
|
||||
{/snippet}
|
||||
</Collapsible.Root>
|
||||
{:else}
|
||||
<Popover.Root open={openPopovers[item.url]} onOpenChange={(open) => openPopovers[item.url] = open}>
|
||||
<Popover.Root open={openPopovers[index]} onOpenChange={(open) => openPopovers[index] = open}>
|
||||
<Sidebar.MenuItem>
|
||||
{#snippet trigger(props)}
|
||||
<Popover.Trigger {...props}>
|
||||
@ -90,7 +90,7 @@
|
||||
<Separator />
|
||||
{#each item.submenus || [] as submenu}
|
||||
<a href={`${item.url}${submenu.url}`}
|
||||
onclick={() => openPopovers[item.url] = false}
|
||||
onclick={() => openPopovers[index] = 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}
|
||||
<a href={item.url}
|
||||
onclick={() => openPopovers[item.url] = false}
|
||||
onclick={() => openPopovers[index] = 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}
|
||||
>
|
||||
|
||||
@ -66,7 +66,7 @@
|
||||
{/snippet}
|
||||
</Collapsible.Root>
|
||||
{:else}
|
||||
<Popover.Root open={openPopovers[item.url]} onOpenChange={(open) => openPopovers[item.url] = open}>
|
||||
<Popover.Root open={openPopovers[index]} onOpenChange={(open) => openPopovers[index] = open}>
|
||||
<Sidebar.MenuItem>
|
||||
{#snippet trigger(props)}
|
||||
<Popover.Trigger {...props}>
|
||||
@ -90,7 +90,7 @@
|
||||
<Separator />
|
||||
{#each item.submenus || [] as submenu}
|
||||
<a href={`${item.url}${submenu.url}`}
|
||||
onclick={() => openPopovers[item.url] = false}
|
||||
onclick={() => openPopovers[index] = 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}
|
||||
<a href={item.url}
|
||||
onclick={() => openPopovers[item.url] = false}
|
||||
onclick={() => openPopovers[index] = 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}
|
||||
>
|
||||
|
||||
51
src/routes/dictionary/container/+page.svelte
Normal file
51
src/routes/dictionary/container/+page.svelte
Normal file
@ -0,0 +1,51 @@
|
||||
<script>
|
||||
import { Separator } from "$lib/components/ui/separator/index.js";
|
||||
import { useMasterDetail } from "$lib/components/composable/use-master-detail.svelte";
|
||||
import { getContainer, createContainer, editContainer } from "$lib/components/dictionary/container/api/container-api";
|
||||
import MasterPage from "$lib/components/dictionary/container/page/master-page.svelte";
|
||||
import ViewPage from "$lib/components/dictionary/container/page/view-page.svelte";
|
||||
import CreatePage from "$lib/components/dictionary/container/page/create-page.svelte";
|
||||
import EditPage from "$lib/components/dictionary/container/page/edit-page.svelte";
|
||||
import { containerSchema, containerInitialForm, containerDefaultErrors, containerFormFields, getContainerFormActions } from "$lib/components/dictionary/container/config/container-form-config";
|
||||
|
||||
const masterDetail = useMasterDetail({
|
||||
onSelect: async (row) => {
|
||||
return await getContainer(row.ConDefID);
|
||||
},
|
||||
formConfig: {
|
||||
schema: containerSchema,
|
||||
initialForm: containerInitialForm,
|
||||
defaultErrors: containerDefaultErrors,
|
||||
mode: 'create',
|
||||
modeOpt: 'default',
|
||||
saveEndpoint: createContainer,
|
||||
editEndpoint: editContainer,
|
||||
}
|
||||
});
|
||||
|
||||
const pageContext = {
|
||||
masterDetail,
|
||||
formFields: containerFormFields,
|
||||
formActions: getContainerFormActions,
|
||||
schema: containerSchema,
|
||||
initialForm: containerInitialForm,
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex w-full h-full overflow-hidden">
|
||||
{#if masterDetail.showMaster}
|
||||
<MasterPage {masterDetail} />
|
||||
{/if}
|
||||
<Separator orientation="vertical"/>
|
||||
{#if masterDetail.showDetail}
|
||||
<main class={`${masterDetail.isMobile ? 'w-full' : masterDetail.isFormMode ? 'w-[97%] flex flex-col items-start' : 'w-[65%]'} h-full overflow-y-auto flex flex-col items-center transition-all duration-300`}>
|
||||
{#if masterDetail.mode === "view"}
|
||||
<ViewPage context={pageContext}/>
|
||||
{:else if masterDetail.mode === "create"}
|
||||
<CreatePage context={pageContext}/>
|
||||
{:else if masterDetail.mode === "edit"}
|
||||
<EditPage context={pageContext}/>
|
||||
{/if}
|
||||
</main>
|
||||
{/if}
|
||||
</div>
|
||||
Loading…
x
Reference in New Issue
Block a user