feat(ui): recipe thumbnail su Select Recipe + fit (object-contain) su Gestione Ricette

- /measure/select: aggiunta miniatura 64×64 accanto al nome ricetta
  (object-contain per mantenere l'immagine intera, non croppata).
  Lo schema backend RecipeSummary esponeva solo id/code/name/active:
  aggiunti image_path e description così la card può rendere thumb
  e sottotitolo.
- /maker/recipes: la miniatura passa da object-cover (crop) a
  object-contain (fit), per visualizzare l'intera immagine della
  ricetta senza tagli.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-19 09:24:36 +02:00
parent f1c7a28296
commit 182aa9fa9a
3 changed files with 28 additions and 11 deletions
+2
View File
@@ -51,6 +51,8 @@ class RecipeSummary(BaseModel):
code: str code: str
name: str name: str
active: bool active: bool
image_path: Optional[str] = None
description: Optional[str] = None
class StationWithRecipesResponse(StationResponse): class StationWithRecipesResponse(StationResponse):
@@ -152,11 +152,11 @@
<div class="p-5 sm:p-6"> <div class="p-5 sm:p-6">
<!-- Card Header --> <!-- Card Header -->
<div class="flex flex-col sm:flex-row sm:items-start gap-4 mb-4"> <div class="flex flex-col sm:flex-row sm:items-start gap-4 mb-4">
<!-- Thumbnail --> <!-- Thumbnail (fit, no crop) -->
<template x-if="recipe.image_path"> <template x-if="recipe.image_path">
<div class="w-20 h-20 rounded-lg overflow-hidden bg-[var(--bg-secondary)] border border-[var(--border-color)] shrink-0"> <div class="w-20 h-20 rounded-lg overflow-hidden bg-[var(--bg-secondary)] border border-[var(--border-color)] shrink-0 flex items-center justify-center">
<img :src="'/maker/api/files/' + recipe.image_path" <img :src="'/maker/api/files/' + recipe.image_path"
class="w-full h-full object-cover" class="max-w-full max-h-full object-contain"
loading="lazy" loading="lazy"
onerror="this.parentElement.style.display='none'"> onerror="this.parentElement.style.display='none'">
</div> </div>
@@ -157,15 +157,30 @@
</span> </span>
</div> </div>
<!-- Title + Thumbnail row -->
<div class="flex items-start gap-3 mb-2">
<!-- Thumbnail (fit, no crop) -->
<template x-if="recipe.image_path">
<div class="w-16 h-16 rounded-md overflow-hidden bg-[var(--bg-secondary)] border border-[var(--border-color)] shrink-0 flex items-center justify-center">
<img :src="'/measure/api/files/' + recipe.image_path"
class="max-w-full max-h-full object-contain"
loading="lazy"
onerror="this.parentElement.style.display='none'">
</div>
</template>
<div class="min-w-0 flex-1">
<!-- Recipe Name --> <!-- Recipe Name -->
<h3 class="text-lg font-semibold text-[var(--text-primary)] mb-2 leading-snug" <h3 class="text-lg font-semibold text-[var(--text-primary)] leading-snug"
x-text="recipe.name"> x-text="recipe.name">
</h3> </h3>
<!-- Description --> <!-- Description -->
<p class="text-sm text-[var(--text-secondary)] line-clamp-2 leading-relaxed" <p class="mt-1 text-sm text-[var(--text-secondary)] line-clamp-2 leading-relaxed"
x-text="recipe.description || '{{ _('Nessuna descrizione disponibile') }}'"> x-text="recipe.description || '{{ _('Nessuna descrizione disponibile') }}'">
</p> </p>
</div>
</div>
<!-- Meta Info --> <!-- Meta Info -->
<div class="mt-4 flex items-center gap-3 text-xs text-[var(--text-muted)]"> <div class="mt-4 flex items-center gap-3 text-xs text-[var(--text-muted)]">