Files
Cibello-app/packages/recipe-engine/src/substitution.ts
T
2026-08-05 19:21:11 +07:00

70 lines
2.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { Substitution, Unit } from "@app/shared-types";
export interface SubstitutableIngredient {
canonicalIngredientId: string;
displayNameSv: string;
quantity: number;
unit: Unit;
optional: boolean;
}
export interface SubstitutionResult {
ingredients: SubstitutableIngredient[];
applied: {
fromId: string;
toId: string;
ratio: number;
instructionsSv?: string | undefined;
warningSv?: string | undefined;
};
}
/**
* Substitutionsmotor (spec §20): byt ingrediens med mängdfaktor och
* instruktionspåverkan. Näringen räknas ALLTID om av nutrition-engine efteråt
* denna modul ändrar bara ingredienslistan.
*/
export function applySubstitution(
ingredients: SubstitutableIngredient[],
substitution: Pick<
Substitution,
"fromIngredientId" | "toIngredientId" | "ratio" | "instructionsSv" | "notRecommendedFor"
>,
toDisplayNameSv: string,
context?: string,
): SubstitutionResult {
const target = ingredients.find((i) => i.canonicalIngredientId === substitution.fromIngredientId);
if (!target) {
throw new Error(
`Ingrediensen ${substitution.fromIngredientId} finns inte i receptet och kan inte bytas.`,
);
}
let warningSv: string | undefined;
if (context && substitution.notRecommendedFor.includes(context)) {
warningSv = `Observera: detta byte rekommenderas inte för ${context}.`;
}
const next = ingredients.map((ing) =>
ing.canonicalIngredientId === substitution.fromIngredientId
? {
...ing,
canonicalIngredientId: substitution.toIngredientId,
displayNameSv: toDisplayNameSv,
quantity: Math.round(ing.quantity * substitution.ratio * 100) / 100,
}
: ing,
);
return {
ingredients: next,
applied: {
fromId: substitution.fromIngredientId,
toId: substitution.toIngredientId,
ratio: substitution.ratio,
instructionsSv: substitution.instructionsSv ?? undefined,
warningSv,
},
};
}