import { RECIPES, INGREDIENTS } from '../data/catalog.js';
import { MEAL_SLOTS } from '../planner/mealSlots.js';
import { addDays, startOfDay } from '../services/dateUtils.js';
import { addOrMergeShoppingLines, loadPantry } from '../services/pantryShopping.js';
import { dateKey, loadPlans, newPlanEntryId, savePlans } from '../services/planStore.js';
import { showAppToast } from '../ui/toast.js';
function escapeHtml(s) {
return String(s)
.replace(/&/g, '&')
.replace(//g, '>')
.replace(/"/g, '"');
}
const slotLabelMap = Object.fromEntries(MEAL_SLOTS.map((s) => [s.id, s.label]));
export function getRecipeDetailHTML() {
return `
Dodaj do planera
Pora posiłku
`;
}
let currentRecipeId = null;
let currentServings = 1;
function populateDetail(recipeId) {
const recipe = RECIPES[recipeId];
if (!recipe) return;
currentRecipeId = recipeId;
currentServings = 1;
document.getElementById('rd-hero-label').textContent = `Zdjęcie: ${recipe.title}`;
document.getElementById('rd-title').textContent = recipe.title;
document.getElementById('rd-time').textContent = `${recipe.minutes} min`;
updateKcalDisplay();
const tagsHtml = [];
for (const slotId of recipe.allowedSlots) {
const label = slotLabelMap[slotId];
if (label) tagsHtml.push(`${escapeHtml(label)}`);
}
for (const tag of (recipe.tags || [])) {
tagsHtml.push(`${escapeHtml(tag)}`);
}
document.getElementById('rd-tags').innerHTML = tagsHtml.join('');
document.getElementById('rd-servings').textContent = '1';
renderIngredients(recipe);
renderSteps(recipe);
renderNutrition(recipe);
const tabBtns = document.querySelectorAll('.rd-tab-btn');
const tabs = document.querySelectorAll('.rd-tab-content');
tabBtns.forEach((b) => {
b.classList.remove('text-gray-900', 'border-gray-900', 'font-semibold');
b.classList.add('text-gray-500', 'border-transparent', 'font-medium');
});
tabBtns[0]?.classList.remove('text-gray-500', 'border-transparent', 'font-medium');
tabBtns[0]?.classList.add('text-gray-900', 'border-gray-900', 'font-semibold');
tabs.forEach((t) => { t.classList.add('hidden'); t.classList.remove('block'); });
document.getElementById('rd-tab-ingredients')?.classList.remove('hidden');
document.getElementById('rd-tab-ingredients')?.classList.add('block');
}
function updateKcalDisplay() {
const recipe = RECIPES[currentRecipeId];
if (!recipe) return;
const kcal = Math.round(recipe.nutritionPerServing.kcal * currentServings);
document.getElementById('rd-kcal').textContent = `${kcal} kcal`;
}
function renderIngredients(recipe) {
const container = document.getElementById('rd-tab-ingredients');
if (!container) return;
const pantry = loadPantry();
const rows = recipe.ingredients.map((ing) => {
const def = INGREDIENTS[ing.ingredientId];
const name = def?.name || ing.ingredientId;
const scaledAmount = ing.amount * currentServings;
const displayAmount = Number.isInteger(scaledAmount) ? scaledAmount : parseFloat(scaledAmount.toFixed(1));
const pantryQty = Number(pantry[ing.ingredientId]) || 0;
let stockBadge = '';
if (def) {
const u = def.pantryUnit === 'szt' ? 'szt.' : def.pantryUnit;
if (pantryQty >= scaledAmount) {
stockBadge = `Masz`;
} else if (pantryQty > 0) {
const miss = parseFloat((scaledAmount - pantryQty).toFixed(1));
stockBadge = `Brak ${miss} ${u}`;
} else {
stockBadge = `Brak`;
}
}
return `
${escapeHtml(name)}
${stockBadge}
${displayAmount} ${escapeHtml(ing.unit)}
`;
}).join('');
container.innerHTML = `
Zaznacz składniki do kupienia
`;
container.querySelectorAll('.rd-ingredient-row').forEach((row) => {
row.addEventListener('click', () => row.classList.toggle('ingredient-active'));
});
document.getElementById('rd-add-to-shopping')?.addEventListener('click', () => {
const recipe = RECIPES[currentRecipeId];
if (!recipe) return;
const checkedRows = container.querySelectorAll('.rd-ingredient-row.ingredient-active');
if (checkedRows.length === 0) {
showAppToast('Zaznacz składniki, które chcesz dodać.');
return;
}
const lines = [];
checkedRows.forEach((row) => {
const ingredientId = row.dataset.ingredientId;
const baseAmount = parseFloat(row.dataset.baseAmount);
const unit = row.dataset.unit;
const def = INGREDIENTS[ingredientId];
lines.push({
ingredientId,
amount: Math.round(baseAmount * currentServings * 100) / 100,
unit,
name: def?.name || ingredientId,
category: def?.category || 'inne',
sourceNote: `Przepis: ${recipe.title}`,
});
});
addOrMergeShoppingLines(lines);
showAppToast(`Dodano ${lines.length} składnik(ów) na listę zakupów.`);
window.refreshShopping?.();
checkedRows.forEach((row) => row.classList.remove('ingredient-active'));
});
}
function renderSteps(recipe) {
const container = document.getElementById('rd-tab-steps');
if (!container) return;
const steps = recipe.steps || [];
if (steps.length === 0) {
container.innerHTML = 'Brak kroków przygotowania.
';
return;
}
container.innerHTML = `
${steps.map((step, i) => `
`).join('')}
`;
}
function renderNutrition(recipe) {
const container = document.getElementById('rd-tab-nutrition');
if (!container) return;
const n = recipe.nutritionPerServing;
const s = currentServings;
container.innerHTML = `
${s > 1 ? `Wartości dla ${s} porcji` : 'Wartości na 1 porcję'}
- Kalorie${Math.round(n.kcal * s)} kcal
- Białko${Math.round(n.protein * s * 10) / 10} g
- Tłuszcze${Math.round(n.fat * s * 10) / 10} g
- Węglowodany${Math.round(n.carbs * s * 10) / 10} g
`;
}
export function setupRecipeDetail() {
document.querySelectorAll('.rd-tab-btn').forEach((btn) => {
btn.addEventListener('click', () => {
const tabId = btn.dataset.rdTab;
document.querySelectorAll('.rd-tab-content').forEach((el) => {
el.classList.add('hidden');
el.classList.remove('block');
});
const target = document.getElementById(`rd-tab-${tabId}`);
if (target) {
target.classList.remove('hidden');
target.classList.add('block');
target.parentElement.scrollTop = 0;
}
document.querySelectorAll('.rd-tab-btn').forEach((b) => {
b.classList.remove('text-gray-900', 'border-gray-900', 'font-semibold');
b.classList.add('text-gray-500', 'border-transparent', 'font-medium');
});
btn.classList.remove('text-gray-500', 'border-transparent', 'font-medium');
btn.classList.add('text-gray-900', 'border-gray-900', 'font-semibold');
});
});
document.getElementById('rd-serv-minus')?.addEventListener('click', () => {
if (currentServings <= 1) return;
currentServings--;
document.getElementById('rd-servings').textContent = currentServings;
const recipe = RECIPES[currentRecipeId];
if (recipe) {
renderIngredients(recipe);
renderNutrition(recipe);
updateKcalDisplay();
}
});
document.getElementById('rd-serv-plus')?.addEventListener('click', () => {
if (currentServings >= 12) return;
currentServings++;
document.getElementById('rd-servings').textContent = currentServings;
const recipe = RECIPES[currentRecipeId];
if (recipe) {
renderIngredients(recipe);
renderNutrition(recipe);
updateKcalDisplay();
}
});
const WEEKDAYS_LONG = ['Niedziela', 'Poniedziałek', 'Wtorek', 'Środa', 'Czwartek', 'Piątek', 'Sobota'];
const MONTHS_SHORT = ['sty', 'lut', 'mar', 'kwi', 'maj', 'cze', 'lip', 'sie', 'wrz', 'paź', 'lis', 'gru'];
let plannerPickerDay = null;
let plannerPickerSlot = null;
const plannerOverlay = document.getElementById('rd-planner-picker');
const plannerSheet = document.getElementById('rd-planner-sheet');
function openPlannerPicker() {
const recipe = RECIPES[currentRecipeId];
if (!recipe) return;
document.getElementById('rd-planner-recipe-name').textContent = recipe.title;
const daysContainer = document.getElementById('rd-planner-days');
const today = startOfDay(new Date());
const days = [];
for (let i = 0; i < 7; i++) days.push(addDays(today, i));
plannerPickerDay = today;
plannerPickerSlot = recipe.allowedSlots[0] || MEAL_SLOTS[0]?.id;
daysContainer.innerHTML = days.map((d, idx) => {
const wd = WEEKDAYS_LONG[d.getDay()];
const label = idx === 0 ? `Dziś — ${wd}, ${d.getDate()} ${MONTHS_SHORT[d.getMonth()]}` : `${wd}, ${d.getDate()} ${MONTHS_SHORT[d.getMonth()]}`;
const sel = idx === 0;
return ``;
}).join('');
const slotsContainer = document.getElementById('rd-planner-slots');
slotsContainer.innerHTML = MEAL_SLOTS.filter((s) => recipe.allowedSlots.includes(s.id)).map((s) => {
const sel = s.id === plannerPickerSlot;
return ``;
}).join('');
plannerOverlay.classList.remove('hidden');
plannerOverlay.style.pointerEvents = 'auto';
requestAnimationFrame(() => {
plannerSheet.style.transform = 'translateY(0)';
});
}
function closePlannerPicker() {
plannerSheet.style.transform = 'translateY(100%)';
setTimeout(() => {
plannerOverlay.classList.add('hidden');
plannerOverlay.style.pointerEvents = 'none';
}, 300);
}
document.getElementById('rd-add-to-planner-btn')?.addEventListener('click', openPlannerPicker);
plannerOverlay?.addEventListener('click', (e) => {
if (e.target === plannerOverlay) closePlannerPicker();
});
document.getElementById('rd-planner-days')?.addEventListener('click', (e) => {
const btn = e.target.closest('.rd-plan-day-btn');
if (!btn) return;
plannerPickerDay = new Date(Number(btn.getAttribute('data-day-ts')));
document.querySelectorAll('.rd-plan-day-btn').forEach((b) => {
b.classList.remove('border-gray-900', 'bg-gray-900', 'text-white');
b.classList.add('border-gray-200', 'bg-gray-50', 'text-gray-900');
});
btn.classList.remove('border-gray-200', 'bg-gray-50', 'text-gray-900');
btn.classList.add('border-gray-900', 'bg-gray-900', 'text-white');
});
document.getElementById('rd-planner-slots')?.addEventListener('click', (e) => {
const btn = e.target.closest('.rd-plan-slot-btn');
if (!btn) return;
plannerPickerSlot = btn.getAttribute('data-slot-id');
document.querySelectorAll('.rd-plan-slot-btn').forEach((b) => {
b.classList.remove('border-gray-900', 'bg-gray-900', 'text-white');
b.classList.add('border-gray-200', 'bg-gray-50', 'text-gray-700');
});
btn.classList.remove('border-gray-200', 'bg-gray-50', 'text-gray-700');
btn.classList.add('border-gray-900', 'bg-gray-900', 'text-white');
});
document.getElementById('rd-planner-confirm')?.addEventListener('click', () => {
if (!currentRecipeId || !plannerPickerDay || !plannerPickerSlot) return;
const plans = loadPlans();
const key = dateKey(plannerPickerDay);
if (!plans[key]) plans[key] = {};
if (!plans[key][plannerPickerSlot]) plans[key][plannerPickerSlot] = [];
plans[key][plannerPickerSlot].push({
id: newPlanEntryId(),
recipeId: currentRecipeId,
servings: currentServings,
});
savePlans(plans);
closePlannerPicker();
showAppToast('Dodano do planera!');
window.refreshPlanner?.();
});
window.openRecipeDetail = (recipeId) => {
if (!recipeId || !RECIPES[recipeId]) return;
populateDetail(recipeId);
const view = document.getElementById('recipe-detail-view');
view.classList.remove('translate-x-full', 'opacity-0', 'pointer-events-none');
view.classList.add('translate-x-0', 'opacity-100', 'pointer-events-auto');
};
window.closeRecipeDetail = () => {
closePlannerPicker();
const view = document.getElementById('recipe-detail-view');
view.classList.remove('translate-x-0', 'opacity-100', 'pointer-events-auto');
view.classList.add('translate-x-full', 'opacity-0', 'pointer-events-none');
};
}