Refactor admin to shared generic CRUD; restructure proclamation categories/groups and APIs
- Replace per-model admin forms with the shared generic AdminTable/AdminModal CRUD - Add ProclamationGroup model and admin + API v2 routes (replaces subscription levels) - Drop subscription levels and flatten proclamation categories - Update v2 serializers and seed data accordingly
This commit is contained in:
@@ -1,11 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { PageProps } from './$types';
|
||||
import type { ActionResult } from '$lib/svelte-admin/types';
|
||||
import { enhance } from '$app/forms';
|
||||
import AdminTable from '$lib/components/admin/AdminTable.svelte';
|
||||
import AdminModal from '$lib/components/admin/AdminModal.svelte';
|
||||
import Toast from '$lib/components/admin/Toast.svelte';
|
||||
import { getModelConfig } from '$lib/svelte-admin/registry';
|
||||
import UserRoleForm from './UserRoleForm.svelte';
|
||||
|
||||
let { data, form }: PageProps = $props();
|
||||
|
||||
@@ -15,16 +14,17 @@
|
||||
let modalOpen = $state(false);
|
||||
let editingRecord = $state<Record<string, unknown> | null>(null);
|
||||
let toastMessage = $state('');
|
||||
let toastType = $state<'success' | 'error'>('success');
|
||||
let fieldErrors = $state<Record<string, string>>({});
|
||||
let formError = $state('');
|
||||
|
||||
let name = $state('');
|
||||
let dirty = $state(false);
|
||||
|
||||
$effect(() => {
|
||||
if (form && 'success' in (form as any)) {
|
||||
const result = form as any;
|
||||
if (result.success) {
|
||||
toastMessage = 'Saved successfully';
|
||||
toastType = 'success';
|
||||
closeModal();
|
||||
} else {
|
||||
formError = result.error ?? '';
|
||||
@@ -33,6 +33,11 @@
|
||||
}
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
name = String((editingRecord ?? {})['name'] ?? '');
|
||||
dirty = false;
|
||||
});
|
||||
|
||||
function openCreate() {
|
||||
editingRecord = null;
|
||||
formError = '';
|
||||
@@ -53,10 +58,14 @@
|
||||
formError = '';
|
||||
fieldErrors = {};
|
||||
}
|
||||
|
||||
function markDirty() {
|
||||
if (editingRecord?.id) dirty = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="p-6">
|
||||
<h1 class="mb-4 text-xl font-bold text-gray-900 dark:text-gray-100">{config.displayName}</h1>
|
||||
<div>
|
||||
<h1>{config.displayName}</h1>
|
||||
<AdminTable
|
||||
records={data.records}
|
||||
listFields={config.listFields}
|
||||
@@ -77,14 +86,33 @@
|
||||
{canDelete}
|
||||
recordId={editingRecord?.id as string | undefined}
|
||||
>
|
||||
<UserRoleForm
|
||||
record={editingRecord ?? {}}
|
||||
{fieldErrors}
|
||||
{formError}
|
||||
submitLabel={editingRecord ? 'Update' : 'Create'}
|
||||
/>
|
||||
<form action="?/upsert" method="POST" use:enhance oninput={markDirty}>
|
||||
{#if editingRecord?.id}
|
||||
<input type="hidden" name="id" value={String(editingRecord.id)} />
|
||||
{/if}
|
||||
|
||||
{#if formError}
|
||||
<div>{formError}</div>
|
||||
{/if}
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<label for="field-name">Name</label>
|
||||
<input type="text" id="field-name" name="name" bind:value={name} />
|
||||
{#if fieldErrors.name}
|
||||
<p>{fieldErrors.name}</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button type="submit" disabled={!!editingRecord?.id && !dirty}>
|
||||
{editingRecord ? 'Update' : 'Create'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</AdminModal>
|
||||
|
||||
{#if toastMessage}
|
||||
<Toast message={toastMessage} type={toastType} />
|
||||
<Toast message={toastMessage} />
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user