Import TheMealDB : "Importer" reste bloqué sans explication pour les ingrédients comptés sans unité (ex. œufs) #5

Closed
opened 2026-08-27 12:49:26 +02:00 by kyuno · 1 comment
Owner

Contexte

En important une recette depuis TheMealDB dont au moins un ingrédient est compté à l'unité sans mot d'unité dans le texte source (ex. "4 Egg Yolks", "2 Egg", "1 onion" — très courant), le bouton "Importer" du formulaire "Revoir l'import" reste indéfiniment désactivé, sans aucun message d'erreur ni indication visuelle de la ligne en cause. L'utilisateur n'a aucun moyen de comprendre pourquoi le formulaire est bloqué, ni de le débloquer (il n'y a pas de champ "unité" vide visible à corriger — voir "Détail" ci-dessous).

Reproduit avec la recette "Flan" (externalId 53322, https://www.themealdb.com/meal/53322), dont les ingrédients "4 Egg Yolks" / "2 Egg" sont bien reconnus comme l'ingrédient "Œuf" mais avec unit: null.

Cause

Deux endroits :

  1. apps/api/src/lib/ingredient-matcher.ts (matchUnit) — n'a aucune valeur de repli quand le texte restant après extraction de la quantité (extractQuantity) ne contient aucun mot d'unité (ex. "4 Egg Yolks" → quantité 4, reste "Egg Yolks" : aucun token ne correspond à une unité du catalogue). Pour un ingrédient dont l'unité est de type COUNT (piece, "unité"), ce cas devrait pouvoir retomber sur piece par défaut plutôt que sur null — une quantité comptée sans mot d'unité explicite (juste "4 œufs") est le cas le plus courant, pas un cas limite.

  2. apps/web/src/features/recipes/RecipeImportForm.tsx:215-223 (canSubmit) — exige unitId !== null pour chaque ligne d'ingrédient résolue avant d'activer "Importer" :

    const canSubmit =
      ...
      ingredientLines.every((line) => Number(line.quantity) > 0 && line.unitId !== null) &&
      ...
    

    Rien dans l'UI (IngredientRow) ne signale visuellement qu'une ligne précise a une unité manquante (pas de bordure/erreur sur le <select> "Choisir une unité"), et aucun message n'explique pourquoi le bouton "Importer" est désactivé — contrairement à la section "Ingrédients à compléter" qui, elle, a un traitement explicite pour les ingrédients non reconnus. Un ingrédient reconnu mais avec unité manquante n'a aucun traitement équivalent.

Reproduction

  1. Se connecter, ouvrir le planning, cliquer "Ajouter une recette" sur un créneau.
  2. Onglet "TheMealDB", sélectionner "Flan" (ou toute recette avec un ingrédient compté à l'unité, ex. "X eggs", "X onions").
  3. Dans "Revoir l'import" : les lignes "Œuf" (x2) affichent "Choisir une unité" (aucune unité pré-sélectionnée), alors que "Sucre"/"Lait" ont bien "g".
  4. Résoudre la section "Ingrédients à compléter" (retirer ou choisir un ingrédient pour "1 vanilla pod" / "To taste Dulce de leche") : le bouton "Importer" reste désactivé quand même, sans aucune explication — même en choisissant manuellement "unité" dans les deux <select> "Œuf", il faut deviner que c'est ça qui bloquait.

Impact

Étant donné que la quasi-totalité des recettes réelles contiennent au moins un ingrédient compté à l'unité (œufs, oignons, gousses d'ail non suivies du mot "clove", etc.), ce bug bloque silencieusement l'import d'une grande partie du catalogue TheMealDB — sans qu'aucun message n'oriente l'utilisateur vers la correction (choisir manuellement "unité" sur la ligne concernée).

Pistes de correction

  • Faire retomber matchUnit (ou son appelant translateRecipeIngredients) sur l'unité piece par défaut quand l'ingrédient matché est de type COUNT et qu'aucune unité n'a pu être extraite du texte.
  • Dans tous les cas, signaler visuellement dans IngredientRow/RecipeImportForm la ou les lignes dont l'unité est manquante (et pourquoi "Importer" est désactivé), au même titre que la section "Ingrédients à compléter" pour les ingrédients non reconnus.

🤖 Filed by Claude Code

## Contexte En important une recette depuis **TheMealDB** dont au moins un ingrédient est compté à l'unité sans mot d'unité dans le texte source (ex. "4 Egg Yolks", "2 Egg", "1 onion" — très courant), le bouton **"Importer"** du formulaire "Revoir l'import" reste **indéfiniment désactivé**, sans aucun message d'erreur ni indication visuelle de la ligne en cause. L'utilisateur n'a aucun moyen de comprendre pourquoi le formulaire est bloqué, ni de le débloquer (il n'y a pas de champ "unité" vide visible à corriger — voir "Détail" ci-dessous). Reproduit avec la recette "Flan" (`externalId` `53322`, https://www.themealdb.com/meal/53322), dont les ingrédients "4 Egg Yolks" / "2 Egg" sont bien reconnus comme l'ingrédient "Œuf" mais avec `unit: null`. ## Cause Deux endroits : 1. **`apps/api/src/lib/ingredient-matcher.ts` (`matchUnit`)** — n'a aucune valeur de repli quand le texte restant après extraction de la quantité (`extractQuantity`) ne contient aucun mot d'unité (ex. `"4 Egg Yolks"` → quantité `4`, reste `"Egg Yolks"` : aucun token ne correspond à une unité du catalogue). Pour un ingrédient dont l'unité est de type `COUNT` (`piece`, "unité"), ce cas devrait pouvoir retomber sur `piece` par défaut plutôt que sur `null` — une quantité comptée sans mot d'unité explicite (juste "4 œufs") est le cas le plus courant, pas un cas limite. 2. **`apps/web/src/features/recipes/RecipeImportForm.tsx:215-223`** (`canSubmit`) — exige `unitId !== null` pour **chaque** ligne d'ingrédient résolue avant d'activer "Importer" : ```ts const canSubmit = ... ingredientLines.every((line) => Number(line.quantity) > 0 && line.unitId !== null) && ... ``` Rien dans l'UI (`IngredientRow`) ne signale visuellement qu'une ligne précise a une unité manquante (pas de bordure/erreur sur le `<select>` "Choisir une unité"), et aucun message n'explique pourquoi le bouton "Importer" est désactivé — contrairement à la section "Ingrédients à compléter" qui, elle, a un traitement explicite pour les ingrédients non reconnus. Un ingrédient reconnu mais avec unité manquante n'a **aucun** traitement équivalent. ## Reproduction 1. Se connecter, ouvrir le planning, cliquer "Ajouter une recette" sur un créneau. 2. Onglet "TheMealDB", sélectionner "Flan" (ou toute recette avec un ingrédient compté à l'unité, ex. "X eggs", "X onions"). 3. Dans "Revoir l'import" : les lignes "Œuf" (x2) affichent "Choisir une unité" (aucune unité pré-sélectionnée), alors que "Sucre"/"Lait" ont bien "g". 4. Résoudre la section "Ingrédients à compléter" (retirer ou choisir un ingrédient pour "1 vanilla pod" / "To taste Dulce de leche") : le bouton "Importer" reste désactivé quand même, sans aucune explication — même en choisissant manuellement "unité" dans les deux `<select>` "Œuf", il faut deviner que c'est ça qui bloquait. ## Impact Étant donné que la quasi-totalité des recettes réelles contiennent au moins un ingrédient compté à l'unité (œufs, oignons, gousses d'ail non suivies du mot "clove", etc.), ce bug bloque silencieusement l'import d'une grande partie du catalogue TheMealDB — sans qu'aucun message n'oriente l'utilisateur vers la correction (choisir manuellement "unité" sur la ligne concernée). ## Pistes de correction - Faire retomber `matchUnit` (ou son appelant `translateRecipeIngredients`) sur l'unité `piece` par défaut quand l'ingrédient matché est de type `COUNT` et qu'aucune unité n'a pu être extraite du texte. - Dans tous les cas, signaler visuellement dans `IngredientRow`/`RecipeImportForm` la ou les lignes dont l'unité est manquante (et pourquoi "Importer" est désactivé), au même titre que la section "Ingrédients à compléter" pour les ingrédients non reconnus. 🤖 Filed by [Claude Code](https://claude.com/claude-code)
kyuno added the
bug
label 2026-08-27 17:37:36 +02:00
kyuno added the
planned
label 2026-09-05 15:48:05 +02:00
kyuno added the
Low
label 2026-09-05 18:52:21 +02:00
Author
Owner

Déjà corrigé sur main — livré par la PR #59 (commit 5d63ff9), qui traite ce ticket sous le n° #53 : "Un ingrédient compté sans mot d'unité dans le texte source (ex. "4 Egg Yolks") laissait l'import bloqué sur "Importer" indéfiniment… matchUnit retombe maintenant sur l'unité générique "piece" quand une quantité a été extraite, et RecipeImportForm/RecipeFormPage surlignent désormais toute ligne dont l'unité manque, avec un message explicite".

État actuel du code :

  • Repli backend — apps/api/src/lib/recipe-matching/recipe-translation.ts : unitId = matchUnit(unitText, …) ?? (quantity !== null ? matchUnit(fallbackCountUnitLabel, …) : null) — une quantité comptée sans mot d'unité retombe sur piece (FALLBACK_COUNT_UNIT_LABEL_BY_LOCALE), plus null.
  • Signal visuel — apps/web/src/features/recipes/ingredients/IngredientRow.tsx : unitMissing → aria-invalid sur le <select>, classe ingredient-row--incomplete (bordure rouge), et <p class="ingredient-row__error">{unitMissingHint}</p> sous la ligne.
  • Explication du bouton désactivé — RecipeImportForm.tsx / RecipeFormPage.tsx : {!canSubmit && hasIngredientMissingUnit && <message>} à côté du bouton "Importer" / "Enregistrer".

Nuance non reprise : le repli s'applique dès qu'une quantité a été extraite, sans le conditionner au type COUNT de l'ingrédient matché (la piste initiale du ticket). Le commentaire de matchUnit's appelant justifie ce choix plus simple ("une quantité comptée sans mot d'unité explicite est le cas le plus courant"). À rouvrir en ticket dédié si le raffinement type-gated est souhaité.

Fermé comme corrigé.

Traité pendant la passe autonome sur les tickets planned — aucune nouvelle PR nécessaire.

Déjà corrigé sur `main` — livré par la PR #59 (commit `5d63ff9`), qui traite ce ticket sous le n° #53 : *"Un ingrédient compté sans mot d'unité dans le texte source (ex. \"4 Egg Yolks\") laissait l'import bloqué sur \"Importer\" indéfiniment… matchUnit retombe maintenant sur l'unité générique \"piece\" quand une quantité a été extraite, et RecipeImportForm/RecipeFormPage surlignent désormais toute ligne dont l'unité manque, avec un message explicite"*. État actuel du code : - **Repli backend** — `apps/api/src/lib/recipe-matching/recipe-translation.ts` : `unitId = matchUnit(unitText, …) ?? (quantity !== null ? matchUnit(fallbackCountUnitLabel, …) : null)` — une quantité comptée sans mot d'unité retombe sur `piece` (`FALLBACK_COUNT_UNIT_LABEL_BY_LOCALE`), plus `null`. - **Signal visuel** — `apps/web/src/features/recipes/ingredients/IngredientRow.tsx` : `unitMissing` → `aria-invalid` sur le `<select>`, classe `ingredient-row--incomplete` (bordure rouge), et `<p class="ingredient-row__error">{unitMissingHint}</p>` sous la ligne. - **Explication du bouton désactivé** — `RecipeImportForm.tsx` / `RecipeFormPage.tsx` : `{!canSubmit && hasIngredientMissingUnit && <message>}` à côté du bouton "Importer" / "Enregistrer". Nuance non reprise : le repli s'applique dès qu'une quantité a été extraite, sans le conditionner au type `COUNT` de l'ingrédient matché (la piste initiale du ticket). Le commentaire de `matchUnit`'s appelant justifie ce choix plus simple ("une quantité comptée sans mot d'unité explicite est le cas le plus courant"). À rouvrir en ticket dédié si le raffinement type-gated est souhaité. Fermé comme corrigé. _Traité pendant la passe autonome sur les tickets `planned` — aucune nouvelle PR nécessaire._
kyuno closed this issue 2026-09-05 22:58:57 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: kyuno/batchCooking#5
No description provided.