feat(frontend): unify editorial UI and DRY form architecture
This commit is contained in:
parent
d4fbc1faf5
commit
693c6a9626
35 changed files with 2600 additions and 1180 deletions
|
|
@ -1,50 +1,51 @@
|
|||
<script lang="ts">
|
||||
import { enhance } from '$app/forms';
|
||||
import { resolve } from '$app/paths';
|
||||
import type { ActionData, PageData } from './$types';
|
||||
import { m } from '$lib/paraglide/messages.js';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { ArrowLeft } from 'lucide-svelte';
|
||||
import { Input } from '$lib/components/ui/input';
|
||||
import { Label } from '$lib/components/ui/label';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger } from '$lib/components/ui/select';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '$lib/components/ui/card';
|
||||
import FormSectionCard from '$lib/components/forms/FormSectionCard.svelte';
|
||||
import SimpleSelect from '$lib/components/forms/SimpleSelect.svelte';
|
||||
|
||||
let { data, form }: { data: PageData; form: ActionData } = $props();
|
||||
let partOfDay = $state('am');
|
||||
|
||||
const partOfDayOptions = [
|
||||
{ value: 'am', label: m.common_am() },
|
||||
{ value: 'pm', label: m.common_pm() }
|
||||
];
|
||||
</script>
|
||||
|
||||
<svelte:head><title>{m["routines_newTitle"]()} — innercontext</title></svelte:head>
|
||||
|
||||
<div class="max-w-md space-y-6">
|
||||
<div class="flex items-center gap-4">
|
||||
<a href="/routines" class="inline-flex items-center gap-1 text-sm text-muted-foreground hover:underline"><ArrowLeft class="size-4" /> {m["routines_backToList"]()}</a>
|
||||
<h2 class="text-2xl font-bold tracking-tight">{m["routines_newTitle"]()}</h2>
|
||||
</div>
|
||||
<div class="editorial-page space-y-4">
|
||||
<section class="editorial-panel reveal-1 space-y-3">
|
||||
<a href={resolve('/routines')} class="editorial-backlink"><ArrowLeft class="size-4" /> {m["routines_backToList"]()}</a>
|
||||
<p class="editorial-kicker">{m["nav_appSubtitle"]()}</p>
|
||||
<h2 class="editorial-title">{m["routines_newTitle"]()}</h2>
|
||||
</section>
|
||||
|
||||
{#if form?.error}
|
||||
<div class="rounded-md bg-destructive/10 px-4 py-3 text-sm text-destructive">{form.error}</div>
|
||||
<div class="editorial-alert editorial-alert--error">{form.error}</div>
|
||||
{/if}
|
||||
|
||||
<Card>
|
||||
<CardHeader><CardTitle>{m["routines_detailsTitle"]()}</CardTitle></CardHeader>
|
||||
<CardContent>
|
||||
<FormSectionCard title={m["routines_detailsTitle"]()} className="reveal-2">
|
||||
<form method="POST" use:enhance class="space-y-5">
|
||||
<div class="space-y-2">
|
||||
<Label for="routine_date">{m.routines_date()}</Label>
|
||||
<Input id="routine_date" name="routine_date" type="date" value={data.today} required />
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label>{m["routines_amOrPm"]()}</Label>
|
||||
<input type="hidden" name="part_of_day" value={partOfDay} />
|
||||
<Select type="single" value={partOfDay} onValueChange={(v) => (partOfDay = v)}>
|
||||
<SelectTrigger>{partOfDay.toUpperCase()}</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="am">{m.common_am()}</SelectItem>
|
||||
<SelectItem value="pm">{m.common_pm()}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<SimpleSelect
|
||||
id="part_of_day"
|
||||
name="part_of_day"
|
||||
label={m["routines_amOrPm"]()}
|
||||
options={partOfDayOptions}
|
||||
bind:value={partOfDay}
|
||||
/>
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="notes">{m.routines_notes()}</Label>
|
||||
|
|
@ -53,9 +54,8 @@
|
|||
|
||||
<div class="flex gap-3 pt-2">
|
||||
<Button type="submit">{m["routines_createRoutine"]()}</Button>
|
||||
<Button variant="outline" href="/routines">{m.common_cancel()}</Button>
|
||||
<Button variant="outline" href={resolve('/routines')}>{m.common_cancel()}</Button>
|
||||
</div>
|
||||
</form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</FormSectionCard>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue