feat(recipes): ingrédients hors-catalogue (placeholders) + revue admin #16
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/off-catalog-ingredients"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Contexte
Le catalogue
Ingredientest seedé et fermé : dès qu'un ingrédient manque, la création manuelle bloquait l'utilisateur (IngredientPickersans issue) et l'import perdait silencieusement la ligne (RecipeImportForm→ choisir dans le catalogue ou écarter). Objectif : débloquer le workflow et rendre visible ce qui manque au catalogue.Basé sur
feat/admin-tech-steps(PR #15) — à retarger surmainune fois #15 mergée.Modèle
IngredientgagneisPlaceholder/displayName/createdById/createdAt/reviewedAt(migration20260828140000_ingredient_placeholder, écrite à la main — Postgres indisponible en session). Un placeholder est une ligneIngredientnormale (RecipeIngredientinchangé),key=placeholder:<uuid>, exclue deGET /reference/ingredientset deingredient-matcher.API
recipeIngredientInputSchema:ingredientIdXORplaceholderName(z.string().trim().min(1).max(120)).createRecipeInternal/updateRecipe:resolveIngredientLinescrée les lignes placeholder dans le$transactionde la recette, puisanalytics.recordEvent("ingredient.placeholder_created"). Une ligne placeholder éditée refait l'aller-retour par son id réel (pas de doublon).admin-catalog.{service,routes}.tsmonté/admin/catalog(requireAdmin) :GET /placeholders?reviewed=— regroupés parnormalizePlaceholderName(minuscules + sans accents + ponctuation→espace), un groupe = un manque (recipeCount, recettes-échantillon, orthographes,firstSeenAt).PATCH /placeholders/mark-reviewed— posereviewedAt.POST /placeholders/prune-orphans(+scripts/prune-orphan-placeholders.ts) — supprime les placeholders sans recette.Front
apps/webIngredientPicker: proponAddPlaceholder→ bouton « Ajouter « … » comme ingrédient à compléter » dans l'état vide (formulaire + import).IngredientRow: badge « à compléter », pas de badges allergène/régime.RecipeImportForm: 3ᵉ action « Garder tel quel » sur la liste « à compléter ».ingredient-label.ts—ingredientLabel(ingredient, t)=displayName ?? t(catalog.ingredients.<key>), appliqué aux 7 sites de rendu de libellé.placeholder-ingredient.ts—IngredientViewsynthétique d'une ligne pas encore enregistrée (id0 → soumise enplaceholderName).Front
apps/admin-webPage
/catalogue(navPackageSearch) : liste des manques (à traiter / archive), « Marquer comme traité » par groupe, « Purger les orphelins ».Vérification
pnpm lint✅ ·pnpm -r build✅normalizePlaceholderName4/4 ✅apps/admin-web(catalog.cy.ts+ navadmin-layout) 6/6 ✅apps/web: nouveau scénario placeholder ✅ ;planning/shopping-list/preferences/recipes/recipe-sources19/19 ✅ (1 flake pré-existant sans rapport dansrecipe-form.feature)recipe-placeholder.test.ts,admin-catalog.test.ts) — non exécutées (pas de Postgres en session, comme les suites admin existantes) ;prisma migrate devà lancer à la revue.🤖 Generated with Claude Code
a053371cf1to5cc70d42445cc70d4244toc246a42a77c246a42a77to16f593d5d0