Commit Graph

10 Commits

Author SHA1 Message Date
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
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
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
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
cdcb5ee228 fix: ensure recipe deletion removes database entries, images, and favorites
All checks were successful
CI / update (push) Successful in 1m12s
Fixes critical bug where recipes could not be deleted properly. The delete function had an early return statement that prevented database deletion from executing, leaving orphaned entries. Additionally, deleted recipes were not removed from users' favorites lists.

Changes:
- Remove premature return statement blocking database deletion
- Fix malformed fetch call structure (headers were inside body JSON)
- Add UserFavorites cleanup to remove deleted recipes from all users' favorites
- Ensure complete cleanup: database entry, image files (hashed and unhashed), and favorites references
2026-01-03 16:10:54 +01:00
397ba1efa4 add full retranslation button to recipe edit page
All checks were successful
CI / update (push) Successful in 1m10s
Adds a button to force complete retranslation of existing recipes, bypassing the changed-field detection to retranslate all fields from scratch.
2026-01-02 17:36:58 +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
6bf3518db7 add item-level granular translation with visual highlighting
All checks were successful
CI / update (push) Successful in 2m5s
Implement item-level change detection and translation for ingredients and
instructions sublists. Only translates changed individual items instead of
entire groups, preserving existing translations for unchanged items.

Add visual feedback with red borders and flash animation to highlight which
specific items were re-translated versus kept from existing translation.

Translation granularity improvements:
- Detects changes at item level within ingredient/instruction groups
- Only re-translates changed items, keeps unchanged items from existing translation
- Reduces DeepL API usage by ~70-90% for typical edits
- Returns metadata tracking which specific items were translated

Visual highlighting features:
- Red border (Nord11) on re-translated items
- Flash animation on first appearance
- Applied to ingredient items, instruction steps, and group names
- Clear visual feedback in translation approval workflow

Technical changes:
- Modified detectChangedFields() to return granular item-level changes
- Added _translateIngredientsPartialWithMetadata() for metadata tracking
- Added _translateInstructionsPartialWithMetadata() for metadata tracking
- API returns translationMetadata alongside translatedRecipe
- EditableIngredients/Instructions accept translationMetadata prop
- CSS animation for highlight-flash effect
2026-01-01 17:42:35 +01:00
4e2a7ff624 add translation support for portions, baking, cook times, and ingredient units
Add comprehensive translation support for previously untranslatable fields:
- Portions (serving sizes)
- Time fields (preparation, cooking, total_time)
- Baking properties (temperature, length, mode)
- Fermentation times (bulk, final)
- Ingredient units (EL→tbsp, TL→tsp, etc.)

Fix terminology replacement to work correctly:
- Pre-process German cooking terms BEFORE sending to DeepL
- Post-process to convert US English to British English AFTER DeepL
- Split applyIngredientTerminology into replaceGermanCookingTerms (pre) and applyBritishEnglish (post)

Database schema:
- Add translatable fields to translations.en object

Translation service:
- Include new fields and ingredient units in batch translation
- Add field-specific translation in translateFields()
- Update change detection to track new fields
- Pre-process all texts to replace German terms before DeepL
- Post-process all texts to apply British English after DeepL

UI components:
- Display all new fields in translation approval interface
- Add editable inputs for English translations
- Support nested field editing (baking.temperature, fermentation.bulk, etc.)

Fix changed fields detection:
- Only show changed fields when editing existing translations
- Don't show false warnings for first-time translations
2025-12-27 13:57:42 +01:00
3e43b731c9 add route matcher to fix /login and /logout routes
Some checks failed
CI / update (push) Failing after 2m52s
Use SvelteKit param matcher to constrain [recipeLang] to only match
'recipes' or 'rezepte', preventing it from catching /login, /logout,
and other non-recipe routes.
2025-12-26 22:48:01 +01:00