* Extended functionalities
* Added different UIs
This commit is contained in:
65
meal-plan-frontend/src/utils/recipe-macros.util.ts
Normal file
65
meal-plan-frontend/src/utils/recipe-macros.util.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import type { IngredientNutritionItem } from "@/types/ingredient-catalog.types";
|
||||
|
||||
export interface MacroTotals {
|
||||
calories: number;
|
||||
protein: number;
|
||||
fat: number;
|
||||
carbs: number;
|
||||
}
|
||||
|
||||
export interface MacroIngredientInput {
|
||||
catalogItemId?: number | null;
|
||||
amountGrams?: number | null;
|
||||
unit?: string | null;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export function hasNonMacroUnit(unit?: string | null): boolean {
|
||||
if (!unit?.trim()) return false;
|
||||
const u = unit.trim().toLowerCase();
|
||||
return u === "do smaku" || u === "optional" || u === "opcjonalnie" || u === "szczypta";
|
||||
}
|
||||
|
||||
export function shouldIncludeIngredientInMacroSum(ing: MacroIngredientInput): boolean {
|
||||
return Boolean(
|
||||
ing.catalogItemId && ing.amountGrams != null && ing.amountGrams > 0 && !hasNonMacroUnit(ing.unit),
|
||||
);
|
||||
}
|
||||
|
||||
export function isUnlinkedMacroIngredient(ing: MacroIngredientInput): boolean {
|
||||
if (!ing.name?.trim()) return false;
|
||||
if (hasNonMacroUnit(ing.unit)) return false;
|
||||
return Boolean(ing.amountGrams != null && ing.amountGrams > 0 && !ing.catalogItemId);
|
||||
}
|
||||
|
||||
export function countUnlinkedMacroIngredients(ingredients: MacroIngredientInput[]): number {
|
||||
return ingredients.filter(isUnlinkedMacroIngredient).length;
|
||||
}
|
||||
|
||||
export function estimateMacrosFromCatalog(
|
||||
ingredients: MacroIngredientInput[],
|
||||
catalogItems: Pick<
|
||||
IngredientNutritionItem,
|
||||
"id" | "caloriesPer100G" | "proteinGPer100G" | "fatGPer100G" | "carbsGPer100G"
|
||||
>[],
|
||||
): MacroTotals | null {
|
||||
let calories = 0;
|
||||
let protein = 0;
|
||||
let fat = 0;
|
||||
let carbs = 0;
|
||||
let hasAny = false;
|
||||
|
||||
for (const ing of ingredients) {
|
||||
if (!shouldIncludeIngredientInMacroSum(ing)) continue;
|
||||
const cat = catalogItems.find((c) => c.id === ing.catalogItemId);
|
||||
if (!cat) continue;
|
||||
const scale = Number(ing.amountGrams) / 100;
|
||||
calories += Math.round(cat.caloriesPer100G * scale);
|
||||
protein += cat.proteinGPer100G * scale;
|
||||
fat += cat.fatGPer100G * scale;
|
||||
carbs += cat.carbsGPer100G * scale;
|
||||
hasAny = true;
|
||||
}
|
||||
|
||||
return hasAny ? { calories, protein, fat, carbs } : null;
|
||||
}
|
||||
Reference in New Issue
Block a user