Répond à deux besoins : permettre à chaque foyer de choisir quelles sources apparaissent dans ses onglets de recettes, et distinguer les sources à API officielle des sources scrapées. - RecipeSourceAdapter.official (booléen, sans défaut — chaque adaptateur doit le déclarer explicitement) synchronisé sur Source.official par syncRecipeSources. - HouseSource : table de jointure opt-in (House <-> Source) — aucune ligne = source masquée. Un foyer nouvellement créé ne voit aucune source tant qu'il ne les active pas explicitement. - GET /reference/sources (catalogue des sources implémentées, avec le flag officiel). - GET/PATCH /house/current/sources (lecture/remplacement complet des sources activées par le foyer courant). - recipe.service.ts : sourceVisibilityWhere() filtre désormais TOUS les onglets (perso/foyer/publique/favoris) — une recette sans source reste toujours visible ; une recette importée ne l'est que si sa source est activée pour le foyer du viewer. Un viewer sans foyer ne voit aucune recette sourcée. Côté web : - Nouvelle étape /onboarding/sources dans le wizard d'inscription, atteinte uniquement si un foyer vient d'être créé/rejoint (sinon on saute direct aux allergènes) ; s'auto-saute aussi si aucune source n'est encore implémentée (catalogue vide aujourd'hui). - Nouvelle section « Sources de recettes » dans /parametres/foyer (masquée dans les mêmes conditions), avec sauvegarde à la volée (même pattern que les autres préférences hot-saved). - SourceSelect (features/house/), grille de cases à cocher avec badge officiel/non-officielle, sur le même principe qu'AllergySelect. 172 tests backend passent (dont 25 nouveaux). Build et lint propres. Vérifié manuellement en navigateur : le parcours d'onboarding saute bien l'étape sources (catalogue vide) et affiche « 4 sur 4 » quand un foyer a été créé ; la section paramètres reste invisible tant qu'aucune source n'existe. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
63 lines
1.6 KiB
TypeScript
63 lines
1.6 KiB
TypeScript
import { wrapAsyncHandler } from "@batch-cooking/express-tools";
|
|
import { Router } from "express";
|
|
import {
|
|
getAllergies,
|
|
getDiets,
|
|
getIngredients,
|
|
getSources,
|
|
getTechSteps,
|
|
getUnits,
|
|
} from "./reference.service.js";
|
|
|
|
/**
|
|
* Router mounted at `/reference` in app.ts. Every route is deliberately
|
|
* public (no `requireAuth`) — this is static reference data, not
|
|
* per-household state, and the signup wizard (household/regime/allergen
|
|
* steps) needs to read it before an account — and therefore a session —
|
|
* exists. `/ingredients` follows the same reasoning even though it's only
|
|
* consumed post-login (the recipe catalog) — it's still non-administrable
|
|
* reference data, no reason to require a session to read it.
|
|
*/
|
|
export const referenceRouter = Router();
|
|
|
|
referenceRouter.get(
|
|
"/diets",
|
|
wrapAsyncHandler(async (_req, res) => {
|
|
res.status(200).json(await getDiets());
|
|
}),
|
|
);
|
|
|
|
referenceRouter.get(
|
|
"/allergies",
|
|
wrapAsyncHandler(async (_req, res) => {
|
|
res.status(200).json(await getAllergies());
|
|
}),
|
|
);
|
|
|
|
referenceRouter.get(
|
|
"/ingredients",
|
|
wrapAsyncHandler(async (_req, res) => {
|
|
res.status(200).json(await getIngredients());
|
|
}),
|
|
);
|
|
|
|
referenceRouter.get(
|
|
"/units",
|
|
wrapAsyncHandler(async (_req, res) => {
|
|
res.status(200).json(await getUnits());
|
|
}),
|
|
);
|
|
|
|
referenceRouter.get(
|
|
"/tech-steps",
|
|
wrapAsyncHandler(async (_req, res) => {
|
|
res.status(200).json(await getTechSteps());
|
|
}),
|
|
);
|
|
|
|
referenceRouter.get(
|
|
"/sources",
|
|
wrapAsyncHandler(async (_req, res) => {
|
|
res.status(200).json(await getSources());
|
|
}),
|
|
);
|