Remplace la FK morte `Ingredient.alternateRecipeId` (jamais branchée nulle part — confirmé par exploration : zéro usage en dehors de schema.prisma) par un flag booléen `reproducible`, plus simple : pas de liaison recette↔ingrédient en base, juste une info "ça vaut le coup d'être fait maison" plus un raccourci de recherche. - Migration : drop `alternate_recipe` (colonne + FK), ajoute `reproducible BOOLEAN NOT NULL DEFAULT false` sur `ingredients`. - `reference-seed-data.ts` : `IngredientSeed` gagne `reproducible?`, threadé dans le flatten + la réconciliation `seedReferenceData`. Premier lot de 27 ingrédients marqués (pains, pâtes à cuire, sauces de base, bouillons/fonds) — même logique que la curation Ciqual : un lot solide plutôt qu'exhaustif sur les 546 ingrédients. - `IngredientView` (shared) + les deux endroits qui la construisent (`reference.service.ts`, `recipe.service.ts`) gagnent `reproducible`. - `ReproducibleBadge` (nouveau) : pastille "Faisable maison" — simple dans `IngredientPicker` (avec son propre toggle d'affichage), lien cliquable dans `IngredientRow` vers `/recettes?search=<nom>` ouvert dans un nouvel onglet (pour ne jamais perdre le formulaire de recette en cours — pas de persistance de brouillon dans `RecipeFormPage`). - `RecipesPage` lit `?search=` au montage pour permettre ce deep-link. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
64 lines
2.5 KiB
TypeScript
64 lines
2.5 KiB
TypeScript
import type { AllergyView, DietView, IngredientView } from "@batch-cooking/shared";
|
|
import { prisma } from "../../db/prisma.js";
|
|
|
|
/**
|
|
* All reference dietary regimes, ordered by `key` — small, static list (see
|
|
* prisma/seed.ts). `key` is a stable slug, not the display label (see
|
|
* {@link DietView}), so this is an alphabetical-by-slug order rather than a
|
|
* true French alphabetical one — close enough for a 5-item list, and the
|
|
* server has no other order to offer now that the label itself only exists
|
|
* client-side (`apps/web`'s `locales/fr/translation.json`).
|
|
*/
|
|
export async function getDiets(): Promise<DietView[]> {
|
|
return prisma.diet.findMany({ orderBy: { key: "asc" } });
|
|
}
|
|
|
|
/**
|
|
* All reference allergens, ordered by key (see {@link getDiets} for why key,
|
|
* not label). `Allergy` carries no `key` of its own — it's the selectable
|
|
* instance of a keyed `Category` (see schema.prisma) — so this resolves
|
|
* each allergen's key from its category and flattens the split away for
|
|
* callers.
|
|
*/
|
|
export async function getAllergies(): Promise<AllergyView[]> {
|
|
const allergies = await prisma.allergy.findMany({
|
|
include: { category: { select: { key: true, kind: true } } },
|
|
orderBy: { category: { key: "asc" } },
|
|
});
|
|
return allergies.map((allergy) => ({
|
|
id: allergy.id,
|
|
key: allergy.category.key,
|
|
kind: allergy.category.kind,
|
|
}));
|
|
}
|
|
|
|
/**
|
|
* All reference ingredients, ordered by key (see {@link getDiets} for why),
|
|
* each resolved to its allergens (see `IngredientAllergy` in schema.prisma)
|
|
* and compatible diet regimes (see `IngredientDiet`) — same flattening
|
|
* approach as {@link getAllergies}. Ingredients with no linked
|
|
* allergen/diet come back with `allergens: []`/`diets: []`.
|
|
*/
|
|
export async function getIngredients(): Promise<IngredientView[]> {
|
|
const ingredients = await prisma.ingredient.findMany({
|
|
include: {
|
|
allergies: { include: { allergy: { include: { category: true } } } },
|
|
diets: { include: { diet: true } },
|
|
},
|
|
orderBy: { key: "asc" },
|
|
});
|
|
return ingredients.map((ingredient) => ({
|
|
id: ingredient.id,
|
|
key: ingredient.key,
|
|
icon: ingredient.icon,
|
|
category: ingredient.category,
|
|
subcategory: ingredient.subcategory,
|
|
reproducible: ingredient.reproducible,
|
|
allergens: ingredient.allergies.map(({ allergy }) => ({
|
|
id: allergy.id,
|
|
key: allergy.category.key,
|
|
kind: allergy.category.kind,
|
|
})),
|
|
diets: ingredient.diets.map(({ diet }) => ({ id: diet.id, key: diet.key })),
|
|
}));
|
|
}
|