feat: add API client, types, layout, and all page routes
This commit is contained in:
parent
2e4e3fba50
commit
b140c55cda
71 changed files with 3237 additions and 58 deletions
27
frontend/src/routes/routines/new/+page.server.ts
Normal file
27
frontend/src/routes/routines/new/+page.server.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { createRoutine } from '$lib/api';
|
||||
import { fail, redirect } from '@sveltejs/kit';
|
||||
import type { Actions, PageServerLoad } from './$types';
|
||||
|
||||
export const load: PageServerLoad = async () => {
|
||||
return { today: new Date().toISOString().slice(0, 10) };
|
||||
};
|
||||
|
||||
export const actions: Actions = {
|
||||
default: async ({ request }) => {
|
||||
const form = await request.formData();
|
||||
const routine_date = form.get('routine_date') as string;
|
||||
const part_of_day = form.get('part_of_day') as string;
|
||||
const notes = form.get('notes') as string;
|
||||
|
||||
if (!routine_date || !part_of_day) {
|
||||
return fail(400, { error: 'Date and AM/PM are required' });
|
||||
}
|
||||
|
||||
try {
|
||||
const routine = await createRoutine({ routine_date, part_of_day, notes: notes || undefined });
|
||||
redirect(303, `/routines/${routine.id}`);
|
||||
} catch (e) {
|
||||
return fail(500, { error: (e as Error).message });
|
||||
}
|
||||
}
|
||||
};
|
||||
59
frontend/src/routes/routines/new/+page.svelte
Normal file
59
frontend/src/routes/routines/new/+page.svelte
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
<script lang="ts">
|
||||
import { enhance } from '$app/forms';
|
||||
import type { ActionData, PageData } from './$types';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
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';
|
||||
|
||||
let { data, form }: { data: PageData; form: ActionData } = $props();
|
||||
let partOfDay = $state('am');
|
||||
</script>
|
||||
|
||||
<svelte:head><title>New Routine — innercontext</title></svelte:head>
|
||||
|
||||
<div class="max-w-md space-y-6">
|
||||
<div class="flex items-center gap-4">
|
||||
<a href="/routines" class="text-sm text-muted-foreground hover:underline">← Routines</a>
|
||||
<h2 class="text-2xl font-bold tracking-tight">New Routine</h2>
|
||||
</div>
|
||||
|
||||
{#if form?.error}
|
||||
<div class="rounded-md bg-destructive/10 px-4 py-3 text-sm text-destructive">{form.error}</div>
|
||||
{/if}
|
||||
|
||||
<Card>
|
||||
<CardHeader><CardTitle>Routine details</CardTitle></CardHeader>
|
||||
<CardContent>
|
||||
<form method="POST" use:enhance class="space-y-5">
|
||||
<div class="space-y-2">
|
||||
<Label for="routine_date">Date *</Label>
|
||||
<Input id="routine_date" name="routine_date" type="date" value={data.today} required />
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label>AM or PM *</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">AM</SelectItem>
|
||||
<SelectItem value="pm">PM</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="notes">Notes</Label>
|
||||
<Input id="notes" name="notes" placeholder="Optional notes" />
|
||||
</div>
|
||||
|
||||
<div class="flex gap-3 pt-2">
|
||||
<Button type="submit">Create routine</Button>
|
||||
<Button variant="outline" href="/routines">Cancel</Button>
|
||||
</div>
|
||||
</form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
Loading…
Add table
Add a link
Reference in a new issue