Files
Nutrio/frontend/src/utils/nutrition.ts

84 lines
2.0 KiB
TypeScript

import type {
DayMealsByType,
Ingredient,
Meal,
MealItem,
NutritionTotals,
} from '@/types/domain'
const round2 = (value: number): number => Math.round(value * 100) / 100
export const emptyTotals = (): NutritionTotals => ({
protein_g: 0,
carbs_g: 0,
sugar_g: 0,
fat_g: 0,
fiber_g: 0,
kcal: 0,
})
export const computeItemNutrition = (ingredient: Ingredient, grams: number): NutritionTotals => {
const factor = grams / 100
const protein = round2(ingredient.protein_g_100 * factor)
const carbs = round2(ingredient.carbs_g_100 * factor)
const sugar = round2(ingredient.sugar_g_100 * factor)
const fat = round2(ingredient.fat_g_100 * factor)
const fiber = round2(ingredient.fiber_g_100 * factor)
const kcal = round2(protein * 4 + carbs * 4 + fat * 9)
return {
protein_g: protein,
carbs_g: carbs,
sugar_g: sugar,
fat_g: fat,
fiber_g: fiber,
kcal,
}
}
export const addTotals = (base: NutritionTotals, add: NutritionTotals): NutritionTotals => {
return {
protein_g: round2(base.protein_g + add.protein_g),
carbs_g: round2(base.carbs_g + add.carbs_g),
sugar_g: round2(base.sugar_g + add.sugar_g),
fat_g: round2(base.fat_g + add.fat_g),
fiber_g: round2(base.fiber_g + add.fiber_g),
kcal: round2(base.kcal + add.kcal),
}
}
export const computeMealTotals = (items: MealItem[]): NutritionTotals => {
let totals = emptyTotals()
for (const item of items) {
if (!item.ingredient || item.grams <= 0) {
continue
}
const itemTotals = computeItemNutrition(item.ingredient, item.grams)
totals = addTotals(totals, itemTotals)
}
return totals
}
export const computeDayTotals = (mealsByType: Partial<DayMealsByType>): NutritionTotals => {
let totals = emptyTotals()
for (const meal of Object.values(mealsByType)) {
if (!meal) {
continue
}
const mealTotals = computeMealTotals(meal.items ?? [])
totals = addTotals(totals, mealTotals)
}
return totals
}
export const withComputedMealTotals = (meal: Meal): Meal => {
return {
...meal,
totals: computeMealTotals(meal.items ?? []),
}
}