84 lines
2.0 KiB
TypeScript
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 ?? []),
|
|
}
|
|
}
|