feat: enable live search on all recipe pages
All checks were successful
CI / update (push) Successful in 1m9s

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.
This commit is contained in:
2026-01-02 20:25:43 +01:00
parent f6258ae518
commit 903722b335
10 changed files with 177 additions and 25 deletions

View File

@@ -26,6 +26,26 @@
noResults: isEnglish ? 'No recipes found.' : 'Keine Rezepte gefunden.',
tryOther: isEnglish ? 'Try different search terms.' : 'Versuche es mit anderen Suchbegriffen.'
});
// Search state for live filtering
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.allRecipes.length;
}
// Filter recipes based on live search
const displayedRecipes = $derived.by(() => {
if (!hasActiveSearch) {
// No active search - show server-side results
return data.results;
}
// Active search - show client-side filtered results
return data.allRecipes.filter(r => matchedRecipeIds.has(r._id));
});
</script>
<style>
@@ -71,25 +91,31 @@
season={data.filters.season}
favoritesOnly={data.filters.favoritesOnly}
lang={data.lang}
recipes={data.allRecipes}
onSearchResults={handleSearchResults}
/>
{#if data.error}
<div class="search-info">
<p>{labels.searchError} {data.error}</p>
</div>
{:else if hasActiveSearch}
<div class="search-info">
<p>{displayedRecipes.length} {labels.resultsFor} "{data.query}"</p>
</div>
{:else if data.query}
<div class="search-info">
<p>{data.results.length} {labels.resultsFor} "{data.query}"</p>
</div>
{/if}
{#if data.results.length > 0}
{#if displayedRecipes.length > 0}
<Recipes>
{#each data.results as recipe}
{#each displayedRecipes as recipe}
<Card {recipe} {current_month} isFavorite={recipe.isFavorite} showFavoriteIndicator={true} routePrefix="/{data.recipeLang}"></Card>
{/each}
</Recipes>
{:else if data.query && !data.error}
{:else if (data.query || hasActiveSearch) && !data.error}
<div class="search-info">
<p>{labels.noResults}</p>
<p>{labels.tryOther}</p>