Files
recipe-mockup/js/data/catalog.js
2026-04-06 11:20:25 +02:00

498 lines
20 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 },
},
rokitnik_zwyczajny: {
id: 'rokitnik_zwyczajny',
name: 'Rokitnik zwyczajny - rokitnik pospolity (Hippophae rhamnoides)',
category: 'owoce',
pantryUnit: 'g',
nutritionPer100g: { kcal: 82, protein: 1.2, fat: 5.4, carbs: 5.5 },
},
/* ── 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 },
},
};
/**
* @typedef {{ ingredientId: string, amount: number, unit: string, alternatives?: string[] }} RecipeIngredientDef
* @typedef {{ id: string, title: string, minutes: number, thumbLabel: string, image?: string, allowedSlots: string[], tags?: string[], nutritionPerServing: NutritionPer100, ingredients: RecipeIngredientDef[], steps: string[] }} RecipeDef
*/
/** Porcja bazowa = 1; składniki przez ingredientId */
/** @type {Record<string, RecipeDef>} */
export const RECIPES = {
kanapka_parmenska: {
id: 'kanapka_parmenska',
title: 'Kanapka z szynką parmeńską i mozzarellą',
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',
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',
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',
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',
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',
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', 'rokitnik_zwyczajny'] },
],
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 };
}