feat(frontend): unify editorial UI and DRY form architecture

This commit is contained in:
Piotr Oleszczyk 2026-03-04 21:43:37 +01:00
parent d4fbc1faf5
commit 693c6a9626
35 changed files with 2600 additions and 1180 deletions

View file

@ -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>