From 402cb015dfca25e6df2e85df7026545980daf177 Mon Sep 17 00:00:00 2001 From: Alexander Bocken Date: Fri, 2 Jan 2026 20:25:43 +0100 Subject: [PATCH] feat: enable live search on all recipe pages Previously, live client-side search only worked on the main /rezepte and /recipes pages. All other pages (category, tag, favorites, search results, icon, and season pages) fell back to server-side search with form submission. Now all recipe pages support live filtering as users type, providing consistent UX across the site. --- src/lib/components/IconLayout.svelte | 4 ++- src/lib/components/SeasonLayout.svelte | 4 ++- .../category/[category]/+page.svelte | 22 +++++++++++-- .../favorites/+page.svelte | 28 ++++++++++++++-- .../icon/[icon]/+page.svelte | 22 +++++++++++-- .../search/+page.server.ts | 24 ++++++++++---- .../search/+page.svelte | 32 +++++++++++++++++-- .../season/+page.svelte | 22 +++++++++++-- .../season/[month]/+page.svelte | 22 +++++++++++-- .../tag/[tag]/+page.svelte | 22 +++++++++++-- 10 files changed, 177 insertions(+), 25 deletions(-) diff --git a/src/lib/components/IconLayout.svelte b/src/lib/components/IconLayout.svelte index a1096446..4cbf1033 100644 --- a/src/lib/components/IconLayout.svelte +++ b/src/lib/components/IconLayout.svelte @@ -6,6 +6,8 @@ export let active_icon export let routePrefix = '/rezepte' export let lang = 'de' + export let recipes = [] + export let onSearchResults = (ids, categories) => {}

{label} {data.category}:

- +
- {#each rand_array(data.recipes) as recipe} + {#each rand_array(filteredRecipes) as recipe} {/each} diff --git a/src/routes/[recipeLang=recipeLang]/favorites/+page.svelte b/src/routes/[recipeLang=recipeLang]/favorites/+page.svelte index bcb9c566..ff4c700a 100644 --- a/src/routes/[recipeLang=recipeLang]/favorites/+page.svelte +++ b/src/routes/[recipeLang=recipeLang]/favorites/+page.svelte @@ -27,6 +27,24 @@ : 'Besuche ein Rezept und klicke auf das Herz-Symbol, um es zu deinen Favoriten hinzuzufügen.', recipesLink: isEnglish ? 'recipe' : 'Rezept' }); + + // Search state + let matchedRecipeIds = $state(new Set()); + let hasActiveSearch = $state(false); + + // Handle search results from Search component + function handleSearchResults(ids, categories) { + matchedRecipeIds = ids; + hasActiveSearch = ids.size < data.favorites.length; + } + + // Filter recipes based on search + const filteredFavorites = $derived.by(() => { + if (!hasActiveSearch) { + return data.favorites; + } + return data.favorites.filter(r => matchedRecipeIds.has(r._id)); + });

{label} {data.tag}:

- +
- {#each rand_array(data.recipes) as recipe} + {#each rand_array(filteredRecipes) as recipe} {/each}