Commit Graph

235 Commits

Author SHA1 Message Date
0459ef26bc fix: use simple event handler for file selection instead of $effect
All checks were successful
CI / update (push) Successful in 1m21s
Replace $effect + bind:files approach with straightforward onchange handler:
- Use event.currentTarget.files[0] to get selected file
- Avoid reactive complexity that caused infinite loops
- Add bind:this reference to file input for clearing
- Clean implementation that works reliably in Svelte 5
2026-01-20 17:29:41 +01:00
3fb0a72014 fix: rewrite CardAdd image upload using Svelte 5 best practices
All checks were successful
CI / update (push) Successful in 1m20s
Replace event handler approach with bind:files and $effect:
- Use bind:files on file input for reactive FileList binding
- Use $effect to react to file selection and handle validation
- Properly clean up blob URLs to prevent memory leaks
- Remove exported functions that aren't used externally
- Add key to each block for tags
- Fix self-assignment warning in tag handling

The previous implementation used onchange with this.files which doesn't
work in Svelte 5. The new approach uses the idiomatic bind:files pattern.
2026-01-20 17:18:25 +01:00
b5fbedd13b fix: use event parameter in CardAdd image selection handler
All checks were successful
CI / update (push) Successful in 1m21s
The show_local_image function was using `this.files[0]` which doesn't work
in Svelte 5's onchange handlers. Changed to use `event.target.files[0]`
to properly access the selected file.

This fixes recipe image uploads not working because the file was never
being captured from the input element.
2026-01-20 17:09:28 +01:00
1bf4f4cbcd debug: add client-side logging for recipe image upload
All checks were successful
CI / update (push) Successful in 1m22s
Add console logging in the browser to track image selection and form
submission:
- Log when user selects an image file in CardAdd component
- Log file validation steps (MIME type, size)
- Log form submission and FormData preparation
- Log whether image is being appended to form

This helps diagnose if the issue is client-side (image not selected/sent)
or server-side (image not received/processed).
2026-01-20 17:04:33 +01:00
50b0e7a70e fix: handle undefined/null input in stripHtmlTags function
All checks were successful
CI / update (push) Successful in 1m19s
Adds null check to prevent crash when recipe name or description fields are undefined.
2026-01-19 21:55:32 +01:00
5598b19ec9 perf: optimize bundle size and add build optimizations
All checks were successful
CI / update (push) Successful in 1m23s
- Move HTML stripping to server-side to remove cheerio from client bundle (247KB reduction)
- Add terser minification with console/debugger removal
- Enable manual code chunking for chart.js and auth libraries
- Convert TTF fonts to WOFF2 format (~900KB savings)
- Enable brotli/gzip precompression in adapter
- Update CSS to prefer WOFF2 with TTF fallback
2026-01-19 21:46:10 +01:00
a48ae3ff3c refactor: defer recipe image upload until form submission
Changed recipe image upload behavior to only process images when the
form is submitted, rather than immediately on file selection. This
prevents orphaned image files when users abandon the form.

Changes:
- CardAdd.svelte: Preview only, store File object instead of uploading
- Created imageProcessing.ts: Shared utility for image processing
- Add/edit page clients: Use selected_image_file instead of filename
- Add/edit page servers: Process and save images during form submission
- Images are validated, hashed, and saved in multiple formats on submit

Benefits:
- No orphaned files from abandoned forms
- Faster initial file selection experience
- Server-side image processing ensures security validation
- Cleaner architecture with shared processing logic
2026-01-15 14:18:52 +01:00
5fae01c06d feat: use checksummed filenames for recipe images and clean up old files
All checks were successful
CI / update (push) Successful in 1m13s
Updated recipe image handling to use checksummed filenames for proper
cache busting. When uploading a new image during recipe edit, old image
files (both hashed and unhashed versions) are now properly deleted from
all directories (full, thumb, placeholder).

Changes:
- CardAdd.svelte: Use checksummed filename from upload response
- Edit page server: Add deleteRecipeImage() helper to remove old images
- Edit page server: Delete old images when new image is uploaded
2026-01-15 13:57:06 +01:00
baa3f3e533 feat: add Redis caching to cospend API endpoints
All checks were successful
CI / update (push) Successful in 1m21s
Implement comprehensive caching for all cospend routes to improve performance:

Cache Implementation:
- Balance API: 30-minute TTL for user balances and global balances
- Debts API: 15-minute TTL for debt breakdown calculations
- Payments List: 10-minute TTL with pagination support
- Individual Payment: 30-minute TTL for payment details

Cache Invalidation:
- Created invalidateCospendCaches() helper function
- Invalidates user balances, debts, and payment lists on mutations
- Applied to payment create, update, and delete operations
- Applied to recurring payment execution (manual and cron)
2026-01-13 19:45:11 +01:00
041d415525 fix: allow arbitrary decimal values for base multiplier 2026-01-13 19:30:35 +01:00
296201eee5 fix: improve UI elements in recipe editor
All checks were successful
CI / update (push) Successful in 1m14s
- Center isBaseRecipe toggle by changing display to inline-flex
- Fix note field editing by adding textarea with bindable value
- Clear instruction step input after submission instead of restoring placeholder
- Style note textarea with transparent background and lighter placeholder text

The instruction field now properly clears on submission, while ingredient fields retain their previous values.
2026-01-13 19:14:26 +01:00
b43b45dac2 feat: add base multiplier support for recipe references
Add optional baseMultiplier field to ingredient and instruction references, allowing base recipes to be included at scaled amounts (e.g., 0.5 for half the recipe).

- Add baseMultiplier field to Recipe schema with default value of 1
- Update TypeScript types to include baseMultiplier
- Add multiplier input field to BaseRecipeSelector modal
- Apply baseMultiplier to ingredient amounts during flattening
- Combine baseMultiplier with recipe multiplier in links
- Display and allow editing baseMultiplier in recipe editor

The multiplier cascades through nested references and works alongside the standard recipe multiplier for compound scaling.
2026-01-13 19:14:10 +01:00
0a49e20c02 refactor: migrate recipe forms to SvelteKit actions with secure image upload
Refactor recipe add/edit routes from client-side fetch to proper SvelteKit
form actions with progressive enhancement and comprehensive security improvements.

**Security Enhancements:**
- Implement 5-layer image validation (file size, MIME type, extension, magic bytes, Sharp structure)
- Replace insecure base64 JSON encoding with FormData for file uploads
- Add file-type@19 dependency for magic bytes validation
- Validate actual file type via magic bytes to prevent file type spoofing

**Progressive Enhancement:**
- Forms now work without JavaScript using native browser submission
- Add use:enhance for improved client-side UX when JS is available
- Serialize complex nested data (ingredients/instructions) via JSON in hidden fields
- Translation workflow integrated via programmatic form submission

**Bug Fixes:**
- Add type="button" to all interactive buttons in CreateIngredientList and CreateStepList
  to prevent premature form submission when clicking on ingredients/steps
- Fix SSR errors by using season_local state instead of get_season() DOM query
- Fix redirect handling in form actions (redirects were being caught as errors)
- Fix TranslationApproval to handle recipes without images using null-safe checks
- Add reactive effect to sync editableEnglish.images with germanData.images length
- Detect and hide 150x150 placeholder images in CardAdd component

**Features:**
- Make image uploads optional for recipe creation (use placeholder based on short_name)
- Handle three image scenarios in edit: keep existing, upload new, rename on short_name change
- Automatic image file renaming across full/thumb/placeholder directories when short_name changes
- Change detection for partial translation updates in edit mode

**Technical Changes:**
- Create imageValidation.ts utility with comprehensive file validation
- Create recipeFormHelpers.ts for data extraction, validation, and serialization
- Refactor /api/rezepte/img/add endpoint to use FormData instead of base64
- Update CardAdd component to upload via FormData immediately with proper error handling
- Use Image API for placeholder detection (avoids CORS issues with fetch)
2026-01-13 15:12:07 +01:00
a936b736de feat: add AND/OR logic mode toggle to filter panel
All checks were successful
CI / update (push) Successful in 1m15s
- Add LogicModeToggle component to switch between AND and OR filter logic
- Enable multi-select for category and icon filters in OR mode
- Update Search component to handle both AND and OR filtering logic
- Resize Toggle component to match LogicModeToggle size (44px x 24px)
- Position logic mode toggle on the left side of filter panel
- Auto-convert arrays to single values when switching from OR to AND mode
- In OR mode: recipes match if they satisfy ANY active filter
- In AND mode: recipes must satisfy ALL active filters
2026-01-10 17:34:13 +01:00
bc170abcdf fix: add category and favorites filters to all recipe pages
- Move categories logic into Search component for centralization
- Add isLoggedIn prop to SeasonLayout and IconLayout components
- Fix FilterPanel CSS to properly handle hidden favorites filter
- Fix FavoritesFilter to trigger onToggle when checkbox changes
- Update Search effect to track all filter states (category, tags, icon, season, favorites)
- Hide favorites filter on favorites page while maintaining proper grid layout
- All filters now work consistently across entire site
2026-01-10 17:20:00 +01:00
7ab3482850 fix: resolve Svelte 5 migration warnings and improve accessibility
All checks were successful
CI / update (push) Successful in 2m2s
- Fix state_referenced_locally warnings by extracting initial values to constants
- Remove unused CSS selectors (subheading, header-actions, back-actions)
- Add ARIA roles and keyboard handlers to settlement options
- Add a11y ignore comment for custom checkbox implementation
2026-01-10 17:05:39 +01:00
5c8605c690 feat: complete Svelte 5 migration across entire application
All checks were successful
CI / update (push) Successful in 2m8s
Migrated all components and routes from Svelte 4 to Svelte 5 syntax:

- Converted export let → $props() with generic type syntax
- Replaced createEventDispatcher → callback props
- Migrated $: reactive statements → $derived() and $effect()
- Updated two-way bindings with $bindable()
- Fixed TypeScript syntax: added lang="ts" to script tags
- Converted inline type annotations to generic parameter syntax

- Updated deprecated event directives to Svelte 5 syntax:
  - on:click → onclick
  - on:submit → onsubmit
  - on:change → onchange

- Converted deprecated <slot> elements → {@render children()}
- Updated slot props to Snippet types
- Fixed season/icon selector components with {#snippet} blocks

- Fixed non-reactive state by converting let → $state()
- Fixed infinite loop in EnhancedBalance by converting $effect → $derived
- Fixed Chart.js integration by converting $state proxies to plain arrays
- Updated cospend dashboard and payment pages with proper reactivity

- Migrated 20+ route files from export let data → $props()
- Fixed TypeScript type annotations in page components
- Updated reactive statements in error and cospend routes

- Removed invalid onchange attribute from Toggle component
- Fixed modal ID isolation in CreateIngredientList/CreateStepList
- Fixed dark mode button visibility in TranslationApproval
- Build now succeeds with zero deprecation warnings

All functionality tested and working. No breaking changes to user experience.
2026-01-10 16:20:50 +01:00
8eee15d901 remove predigten 2026-01-10 15:33:21 +01:00
2c370363f5 fix: resolve recipe edit modal issues and improve dark mode visibility
All checks were successful
CI / update (push) Successful in 1m15s
- Migrate TranslationApproval and edit page to Svelte 5 runes ($props, $state, $derived)
- Fix empty modal issue by eagerly initializing editableEnglish from germanData
- Fix modal state isolation by adding language-specific modal IDs (en/de)
- Resolve cross-contamination where English modals opened German ingredient/instruction editors
- Improve button icon visibility in dark mode by setting white fill color
- Replace createEventDispatcher with callback props for Svelte 5 compatibility
2026-01-10 10:48:02 +01:00
1628f8ba23 feat: add Redis caching for recipe queries with automatic invalidation
All checks were successful
CI / update (push) Successful in 13s
Implements Redis caching layer for recipe endpoints to reduce MongoDB load and improve response times:

- Install ioredis for Redis client with TypeScript support
- Create cache.ts with namespaced keys (homepage: prefix) to avoid conflicts with other Redis applications
- Add caching to recipe query endpoints (all_brief, by tag, in_season) with 1-hour TTL
- Implement automatic cache invalidation on recipe create/edit/delete operations
- Cache recipes before randomization to maximize cache reuse while maintaining random order per request
- Add graceful fallback to MongoDB if Redis is unavailable
- Update .env.example with Redis configuration (REDIS_HOST, REDIS_PORT)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-07 20:25:11 +01:00
bfba0870e3 fix hover on Card not red
All checks were successful
CI / update (push) Successful in 1m11s
2026-01-05 23:50:03 +01:00
2feb8355b8 refactor: add TypeScript type annotations to fix implicit 'any' errors
Fixed 12 type errors by adding proper type annotations:

Quick Wins Completed:
- do_on_key.js: Added JSDoc types for KeyboardEvent and function parameters
- randomize.js: Added JSDoc types with generic template for array shuffling
- cookie.js: Added JSDoc types for Request API
- stripHtmlTags.ts: Added TypeScript types for string parameter

Progress: 12/1239 errors fixed (Quick Wins - Category 1 partial)

Created TODO_cleanup.md to track remaining 1227 type errors systematically.
2026-01-05 23:49:02 +01:00
f66334290a refactor: complete Svelte 5 migration to eliminate all deprecation warnings
All checks were successful
CI / update (push) Successful in 1m35s
Migrated all components and routes to Svelte 5 syntax standards:

Event Handlers:
- Updated all deprecated on:* directives to new on* attribute syntax
- Changed on:click → onclick, on:keydown → onkeydown, on:input → oninput
- Updated on:blur, on:focus, on:load, on:submit, on:cancel handlers

Reactive State:
- Added $state() declarations for all reactive variables
- Fixed non-reactive update warnings in layout and component files

Component API:
- Replaced <slot /> with {@render children()} pattern
- Added children prop to components using slots

Accessibility:
- Added id attributes to inputs and for attributes to labels
- Fixed label-control associations across forms
- Removed event listeners from non-interactive elements

HTML Fixes:
- Fixed self-closing textarea tags
- Corrected implicitly closed elements
- Proper element nesting

CSS Cleanup:
- Removed 20+ unused CSS selectors across components
- Cleaned up orphaned styles from refactoring

All vite-plugin-svelte warnings resolved. Codebase now fully compliant with Svelte 5.
2026-01-05 23:39:44 +01:00
2de51ee492 fix: eliminate layout shift in recipe search by reserving filter panel space
All checks were successful
CI / update (push) Successful in 1m10s
Changed FilterPanel from conditional rendering to always-rendered with visibility control. This prevents layout shift when JavaScript loads by reserving the space upfront while keeping it visually hidden for non-JS users.
2026-01-05 23:19:59 +01:00
ab84ffc131 fix: force white color for Login link in production with !important
All checks were successful
CI / update (push) Successful in 1m39s
The Login link was appearing light blue and nord purple when visited
in production/preview builds due to CSS specificity conflicts with
global nordtheme.css link styles. Added !important flags to enforce
white color for all link states and nord8 for hover/focus states.
2026-01-05 23:08:32 +01:00
3a2a4ec928 feat: consolidate admin features into centralized administration page
All checks were successful
CI / update (push) Successful in 1m10s
- Created administration page at /{recipeLang}/administration accessible only to rezepte_users
- Moved alt-text generator from /admin to /{recipeLang}/admin/alt-text-generator
- Added "Administration" link to user profile dropdown for rezepte_users
- Removed "Unübersetzt" link from main navigation (now accessed via administration page)
- Administration page provides card-based UI with links to:
  - Untranslated Recipes management
  - AI Alt-Text Generator
- Both features now integrated into recipe language routing structure
- Added server-side authentication to all admin routes
2026-01-05 22:54:27 +01:00
6b3aed582e fix: improve logo alignment and reduce focus area padding
All checks were successful
CI / update (push) Successful in 1m11s
- Removed 'entry' class from desktop logo to match mobile implementation
- Added left padding to nav for consistent logo alignment across viewports
- Reduces excessive padding when tabbing through logo links
2026-01-05 22:33:31 +01:00
9cec69af10 fix: ensure Login link uses consistent white styling like other header links
Updated CSS selectors to specifically target 'a.entry' instead of '.entry' to properly apply styling to the Login link. This ensures the link appears white in both light and dark modes, matching the styling of other navigation links.
2026-01-05 22:29:25 +01:00
6faa06e0e1 fix: improve text contrast in filter labels and update login button text
All checks were successful
CI / update (push) Successful in 1m12s
- Change login button text from "Log In" to "Login"
- Update filter labels (Kategorie, Icon, Tags, Saison, Favoriten) to use darker color (nord2) in light mode for better readability
- Improve placeholder text contrast in filter inputs by using lighter shade (nord4)
- Maintain light color scheme (nord6) for filter labels in dark mode
2026-01-05 17:53:01 +01:00
4ffc0940ef feat: add AI-powered alt text generation for recipe images
All checks were successful
CI / update (push) Successful in 1m10s
- Implement local Ollama integration for bilingual (DE/EN) alt text generation
- Add image management UI to German edit page and English translation section
- Update Card and recipe detail pages to display alt text from images array
- Include GenerateAltTextButton component for manual alt text generation
- Add bulk processing admin page for batch alt text generation
- Optimize images to 1024x1024 before AI processing for 75% faster generation
- Store alt text in recipe.images[].alt and translations.en.images[].alt
2026-01-05 17:28:19 +01:00
cc978e73b4 feat: improve accessibility and update color scheme based on PageSpeed insights
All checks were successful
CI / update (push) Successful in 1m13s
- Add aria-labels to icon-only links (add button, edit button, logo, nav toggle)
- Add main landmark element for better page structure
- Fix heading hierarchy on recipe pages (h1 → h2 → h3 progression)
- Add role="status" to loading placeholders to allow aria-label usage
- Update link colors from red to blue for better contrast in both light and dark modes
- Change hover colors from orange/red to light blue across all interactive elements
- Reduce font size of section labels (Season, Keywords) while maintaining semantic structure

These changes address PageSpeed accessibility recommendations including low-contrast text,
missing accessible names, prohibited ARIA attributes, missing landmarks, and improper
heading order.
2026-01-05 16:14:37 +01:00
4a8e6c6600 fix: use correct short_name for base recipe links in English and edit pages
All checks were successful
CI / update (push) Successful in 1m11s
- Use English short_name for base recipe links when viewing English recipes
- Fix edit page to use /rezepte/edit/<shortname> instead of /{data.lang}/edit/<shortname>
- Ensures base recipe reference links work correctly in both languages
2026-01-05 00:01:35 +01:00
8eacf1f5d0 fix: enable nested base recipe references to display correctly
All checks were successful
CI / update (push) Successful in 1m10s
- Add recursive population for nested base recipe references (up to 3 levels deep) in API endpoints
- Implement recursive mapping of baseRecipeRef to resolvedRecipe for all nesting levels
- Add recursive flattening functions in frontend components to handle nested references
- Fix TranslationApproval to use short_name instead of ObjectId for base recipe lookups
- Add circular reference detection to prevent infinite loops

This ensures that when Recipe A references Recipe B as a base, and Recipe B references Recipe C, all three recipes' content is properly displayed.
2026-01-04 23:41:53 +01:00
8a152c5fb2 feat: add comprehensive base recipe translation support
- Add language prop to CreateIngredientList and CreateStepList components
  - Support both 'de' and 'en' with translation dictionaries
  - All UI labels now respect the lang prop

- Implement syncBaseRecipeReferences() in TranslationApproval
  - Always runs on component mount (not just for new translations)
  - Fetches English names for base recipe references
  - Merges German structure with existing English translations
  - Preserves existing translations while adding new base recipe refs

- Enhance partial translation in translation.ts
  - Handle base recipe reference fields (itemsBefore/itemsAfter, stepsBefore/stepsAfter)
  - Detect changes using JSON comparison
  - Only re-translate fields that changed
  - Ensures additional items/steps in base recipe refs are preserved during updates
2026-01-04 22:25:34 +01:00
1d4daf11ad refactor: use CreateIngredientList and CreateStepList in translation approval UI
Replaced the plain EditableIngredients and EditableInstructions components
with the styled CreateIngredientList and CreateStepList components to match
the German recipe editing UI above:

- Now displays English translation with same styling as German recipe
- Ingredients and instructions shown in familiar two-column layout
- Timing fields (preparation, baking, fermentation, cooking, total_time)
  integrated into CreateStepList component instead of separate fields
- Added getters/setters for add_info object to enable two-way binding
  between CreateStepList edits and editableEnglish data
- Removed redundant field editors for baking/fermentation since they're
  now part of CreateStepList

Translation approval UI now has consistent styling with the rest of the
edit page for a more cohesive user experience.
2026-01-04 21:35:55 +01:00
03df3b0d14 refactor: simplify translation approval UI to single-column layout
Streamlined the translation approval workflow by removing the side-by-side
German/English comparison and focusing on the English translation only:

- TranslationApproval: Removed two-column comparison grid, now shows only
  English translation in single-column layout for cleaner UI
- Added 'Vollständig neu übersetzen' button to TranslationApproval actions
  section (next to Re-translate button as requested)
- Edit page: Removed standalone 'Vollständig neu übersetzen' button from
  submit buttons, now handled within translation approval workflow
- Updated CSS to use simplified .translation-preview and .field-section
  classes instead of grid layout

The German original is still accessible above in the edit form, making
the translation approval process more focused and less cluttered.
2026-01-04 21:30:55 +01:00
95e6d78619 feat: add translation editing support for base recipe reference fields
All checks were successful
CI / update (push) Successful in 1m10s
Enhanced translation approval UI to allow editing translated text in base
recipe references:

- EditableIngredients: Added support for editing labelOverride, itemsBefore,
  and itemsAfter fields with visual distinction for base recipe references
- EditableInstructions: Added support for editing labelOverride, stepsBefore,
  and stepsAfter fields with organized sections
- TranslationApproval: Updated German side to display base recipe reference
  fields (labelOverride, items/steps before/after) in read-only view

Users can now edit all auto-translated fields in base recipe references
including additional ingredients/instructions added before or after the
base recipe content.
2026-01-04 20:54:49 +01:00
7e66445312 fix: ensure base recipe references display correctly in English and auto-translate
All checks were successful
CI / update (push) Successful in 1m11s
Fixed three issues with base recipe translation support:

1. Base recipe content not loading in English - English API endpoint now
   populates baseRecipeRef fields to resolve base recipe data
2. itemsBefore/itemsAfter and stepsBefore/stepsAfter not being detected as
   changed - enhanced change detection to properly track all base recipe
   reference fields for re-translation
3. Base recipe name labels showing German text in English view - display
   components now use translated base recipe names as label fallback
2026-01-04 20:45:52 +01:00
545bd97959 fix: ensure edit modals close properly on Enter and Escape
All checks were successful
CI / update (push) Successful in 1m12s
- Add setTimeout to defer modal.close() to next tick for proper Svelte binding updates
- Add HTMLDialogElement type casting with null checks for modal elements
- Add cancel event handlers to reset state when Escape is pressed
- Ensures modals close reliably when Enter is pressed to submit
- Prevents orphaned state when modals are dismissed with Escape
2026-01-04 15:28:46 +01:00
b67e2434b5 feat: implement base recipe references with customizable ingredients and instructions
Add comprehensive base recipe system allowing recipes to reference other recipes dynamically. References can include custom items before/after the base recipe content and render as unified lists.

Features:
- Mark recipes as base recipes with isBaseRecipe flag
- Insert base recipe references at any position in ingredients/instructions
- Add custom items before/after referenced content (itemsBefore/itemsAfter, stepsBefore/stepsAfter)
- Combined rendering displays all items in single unified lists
- Full edit/remove functionality for additional items with modal reuse
- Empty item validation prevents accidental blank entries
- HTML rendering in section titles for proper <wbr> and &shy; support
- Reference links in section headings with multiplier preservation
- Subtle hover effects (2% scale) on add buttons
- Translation support for all reference fields
- Deletion handling expands references before removing base recipes
2026-01-04 15:21:25 +01:00
2696f09653 feat: add lock icons to restricted links on homepage
All checks were successful
CI / update (push) Successful in 1m10s
Add small lock icons in the top right corner of links that require authentication (streaming, family photos, cloud, shopping, family tree, transmission, documents, and audiobooks). The icons use SVG symbol references for efficient reuse and adapt to dark mode automatically.
2026-01-03 22:49:22 +01:00
efb548511f feat: add untranslated recipes page for recipe admins
All checks were successful
CI / update (push) Successful in 1m9s
Add new page at /rezepte/untranslated for recipe admins to view and manage recipes without approved English translations. Includes translation status tracking, statistics dashboard, and visual badges.

Changes:
- Add API endpoint to fetch recipes without approved translations
- Create untranslated recipes page with auth checks for rezepte_users group
- Add translation status badges to Card component (pending, needs_update, none)
- Add database index on translations.en.translationStatus for performance
- Create layout for /rezepte route with header navigation
- Add "Unübersetzt" link to navigation for authorized users
2026-01-03 20:03:36 +01:00
191a1879d8 fix: sync language selector with browser back/forward navigation
All checks were successful
CI / update (push) Successful in 1m10s
Replace non-reactive window.location.pathname with SvelteKit's reactive $page store to ensure language selector updates when navigating via browser back/forward buttons.
2026-01-03 19:39:15 +01:00
b6eb3d9458 fix: prevent input field overflow on mobile by ensuring equal margins
Adds box-sizing: border-box to all filter inputs after 'all: unset' to ensure padding is included within the 100% width calculation, preventing horizontal overflow and ensuring equal left/right margins on small screens.
2026-01-03 12:58:40 +01:00
9e0e16aa68 fix: restore vertical filter layout on mobile and enhance dropdown shadows
Some checks failed
CI / update (push) Failing after 1m10s
Fixed CSS specificity issue where filter-panel classes were preventing vertical stacking on small screens. Also added drop-shadow to all filter dropdowns for improved visual depth.
2026-01-02 22:03:29 +01:00
626f4b039a feat: add graceful degradation and conditional favorites filter
Add progressive enhancement to hide filter panel when JavaScript is
disabled, and conditionally render favorites filter based on login status.

Search Component:
- Added showFilters state (default false)
- Set showFilters to true in onMount when JS is enabled
- Wrapped FilterPanel in {#if showFilters} for graceful degradation
- Filters hidden without JavaScript, visible with JS

FilterPanel:
- Split grid layout into two variants:
  - with-favorites: 5 columns (120px 120px 1fr 160px 90px)
  - without-favorites: 4 columns (120px 120px 1fr 160px)
- Conditionally render FavoritesFilter only when isLoggedIn
- Apply appropriate class based on login status

FavoritesFilter:
- Simplified template (no internal login check)
- Only rendered when user is logged in via FilterPanel

UX:
- Non-JS browsers: Simple search only, filters gracefully hidden
- Not logged in: 4-column layout without favorites filter
- Logged in: 5-column layout with favorites filter
2026-01-02 21:41:24 +01:00
2f71b13de6 feat: add comprehensive filter UI with chip-based dropdowns
Some checks failed
CI / update (push) Failing after 1m10s
Add advanced filtering with category, tags (multi-select), icon, season,
and favorites filters. All filters use consistent chip-based dropdown UI
with type-to-search functionality.

New Components:
- TagChip.svelte: Reusable chip component with selected/removable states
- CategoryFilter.svelte: Single-select category with chip dropdown
- TagFilter.svelte: Multi-select tags with AND logic and chip dropdown
- IconFilter.svelte: Single-select emoji icon with chip dropdown
- SeasonFilter.svelte: Multi-select months with chip dropdown
- FavoritesFilter.svelte: Toggle for favorites-only filtering
- FilterPanel.svelte: Container with responsive layout and mobile toggle

Search Component:
- Integrated FilterPanel with all filter types
- Added applyNonTextFilters() for category/tags/icon/season/favorites
- Implemented favorites filter logic (recipe.isFavorite check)
- Made tags/icons reload reactively when language changes with $effect
- Updated buildSearchUrl() for comma-separated array parameters
- Passed categories and isLoggedIn props to enable all filters

Server API:
- Both /api/rezepte/search and /api/recipes/search support:
  - Multi-tag AND logic using MongoDB $all operator
  - Multi-season filtering using MongoDB $in operator
  - Backwards compatible with single tag/season parameters
- Updated search page server load to parse tag/season arrays

UI/UX:
- Filters display inline on wide screens with 2rem gap
- Mobile: collapsible with subtle toggle button and slide-down animation
- Chip-based dropdowns appear on focus with filtering as you type
- Selected items display as removable chips below inputs (no background)
- Centered labels on desktop, left-aligned on mobile
- Reduced vertical spacing on mobile (0.3rem gap)
- Max-width constraints: 500px for filters, 600px for panel on mobile
- Consistent naming: "Tags" and "Icon" instead of German translations
2026-01-02 21:30:33 +01:00
903722b335 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.
2026-01-02 20:25:47 +01:00
f22b8d86be feat: reset to selection page when switching language on category/tag pages
Some checks failed
CI / update (push) Has been cancelled
When switching languages on specific category or tag pages, redirect to
the selection page instead of trying to maintain the same category/tag,
since category and tag names differ between languages. Icon pages continue
to swap directly since icons are consistent across languages.
2026-01-02 18:52:08 +01:00
ccf3fd7ea2 implement content-hash based image cache invalidation
Add content-based hashing to recipe images for proper cache invalidation
while maintaining graceful degradation through dual file storage.

Changes:
- Add imageHash utility with SHA-256 content hashing (8-char)
- Update Recipe model to store hashed filenames in images[0].mediapath
- Modify image upload endpoint to save both hashed and unhashed versions
- Update frontend components to use images[0].mediapath with fallback
- Add migration endpoint to hash existing images (production-only)
- Update image delete/rename endpoints to handle both file versions

Images are now stored as:
  - recipe.a1b2c3d4.webp (hashed, cached forever)
  - recipe.webp (unhashed, graceful degradation fallback)

Database stores hashed filename for cache busting, while unhashed
version remains on disk for backward compatibility and manual uploads.
2026-01-02 12:06:56 +01:00