Files
recipe-mockup/js/data/catalog.js
ulfrxdev f80b115cae
All checks were successful
Build and Deploy / build-and-push (push) Successful in 23s
Reorganise the views and prepare summary
2026-03-26 22:29:06 +01:00

442 lines
16 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 = {
maka_pszenna: {
id: 'maka_pszenna',
name: 'Mąka pszenna',
category: 'suche',
pantryUnit: 'g',
nutritionPer100g: { kcal: 364, protein: 10, fat: 1, carbs: 76 },
},
mleko: {
id: 'mleko',
name: 'Mleko',
category: 'nabial',
pantryUnit: 'ml',
purchasePack: { amount: 1000, label: 'butelka 1 l' },
nutritionPer100g: { kcal: 42, protein: 3.4, fat: 1, carbs: 5 },
},
jajko: {
id: 'jajko',
name: 'Jajka',
category: 'nabial',
pantryUnit: 'szt',
nutritionPer100g: { kcal: 143, protein: 13, fat: 9.5, carbs: 1.1 },
},
piers_kurczaka: {
id: 'piers_kurczaka',
name: 'Pierś z kurczaka',
category: 'mieso_ryby',
pantryUnit: 'g',
nutritionPer100g: { kcal: 165, protein: 31, fat: 3.6, carbs: 0 },
},
mix_salat: {
id: 'mix_salat',
name: 'Mix sałat',
category: 'warzywa',
pantryUnit: 'g',
nutritionPer100g: { kcal: 20, protein: 1.5, fat: 0.3, carbs: 3 },
},
pomidor: {
id: 'pomidor',
name: 'Pomidor',
category: 'warzywa',
pantryUnit: 'szt',
nutritionPer100g: { kcal: 18, protein: 0.9, fat: 0.2, carbs: 3.9 },
},
makaron_suchy: {
id: 'makaron_suchy',
name: 'Makaron',
category: 'suche',
pantryUnit: 'g',
nutritionPer100g: { kcal: 371, protein: 13, fat: 1.5, carbs: 74 },
},
pomidory_krojone: {
id: 'pomidory_krojone',
name: 'Pomidory krojone (puszka)',
category: 'warzywa',
pantryUnit: 'g',
nutritionPer100g: { kcal: 20, protein: 1, fat: 0.2, carbs: 4 },
},
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 },
},
jogurt_naturalny: {
id: 'jogurt_naturalny',
name: 'Jogurt naturalny',
category: 'nabial',
pantryUnit: 'g',
nutritionPer100g: { kcal: 61, protein: 3.5, fat: 3.3, carbs: 4.7 },
},
mieszanka_jagod: {
id: 'mieszanka_jagod',
name: 'Mieszanka jagód',
category: 'owoce',
pantryUnit: 'g',
nutritionPer100g: { kcal: 50, protein: 0.7, fat: 0.3, carbs: 12 },
},
miod: {
id: 'miod',
name: 'Miód',
category: 'inne',
pantryUnit: 'g',
nutritionPer100g: { kcal: 304, protein: 0.3, fat: 0, carbs: 82 },
},
chleb_zakwas: {
id: 'chleb_zakwas',
name: 'Chleb na zakwasie',
category: 'pieczywo',
pantryUnit: 'szt',
nutritionPer100g: { kcal: 250, protein: 9, fat: 1.5, carbs: 49 },
},
awokado: {
id: 'awokado',
name: 'Awokado',
category: 'warzywa',
pantryUnit: 'szt',
nutritionPer100g: { kcal: 160, protein: 2, fat: 15, carbs: 9 },
},
cytryna: {
id: 'cytryna',
name: 'Cytryna',
category: 'owoce',
pantryUnit: 'szt',
nutritionPer100g: { kcal: 29, protein: 1.1, fat: 0.3, carbs: 9 },
},
losos_filet: {
id: 'losos_filet',
name: 'Filet z łososia',
category: 'mieso_ryby',
pantryUnit: 'g',
nutritionPer100g: { kcal: 208, protein: 20, fat: 13, carbs: 0 },
},
koper_swiezy: {
id: 'koper_swiezy',
name: 'Koper',
category: 'przyprawy',
pantryUnit: 'g',
nutritionPer100g: { kcal: 43, protein: 3.5, fat: 1.1, carbs: 7 },
},
mieso_wol_mielone: {
id: 'mieso_wol_mielone',
name: 'Mięso mielone wołowe',
category: 'mieso_ryby',
pantryUnit: 'g',
nutritionPer100g: { kcal: 250, protein: 26, fat: 15, carbs: 0 },
},
tortilla_kukurydziana: {
id: 'tortilla_kukurydziana',
name: 'Tortille kukurydziane',
category: 'pieczywo',
pantryUnit: 'szt',
nutritionPer100g: { kcal: 218, protein: 5.7, fat: 2.9, carbs: 44 },
},
salsa_pomidorowa: {
id: 'salsa_pomidorowa',
name: 'Salsa pomidorowa',
category: 'warzywa',
pantryUnit: 'g',
nutritionPer100g: { kcal: 36, protein: 1.5, fat: 0.2, carbs: 8 },
},
platki_owsiane: {
id: 'platki_owsiane',
name: 'Płatki owsiane',
category: 'suche',
pantryUnit: 'g',
nutritionPer100g: { kcal: 389, protein: 17, fat: 7, carbs: 66 },
},
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 },
},
orzechy_wloskie: {
id: 'orzechy_wloskie',
name: 'Orzechy włoskie',
category: 'suche',
pantryUnit: 'g',
nutritionPer100g: { kcal: 654, protein: 15, fat: 65, carbs: 14 },
},
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 },
},
};
/** Porcja bazowa = 1; składniki przez ingredientId */
export const RECIPES = {
placki: {
id: 'placki',
title: 'Puszyste placki',
description: 'Klasyczne placki na śniadanie — puszyste i złociste.',
minutes: 15,
thumbLabel: 'Placki',
allowedSlots: ['sniadanie', 'drugie_sniadanie'],
tags: ['wegetariańskie', 'słodkie'],
nutritionPerServing: { kcal: 320, protein: 12, fat: 8, carbs: 48 },
ingredients: [
{ ingredientId: 'maka_pszenna', amount: 200, unit: 'g' },
{ ingredientId: 'mleko', amount: 250, unit: 'ml' },
{ ingredientId: 'jajko', amount: 2, unit: 'szt.' },
],
steps: [
'Mąkę przesiej do miski, dodaj szczyptę soli.',
'Wbij jajka, wlej mleko i wymieszaj trzepaczką na gładkie ciasto.',
'Rozgrzej patelnię z odrobiną masła na średnim ogniu.',
'Nakładaj ciasto łyżką wazową i smaż placki po ok. 2 min z każdej strony.',
],
},
salatka: {
id: 'salatka',
title: 'Sałatka z kurczakiem',
description: 'Zielone warzywa z grillowanym kurczakiem.',
minutes: 20,
thumbLabel: 'Sałatka',
allowedSlots: ['obiad'],
tags: ['wysokobiałkowe', 'niskokaloryczne'],
nutritionPerServing: { kcal: 250, protein: 35, fat: 9, carbs: 12 },
ingredients: [
{ ingredientId: 'piers_kurczaka', amount: 150, unit: 'g' },
{ ingredientId: 'mix_salat', amount: 100, unit: 'g' },
{ ingredientId: 'pomidor', amount: 1, unit: 'szt.' },
],
steps: [
'Pierś z kurczaka przypraw solą i pieprzem, griluj na patelni ok. 5 min z każdej strony.',
'Pokrój kurczaka w paski i odłóż do ostygnięcia.',
'Wymieszaj mix sałat z pokrojonym pomidorem.',
'Ułóż kurczaka na sałatce, polej ulubionym dressingiem.',
],
},
makaron: {
id: 'makaron',
title: 'Makaron z pomidorami i bazylią',
description: 'Aromatyczny sos pomidorowy z czosnkiem i świeżą bazylią.',
minutes: 30,
thumbLabel: 'Makaron',
allowedSlots: ['obiad', 'kolacja'],
tags: ['wegetariańskie', 'wegańskie'],
nutritionPerServing: { kcal: 450, protein: 14, fat: 12, carbs: 72 },
ingredients: [
{ ingredientId: 'makaron_suchy', amount: 120, unit: 'g' },
{ ingredientId: 'pomidory_krojone', amount: 400, unit: 'g' },
{ ingredientId: 'bazylia_swieza', amount: 10, unit: 'g' },
],
steps: [
'Ugotuj makaron al dente wg instrukcji na opakowaniu.',
'Na patelni rozgrzej oliwę, dodaj pomidory krojone i gotuj 10 min.',
'Dopraw solą, pieprzem i szczyptą cukru.',
'Wymieszaj makaron z sosem, udekoruj świeżą bazylią.',
],
},
koktajl: {
id: 'koktajl',
title: 'Koktajl owocowy',
description: 'Mix jagód i jogurtu — szybka przekąska lub drugie śniadanie.',
minutes: 5,
thumbLabel: 'Koktajl',
allowedSlots: ['przekaska', 'drugie_sniadanie'],
tags: ['wegetariańskie', 'szybkie'],
nutritionPerServing: { kcal: 180, protein: 8, fat: 3, carbs: 32 },
ingredients: [
{ ingredientId: 'jogurt_naturalny', amount: 200, unit: 'g' },
{ ingredientId: 'mieszanka_jagod', amount: 150, unit: 'g' },
{ ingredientId: 'miod', amount: 15, unit: 'g' },
],
steps: [
'Wrzuć jogurt, jagody i miód do blendera.',
'Zmiksuj na gładką masę (~30 sekund).',
'Przelej do szklanki. Gotowe!',
],
},
tost_awokado: {
id: 'tost_awokado',
title: 'Tost z awokado',
description: 'Chleb na zakwasie z rozgniecionym awokado i cytryną.',
minutes: 10,
thumbLabel: 'Tost',
allowedSlots: ['sniadanie', 'drugie_sniadanie'],
tags: ['wegetariańskie', 'wegańskie', 'szybkie'],
nutritionPerServing: { kcal: 220, protein: 6, fat: 14, carbs: 20 },
ingredients: [
{ ingredientId: 'chleb_zakwas', amount: 2, unit: 'kromki' },
{ ingredientId: 'awokado', amount: 1, unit: 'szt.' },
{ ingredientId: 'cytryna', amount: 0.5, unit: 'szt.' },
],
steps: [
'Opiecz kromki chleba w tosterze lub na suchej patelni.',
'Przekrój awokado, wyjmij pestkę i wyłóż miąższ do miseczki.',
'Rozgnieć widelcem, dodaj sok z cytryny, sól i pieprz.',
'Nałóż masę na tosty. Podawaj od razu.',
],
},
losos: {
id: 'losos',
title: 'Grillowany łosoś',
description: 'Świeży łosoś z masłem cytrynowym i koperkiem.',
minutes: 25,
thumbLabel: 'Łosoś',
allowedSlots: ['kolacja', 'obiad'],
tags: ['wysokobiałkowe'],
nutritionPerServing: { kcal: 380, protein: 38, fat: 22, carbs: 4 },
ingredients: [
{ ingredientId: 'losos_filet', amount: 180, unit: 'g' },
{ ingredientId: 'cytryna', amount: 0.5, unit: 'szt.' },
{ ingredientId: 'koper_swiezy', amount: 5, unit: 'g' },
],
steps: [
'Filety oprósz solą, pieprzem i skrop sokiem z cytryny.',
'Rozgrzej patelnię grillową na dość mocnym ogniu.',
'Smaż łososia 45 min z każdej strony (skórą do dołu na start).',
'Podawaj z posiekanym koperkiem i plasterkiem cytryny.',
],
},
tacos: {
id: 'tacos',
title: 'Tacos z wołowiną',
description: 'Pikantna mielona wołowina ze świeżą salsą w tortillach.',
minutes: 20,
thumbLabel: 'Tacos',
allowedSlots: ['kolacja', 'obiad'],
tags: [],
nutritionPerServing: { kcal: 410, protein: 28, fat: 18, carbs: 38 },
ingredients: [
{ ingredientId: 'mieso_wol_mielone', amount: 200, unit: 'g' },
{ ingredientId: 'tortilla_kukurydziana', amount: 4, unit: 'szt.' },
{ ingredientId: 'salsa_pomidorowa', amount: 100, unit: 'g' },
],
steps: [
'Na rozgrzanej patelni podsmaż mielone, rozbijając widelcem, aż się zarumieni.',
'Dopraw kuminem, papryką, solą i pieprzem.',
'Podgrzej tortille na suchej patelni po 15 sek. z każdej strony.',
'Nałóż mięso na tortillę, polej salsą i zawiń.',
],
},
owsianka: {
id: 'owsianka',
title: 'Miska owsianki',
description: 'Ciepła owsianka z miodem — szybki i sycący posiłek.',
minutes: 10,
thumbLabel: 'Owsianka',
allowedSlots: ['sniadanie', 'drugie_sniadanie'],
tags: ['wegetariańskie', 'szybkie'],
nutritionPerServing: { kcal: 210, protein: 8, fat: 6, carbs: 34 },
ingredients: [
{ ingredientId: 'platki_owsiane', amount: 60, unit: 'g' },
{ ingredientId: 'mleko', amount: 200, unit: 'ml' },
{ ingredientId: 'miod', amount: 20, unit: 'g' },
],
steps: [
'W garnuszku zagotuj mleko.',
'Wsyp płatki owsiane, zmniejsz ogień i gotuj 34 min, mieszając.',
'Przełóż do miski, polej miodem. Opcjonalnie dodaj owoce lub orzechy.',
],
},
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',
allowedSlots: ['sniadanie', 'drugie_sniadanie', 'przekaska'],
tags: ['wegetariańskie', 'wysokobiałkowe', 'szybkie'],
nutritionPerServing: { kcal: 642, protein: 32, fat: 43, carbs: 41 },
ingredients: [
{ ingredientId: 'serek_wiejski', amount: 200, unit: 'g' },
{ ingredientId: 'miod', amount: 10, unit: 'g' },
{ ingredientId: 'orzechy_wloskie', amount: 50, unit: 'g' },
{ ingredientId: 'truskawki', amount: 100, unit: 'g' },
{ ingredientId: 'borowki_amerykanskie', amount: 80, unit: 'g' },
],
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;
const f = stockQty / 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 };
}