From 4d5e0aa963687d62e5b3ded4066ec14e443db603 Mon Sep 17 00:00:00 2001 From: Hendrik Date: Fri, 17 Apr 2026 15:28:22 +0200 Subject: [PATCH] feat(ui): add layout with profile bar, home, search, recipe pages - Homepage with search and recent recipes - Search page listing local hits (FTS5) - Recipe page with ratings, favorites, cooking log, comments - Wake-Lock on recipe view for mobile kitchen use Co-Authored-By: Claude Opus 4.7 (1M context) --- src/routes/+layout.svelte | 60 +++- src/routes/+page.svelte | 138 ++++++++-- src/routes/recipes/[id]/+page.server.ts | 23 ++ src/routes/recipes/[id]/+page.svelte | 352 ++++++++++++++++++++++++ src/routes/search/+page.svelte | 175 ++++++++++++ 5 files changed, 722 insertions(+), 26 deletions(-) create mode 100644 src/routes/recipes/[id]/+page.server.ts create mode 100644 src/routes/recipes/[id]/+page.svelte create mode 100644 src/routes/search/+page.svelte diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 4fa864c..e5a463f 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1 +1,59 @@ - + + +
+ Kochwas + +
+ +
+ {@render children()} +
+ + diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index bb390d1..ca7c74d 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,8 +1,18 @@ -
+

Kochwas

- +
-

Phase 1: Foundations — Suche folgt in Phase 3.

-
+ + +{#if recent.length > 0} +
+

Zuletzt hinzugefügt

+ +
+{/if} diff --git a/src/routes/recipes/[id]/+page.server.ts b/src/routes/recipes/[id]/+page.server.ts new file mode 100644 index 0000000..9baf2a7 --- /dev/null +++ b/src/routes/recipes/[id]/+page.server.ts @@ -0,0 +1,23 @@ +import type { PageServerLoad } from './$types'; +import { error } from '@sveltejs/kit'; +import { getDb } from '$lib/server/db'; +import { getRecipeById } from '$lib/server/recipes/repository'; +import { + listComments, + listCookingLog, + listRatings +} from '$lib/server/recipes/actions'; + +export const load: PageServerLoad = async ({ params }) => { + const id = Number(params.id); + if (!Number.isInteger(id) || id <= 0) error(400, { message: 'Invalid id' }); + const db = getDb(); + const recipe = getRecipeById(db, id); + if (!recipe) error(404, { message: 'Nicht gefunden' }); + const ratings = listRatings(db, id); + const comments = listComments(db, id); + const cooking_log = listCookingLog(db, id); + const avg_stars = + ratings.length === 0 ? null : ratings.reduce((s, r) => s + r.stars, 0) / ratings.length; + return { recipe, ratings, comments, cooking_log, avg_stars }; +}; diff --git a/src/routes/recipes/[id]/+page.svelte b/src/routes/recipes/[id]/+page.svelte new file mode 100644 index 0000000..60cde78 --- /dev/null +++ b/src/routes/recipes/[id]/+page.svelte @@ -0,0 +1,352 @@ + + + + {#snippet showActions()} +
+
+ Deine Bewertung: + + {#if data.avg_stars !== null} + ⌀ {data.avg_stars.toFixed(1)} ({ratings.length}) + {/if} +
+
+ + + + + +
+
+ {/snippet} +
+ +
+

Kommentare

+ {#if comments.length === 0} +

Noch keine Kommentare.

+ {/if} +
    + {#each comments as c (c.id)} +
  • +
    {c.author}
    +
    {c.text}
    +
    {new Date(c.created_at).toLocaleString('de-DE')}
    +
  • + {/each} +
+
+ + +
+
+ +{#if cookingLog.length > 0} +
+

Kochjournal

+
    + {#each cookingLog.slice(0, 20) as entry (entry.id)} +
  • + {new Date(entry.cooked_at).toLocaleString('de-DE')} +
  • + {/each} +
+
+{/if} + + diff --git a/src/routes/search/+page.svelte b/src/routes/search/+page.svelte new file mode 100644 index 0000000..6a18db3 --- /dev/null +++ b/src/routes/search/+page.svelte @@ -0,0 +1,175 @@ + + + + +{#if loading} +

Suche läuft …

+{:else if searched && hits.length === 0} +
+

Kein Rezept im Bestand für „{query}".

+

Bald: Internet durchsuchen.

+
+{:else if hits.length > 0} + + {#if canWebSearch} +

Weitersuchen im Internet — Phase 4.

+ {/if} +{/if} + +