fix: variations/adapt-recipe silent errors and no-op duplicates
AI adapt/variations flows had no catch on their fetch calls, so a network failure surfaced as nothing happening rather than an error toast. They also unconditionally persisted the AI's output even when it was identical to the source recipe, and the adapt route never recorded a recipeVariations row (only plain forks did) or enforced the per-tier recipe-count limit other create paths already check. v0.39.0
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
type DiffIngredient = { rawName: string; quantity?: string | number | null; unit?: string | null };
|
||||
type DiffStep = { instruction: string };
|
||||
|
||||
const norm = (s: string) => s.trim().toLowerCase();
|
||||
|
||||
/** True if an AI-adapted/varied recipe is functionally identical to its
|
||||
* source — same servings, same ingredients (name/quantity/unit, in order),
|
||||
* same steps. Used to skip persisting a "variation" that changed nothing,
|
||||
* which otherwise clutters recipe history with no-op duplicates. */
|
||||
export function isRecipeUnchanged(
|
||||
original: { baseServings: number; ingredients: DiffIngredient[]; steps: DiffStep[] },
|
||||
candidate: { baseServings: number; ingredients: DiffIngredient[]; steps: DiffStep[] }
|
||||
): boolean {
|
||||
if (original.baseServings !== candidate.baseServings) return false;
|
||||
if (original.ingredients.length !== candidate.ingredients.length) return false;
|
||||
if (original.steps.length !== candidate.steps.length) return false;
|
||||
|
||||
for (let i = 0; i < original.ingredients.length; i++) {
|
||||
const o = original.ingredients[i]!;
|
||||
const c = candidate.ingredients[i]!;
|
||||
if (norm(o.rawName) !== norm(c.rawName)) return false;
|
||||
if (String(o.quantity ?? "") !== String(c.quantity ?? "")) return false;
|
||||
if (norm(o.unit ?? "") !== norm(c.unit ?? "")) return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < original.steps.length; i++) {
|
||||
if (norm(original.steps[i]!.instruction) !== norm(candidate.steps[i]!.instruction)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user