Files
recipe-mockup/js/data/catalog.js
ulfrxdev 855d17374e
All checks were successful
Build and Deploy / build-and-push (push) Successful in 26s
Fix calculating nutritions
2026-03-27 23:08:54 +01:00

491 lines
19 KiB
JavaScript
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.
/**
* Katalog składników i przepisów — odpowiednik tabel w DB (edycja poza aplikacją).
* pantryUnit: jednostka magazynowa / sumowania na liście zakupów (g, ml, szt.).
* purchasePack: minimalna „sztuka” ze sklepu w tej samej jednostce co pantryUnit (np. 200 g).
* nutritionPer100g — wartości szacunkowe na 100 g (dla płynów: traktuj ml≈g przy wodzie).
*/
export const CATEGORY_LABELS = {
pieczywo: 'Pieczywo',
nabial: 'Nabiał',
mieso_ryby: 'Mięso i ryby',
warzywa: 'Warzywa',
owoce: 'Owoce',
suche: 'Suche i kasze',
przyprawy: 'Przyprawy i zioła',
inne: 'Inne',
};
/**
* @typedef {{ kcal: number, protein: number, fat: number, carbs: number }} NutritionPer100
* @typedef {{ amount: number, label?: string }} PurchasePack
* @typedef {{ id: string, name: string, category: keyof typeof CATEGORY_LABELS, pantryUnit: 'g'|'ml'|'szt', purchasePack?: PurchasePack, nutritionPer100g?: NutritionPer100 }} IngredientDef
*/
/** @type {Record<string, IngredientDef>} */
export const INGREDIENTS = {
/* ── Pieczywo ─────────────────────────────────────── */
bulka_grahamka: {
id: 'bulka_grahamka',
name: 'Bułka grahamka',
category: 'pieczywo',
pantryUnit: 'szt',
weightPerPiece: 70,
purchasePack: { amount: 1, label: '1 bułka ~70 g' },
nutritionPer100g: { kcal: 260, protein: 9, fat: 3, carbs: 48 },
},
/* ── Nabiał ───────────────────────────────────────── */
jajko: {
id: 'jajko',
name: 'Jajka',
category: 'nabial',
pantryUnit: 'szt',
weightPerPiece: 60,
nutritionPer100g: { kcal: 143, protein: 13, fat: 9.5, carbs: 1.1 },
},
mozzarella: {
id: 'mozzarella',
name: 'Mozzarella',
category: 'nabial',
pantryUnit: 'g',
purchasePack: { amount: 125, label: 'kulka 125 g' },
nutritionPer100g: { kcal: 280, protein: 22, fat: 20, carbs: 2 },
},
ricotta: {
id: 'ricotta',
name: 'Ricotta',
category: 'nabial',
pantryUnit: 'g',
purchasePack: { amount: 250, label: 'opakowanie 250 g' },
nutritionPer100g: { kcal: 174, protein: 11, fat: 13, carbs: 3 },
},
serek_wiejski: {
id: 'serek_wiejski',
name: 'Serek wiejski',
category: 'nabial',
pantryUnit: 'g',
purchasePack: { amount: 200, label: 'opakowanie 200 g' },
nutritionPer100g: { kcal: 97, protein: 11, fat: 5, carbs: 3 },
},
serek_smietankowy: {
id: 'serek_smietankowy',
name: 'Serek śmietankowy',
category: 'nabial',
pantryUnit: 'g',
purchasePack: { amount: 150, label: 'opakowanie 150 g' },
nutritionPer100g: { kcal: 230, protein: 6, fat: 21, carbs: 4 },
},
/* ── Mięso i ryby ─────────────────────────────────── */
szynka_parmenska: {
id: 'szynka_parmenska',
name: 'Szynka parmeńska',
category: 'mieso_ryby',
pantryUnit: 'g',
purchasePack: { amount: 100, label: 'opakowanie 100 g' },
nutritionPer100g: { kcal: 250, protein: 28, fat: 15, carbs: 0 },
},
szynka_z_kurczaka: {
id: 'szynka_z_kurczaka',
name: 'Szynka z kurczaka',
category: 'mieso_ryby',
pantryUnit: 'g',
purchasePack: { amount: 100, label: 'opakowanie 100 g' },
nutritionPer100g: { kcal: 105, protein: 19.5, fat: 2, carbs: 1.5 },
},
losos_wedzony: {
id: 'losos_wedzony',
name: 'Łosoś wędzony',
category: 'mieso_ryby',
pantryUnit: 'g',
purchasePack: { amount: 100, label: 'opakowanie 100 g' },
nutritionPer100g: { kcal: 150, protein: 20, fat: 7, carbs: 0 },
},
/* ── Warzywa ──────────────────────────────────────── */
pomidor: {
id: 'pomidor',
name: 'Pomidor',
category: 'warzywa',
pantryUnit: 'szt',
weightPerPiece: 130,
nutritionPer100g: { kcal: 18, protein: 0.9, fat: 0.2, carbs: 3.9 },
},
pomidorki_koktajlowe: {
id: 'pomidorki_koktajlowe',
name: 'Pomidorki koktajlowe',
category: 'warzywa',
pantryUnit: 'g',
purchasePack: { amount: 250, label: 'opakowanie 250 g' },
nutritionPer100g: { kcal: 18, protein: 0.9, fat: 0.2, carbs: 3.9 },
},
papryka_czerwona: {
id: 'papryka_czerwona',
name: 'Papryka czerwona',
category: 'warzywa',
pantryUnit: 'szt',
weightPerPiece: 160,
nutritionPer100g: { kcal: 31, protein: 1, fat: 0.3, carbs: 6 },
},
ogorek: {
id: 'ogorek',
name: 'Ogórek',
category: 'warzywa',
pantryUnit: 'szt',
weightPerPiece: 200,
nutritionPer100g: { kcal: 15, protein: 0.7, fat: 0.1, carbs: 3 },
},
czosnek: {
id: 'czosnek',
name: 'Czosnek',
category: 'warzywa',
pantryUnit: 'szt',
weightPerPiece: 35,
nutritionPer100g: { kcal: 149, protein: 6.4, fat: 0.5, carbs: 33 },
},
kielki_rzodkiewki: {
id: 'kielki_rzodkiewki',
name: 'Kiełki rzodkiewki',
category: 'warzywa',
pantryUnit: 'g',
nutritionPer100g: { kcal: 28, protein: 3, fat: 0.6, carbs: 3.5 },
},
/* ── Owoce ────────────────────────────────────────── */
truskawki: {
id: 'truskawki',
name: 'Truskawki',
category: 'owoce',
pantryUnit: 'g',
nutritionPer100g: { kcal: 32, protein: 0.7, fat: 0.3, carbs: 8 },
},
borowki_amerykanskie: {
id: 'borowki_amerykanskie',
name: 'Borówki amerykańskie',
category: 'owoce',
pantryUnit: 'g',
nutritionPer100g: { kcal: 57, protein: 0.7, fat: 0.3, carbs: 14 },
},
banany: {
id: 'banany',
name: 'Banany',
category: 'owoce',
pantryUnit: 'g',
nutritionPer100g: { kcal: 89, protein: 1.1, fat: 0.3, carbs: 23 },
},
jagody: {
id: 'jagody',
name: 'Jagody',
category: 'owoce',
pantryUnit: 'g',
nutritionPer100g: { kcal: 44, protein: 0.7, fat: 0.4, carbs: 10 },
},
/* ── Suche i kasze ────────────────────────────────── */
makaron_suchy: {
id: 'makaron_suchy',
name: 'Makaron',
category: 'suche',
pantryUnit: 'g',
nutritionPer100g: { kcal: 371, protein: 13, fat: 1.5, carbs: 74 },
},
nasiona_slonecznika: {
id: 'nasiona_slonecznika',
name: 'Nasiona słonecznika',
category: 'suche',
pantryUnit: 'g',
nutritionPer100g: { kcal: 584, protein: 21, fat: 51, carbs: 20 },
},
orzechy_wloskie: {
id: 'orzechy_wloskie',
name: 'Orzechy włoskie',
category: 'suche',
pantryUnit: 'g',
nutritionPer100g: { kcal: 654, protein: 15, fat: 65, carbs: 14 },
},
orzechy_laskowe: {
id: 'orzechy_laskowe',
name: 'Orzechy laskowe',
category: 'suche',
pantryUnit: 'g',
nutritionPer100g: { kcal: 628, protein: 15, fat: 61, carbs: 17 },
},
orzechy_nerkowca: {
id: 'orzechy_nerkowca',
name: 'Orzechy nerkowca',
category: 'suche',
pantryUnit: 'g',
nutritionPer100g: { kcal: 553, protein: 18, fat: 44, carbs: 30 },
},
migdaly: {
id: 'migdaly',
name: 'Migdały',
category: 'suche',
pantryUnit: 'g',
nutritionPer100g: { kcal: 579, protein: 21, fat: 50, carbs: 22 },
},
orzechy_pekan: {
id: 'orzechy_pekan',
name: 'Orzechy pekan',
category: 'suche',
pantryUnit: 'g',
nutritionPer100g: { kcal: 691, protein: 9, fat: 72, carbs: 14 },
},
/* ── Przyprawy i zioła ────────────────────────────── */
bazylia_swieza: {
id: 'bazylia_swieza',
name: 'Bazylia świeża',
category: 'przyprawy',
pantryUnit: 'g',
nutritionPer100g: { kcal: 23, protein: 3.2, fat: 0.6, carbs: 2.7 },
},
koper_swiezy: {
id: 'koper_swiezy',
name: 'Koper',
category: 'przyprawy',
pantryUnit: 'g',
nutritionPer100g: { kcal: 43, protein: 3.5, fat: 1.1, carbs: 7 },
},
szczypiorek: {
id: 'szczypiorek',
name: 'Szczypiorek',
category: 'przyprawy',
pantryUnit: 'g',
nutritionPer100g: { kcal: 30, protein: 3.3, fat: 0.7, carbs: 1.8 },
},
tymianek: {
id: 'tymianek',
name: 'Tymianek suszony',
category: 'przyprawy',
pantryUnit: 'g',
nutritionPer100g: { kcal: 276, protein: 9, fat: 7, carbs: 45 },
},
chrzan: {
id: 'chrzan',
name: 'Chrzan tarty',
category: 'przyprawy',
pantryUnit: 'g',
nutritionPer100g: { kcal: 44, protein: 1, fat: 0.5, carbs: 8 },
},
/* ── Inne ─────────────────────────────────────────── */
miod: {
id: 'miod',
name: 'Miód',
category: 'inne',
pantryUnit: 'g',
nutritionPer100g: { kcal: 304, protein: 0.3, fat: 0, carbs: 82 },
},
oliwa: {
id: 'oliwa',
name: 'Oliwa z oliwek',
category: 'inne',
pantryUnit: 'ml',
nutritionPer100g: { kcal: 884, protein: 0, fat: 100, carbs: 0 },
},
hummus: {
id: 'hummus',
name: 'Hummus',
category: 'inne',
pantryUnit: 'g',
purchasePack: { amount: 200, label: 'opakowanie 200 g' },
nutritionPer100g: { kcal: 166, protein: 8, fat: 10, carbs: 14 },
},
};
/** Porcja bazowa = 1; składniki przez ingredientId */
export const RECIPES = {
kanapka_parmenska: {
id: 'kanapka_parmenska',
title: 'Kanapka z szynką parmeńską i mozzarellą',
description: 'Bułka grahamka z szynką parmeńską, mozzarellą i pomidorkami — włoskie smaki na szybko.',
minutes: 5,
thumbLabel: 'Parmeńska',
image: 'images/recipes/kanapka_parmenska.jpg',
allowedSlots: ['sniadanie', 'drugie_sniadanie', 'kolacja'],
tags: ['szybkie'],
nutritionPerServing: { kcal: 606, protein: 47, fat: 29, carbs: 39 },
ingredients: [
{ ingredientId: 'bulka_grahamka', amount: 1, unit: 'szt.' },
{ ingredientId: 'szynka_parmenska', amount: 95, unit: 'g' },
{ ingredientId: 'mozzarella', amount: 60, unit: 'g' },
{ ingredientId: 'pomidorki_koktajlowe', amount: 100, unit: 'g' },
],
steps: [
'Bułkę grahamkę przekrój na pół.',
'Na bułce ułóż plastry szynki parmeńskiej, na nią pokrojoną mozzarellę.',
'Podawaj z pomidorkami koktajlowymi.',
],
},
makaron_ricotta: {
id: 'makaron_ricotta',
title: 'Makaron z ricottą i pomidorami',
description: 'Makaron z sosem z pieczonych pomidorków koktajlowych, ricottą i słonecznikiem.',
minutes: 20,
thumbLabel: 'Ricotta',
image: 'images/recipes/makaron_ricotta.jpg',
allowedSlots: ['obiad', 'kolacja'],
tags: ['wegetariańskie'],
nutritionPerServing: { kcal: 608, protein: 24, fat: 24, carbs: 75 },
ingredients: [
{ ingredientId: 'makaron_suchy', amount: 80, unit: 'g' },
{ ingredientId: 'pomidorki_koktajlowe', amount: 200, unit: 'g' },
{ ingredientId: 'czosnek', amount: 6, unit: 'g' },
{ ingredientId: 'tymianek', amount: 1, unit: 'g' },
{ ingredientId: 'oliwa', amount: 5, unit: 'ml' },
{ ingredientId: 'ricotta', amount: 75, unit: 'g' },
{ ingredientId: 'bazylia_swieza', amount: 3, unit: 'g' },
{ ingredientId: 'nasiona_slonecznika', amount: 15, unit: 'g' },
],
steps: [
'Makaron ugotuj wg przepisu na opakowaniu. Po ugotowaniu pozostaw 12 łyżki wody.',
'Na patelni rozgrzej oliwę, dodaj przeciśnięty czosnek, przekrojone na pół pomidorki i tymianek — podsmażaj 23 minuty.',
'Na patelnię z sosem dodaj ugotowany makaron. Wymieszaj, przypraw solą i pieprzem.',
'Ricottę wymieszaj z 12 łyżkami wody z gotowania makaronu. Nałóż na makaron.',
'Posyp bazylią świeżą i nasionami słonecznika.',
],
},
jajecznica: {
id: 'jajecznica',
title: 'Jajecznica z pieczywem',
description: 'Klasyczna jajecznica z 4 jajek z bułką grahamką i szczypiorkiem.',
minutes: 5,
thumbLabel: 'Jajecznica',
image: 'images/recipes/jajecznica.png',
allowedSlots: ['sniadanie', 'drugie_sniadanie', 'kolacja'],
tags: ['szybkie', 'wysokobiałkowe'],
nutritionPerServing: { kcal: 571, protein: 38, fat: 30, carbs: 36 },
ingredients: [
{ ingredientId: 'jajko', amount: 4, unit: 'szt.' },
{ ingredientId: 'oliwa', amount: 5, unit: 'ml' },
{ ingredientId: 'bulka_grahamka', amount: 1, unit: 'szt.' },
{ ingredientId: 'szczypiorek', amount: 5, unit: 'g' },
],
steps: [
'Na patelni rozgrzej oliwę na małej mocy palnika.',
'Wbij jajka bezpośrednio na patelnię. Smaż bez przykrycia, delikatnie mieszając łopatką, aż żółtka i białka stopniowo się połączą.',
'Dopraw solą i pieprzem. Kontynuuj smażenie, aż jajka się zetną, ale pozostaną lekko kremowe — ok. 34 minuty.',
'Posyp posiekanym szczypiorkiem i podawaj z bułką grahamką.',
],
},
kanapka_hummus: {
id: 'kanapka_hummus',
title: 'Kanapka z hummusem, wędliną i warzywami',
description: 'Bułka grahamka z hummusem, szynką z kurczaka i świeżymi warzywami.',
minutes: 5,
thumbLabel: 'Hummus',
image: 'images/recipes/kanapka_hummus.png',
allowedSlots: ['sniadanie', 'drugie_sniadanie', 'kolacja'],
tags: ['szybkie', 'wysokobiałkowe'],
nutritionPerServing: { kcal: 609, protein: 46, fat: 19, carbs: 66 },
ingredients: [
{ ingredientId: 'bulka_grahamka', amount: 1, unit: 'szt.' },
{ ingredientId: 'szynka_z_kurczaka', amount: 130, unit: 'g' },
{ ingredientId: 'pomidor', amount: 80, unit: 'g' },
{ ingredientId: 'papryka_czerwona', amount: 85, unit: 'g' },
{ ingredientId: 'ogorek', amount: 75, unit: 'g' },
{ ingredientId: 'szczypiorek', amount: 20, unit: 'g' },
{ ingredientId: 'hummus', amount: 140, unit: 'g' },
],
steps: [
'Pomidora i ogórka pokrój w plastry. Paprykę pokrój w paski. Szczypiorek posiekaj.',
'Bułkę grahamkę przekrój i posmaruj hummusem.',
'Na bułce ułóż szynkę z kurczaka, pomidora, paprykę i ogórka.',
'Posyp szczypiorkiem i podawaj.',
],
},
kanapka_losos: {
id: 'kanapka_losos',
title: 'Kanapka z wędzonym łososiem',
description: 'Bułka grahamka z łososiem wędzonym, pastą chrzanowo-serową i kiełkami.',
minutes: 5,
thumbLabel: 'Łosoś',
image: 'images/recipes/kanapka_losos.jpg',
allowedSlots: ['sniadanie', 'drugie_sniadanie', 'kolacja'],
tags: ['szybkie'],
nutritionPerServing: { kcal: 443, protein: 30, fat: 18, carbs: 39 },
ingredients: [
{ ingredientId: 'bulka_grahamka', amount: 1, unit: 'szt.' },
{ ingredientId: 'losos_wedzony', amount: 100, unit: 'g' },
{ ingredientId: 'serek_smietankowy', amount: 40, unit: 'g' },
{ ingredientId: 'chrzan', amount: 10, unit: 'g' },
{ ingredientId: 'koper_swiezy', amount: 5, unit: 'g' },
{ ingredientId: 'kielki_rzodkiewki', amount: 5, unit: 'g' },
{ ingredientId: 'ogorek', amount: 75, unit: 'g' },
],
steps: [
'Bułkę grahamkę przekrój i podsmaż na patelni na średnim ogniu przez 23 minuty.',
'Chrzan dokładnie wymieszaj z serkiem śmietankowym.',
'Koperek drobno posiekaj. Ogórka pokrój na mniejsze kawałki.',
'Na bułce rozsmaruj pastę chrzanowo-serową. Ułóż łososia, koperek, ogórka i kiełki.',
],
},
serek_owoc: {
id: 'serek_owoc',
title: 'Serek wiejski z orzechami i owocami',
description: 'Lekki, pożywny posiłek: serek z orzechami, truskawkami i borówkami.',
minutes: 5,
thumbLabel: 'Serek',
image: 'images/recipes/serek_owoc.jpg',
allowedSlots: ['sniadanie', 'drugie_sniadanie', 'przekaska'],
tags: ['wegetariańskie', 'wysokobiałkowe', 'szybkie'],
nutritionPerServing: { kcal: 629, protein: 31, fat: 43, carbs: 40 },
ingredients: [
{ ingredientId: 'serek_wiejski', amount: 200, unit: 'g' },
{ ingredientId: 'miod', amount: 10, unit: 'g' },
{ ingredientId: 'orzechy_wloskie', amount: 50, unit: 'g', alternatives: ['orzechy_laskowe', 'orzechy_nerkowca', 'migdaly', 'orzechy_pekan'] },
{ ingredientId: 'truskawki', amount: 100, unit: 'g', alternatives: ['banany'] },
{ ingredientId: 'borowki_amerykanskie', amount: 80, unit: 'g', alternatives: ['jagody'] },
],
steps: [
'Przełóż serek wiejski do miseczki.',
'Dodaj miód i delikatnie wymieszaj.',
'Orzechy posiekaj na mniejsze kawałki i posyp nimi serek z miodem.',
'Umyj owoce (ew. pokrój na połówki) i ułóż na wierzchu. Gotowe!',
],
},
};
/**
* Krok +/- w spiżarni: całe opakowanie albo domyślny krok (10 g/ml lub 1 szt.).
* @param {string} ingredientId
* @returns {number}
*/
export function pantryQtyStep(ingredientId) {
const d = INGREDIENTS[ingredientId];
if (!d) return 10;
if (d.purchasePack && Number.isFinite(d.purchasePack.amount) && d.purchasePack.amount > 0) {
return d.purchasePack.amount;
}
return d.pantryUnit === 'szt' ? 1 : 10;
}
/**
* @param {IngredientDef} def
* @param {number} stockQty — w pantryUnit
*/
export function nutritionForStock(def, stockQty) {
const n = def.nutritionPer100g;
if (!n || !Number.isFinite(stockQty) || stockQty <= 0) return null;
let grams = stockQty;
if (def.pantryUnit === 'szt' && def.weightPerPiece) {
grams = stockQty * def.weightPerPiece;
}
const f = grams / 100;
return {
kcal: Math.round(n.kcal * f),
protein: Math.round(n.protein * f * 10) / 10,
fat: Math.round(n.fat * f * 10) / 10,
carbs: Math.round(n.carbs * f * 10) / 10,
};
}
/**
* Pełne opakowania + reszta (np. 450 g / 200 → 2 + 50 g).
* @param {IngredientDef} def
* @param {number} stockQty
* @returns {{ fullPacks: number, remainder: number } | null}
*/
export function splitStockIntoPacks(def, stockQty) {
const size = def.purchasePack?.amount;
if (!size || !Number.isFinite(size) || size <= 0 || !Number.isFinite(stockQty)) return null;
const fullPacks = Math.floor(stockQty / size);
const remainder = Math.round((stockQty - fullPacks * size) * 10) / 10;
return { fullPacks, remainder };
}