let allMeals = []; let currentPlan = []; document.addEventListener("DOMContentLoaded", () => { setupTabs(); loadMeals(); setupFilters(); setupButtons(); }); function setupTabs() { document.querySelectorAll(".tab").forEach(tab => { tab.addEventListener("click", () => { document.querySelectorAll(".tab").forEach(t => t.classList.remove("active")); document.querySelectorAll(".tab-content").forEach(c => c.classList.remove("active")); tab.classList.add("active"); document.getElementById(tab.dataset.tab).classList.add("active"); }); }); } async function loadMeals() { try { const res = await fetch("/api/meals"); allMeals = await res.json(); renderMeals(allMeals); renderRecipes(allMeals); } catch (e) { console.error("Ошибка загрузки блюд:", e); } } function setupFilters() { document.querySelectorAll(".filter-btn").forEach(btn => { btn.addEventListener("click", () => { document.querySelectorAll(".filter-btn").forEach(b => b.classList.remove("active")); btn.classList.add("active"); const type = btn.dataset.type; if (type === "all") { renderMeals(allMeals); } else { renderMeals(allMeals.filter(m => m.type === type)); } }); }); } function setupButtons() { document.getElementById("btn-generate").addEventListener("click", generatePlan); document.getElementById("btn-export").addEventListener("click", exportToExcel); } function renderMeals(meals) { const container = document.getElementById("meals-list"); if (meals.length === 0) { container.innerHTML = '

Нет блюд

'; return; } container.innerHTML = meals.map(m => `
${m.type}

${m.name}

${m.calories} ккал Б: ${m.protein}г Ж: ${m.fat}г У: ${m.carbs}г
⏱ ${m.time_min} мин | 🍽 ${m.servings} порц.
`).join(""); } function renderRecipes(meals) { const container = document.getElementById("recipes-list"); container.innerHTML = meals.map(m => `
${m.type}

${m.name}

${m.calories} ккал 🍽 ${m.servings} порц.
`).join(""); } async function showRecipe(id) { const res = await fetch(`/api/meal/${id}`); const meal = await res.json(); if (!meal) return; document.getElementById("recipe-detail").innerHTML = `

${meal.name}

Ингредиенты (на ${meal.servings} порций)

КБЖУ на порцию

Калории${meal.calories} ккал
Белки${meal.protein} г
Жиры${meal.fat} г
Углеводы${meal.carbs} г

⏱ Время приготовления: ${meal.time_min} мин

`; document.getElementById("recipe-detail").classList.add("active"); document.getElementById("recipe-detail").scrollIntoView({ behavior: "smooth" }); } async function generatePlan() { const btn = document.getElementById("btn-generate"); btn.textContent = "⏳ Генерация..."; btn.disabled = true; try { console.log("Генерация плана..."); const res = await fetch("/api/generate-plan", { method: "POST" }); console.log("Статус ответа:", res.status); if (!res.ok) { const errText = await res.text(); throw new Error("Сервер вернул ошибку " + res.status + ": " + errText); } const result = await res.json(); console.log("План получен:", result); currentPlan = result.plan; renderWeeklyTotals(result.weekly_totals); renderWeekPlan(result.plan); const shoppingRes = await fetch("/api/shopping-list", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ plan: result.plan }) }); if (!shoppingRes.ok) { throw new Error("Список продуктов: ошибка " + shoppingRes.status); } const shopping = await shoppingRes.json(); console.log("Список продуктов:", shopping); renderShoppingList(shopping); const timelineRes = await fetch("/api/timeline", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ plan: result.plan }) }); if (!timelineRes.ok) { throw new Error("Хронология: ошибка " + timelineRes.status); } const timeline = await timelineRes.json(); console.log("Хронология:", timeline); renderTimeline(timeline); btn.textContent = "🔄 Сгенерировать заново"; } catch (e) { console.error("❌ Ошибка генерации:", e); alert("Ошибка: " + e.message); btn.textContent = "⚠️ Ошибка: " + e.message; } btn.disabled = false; } function renderWeeklyTotals(totals) { document.getElementById("weekly-totals").innerHTML = `

📊 Итого за неделю (на 4 человек)

${totals.calories.toLocaleString()}
ккал всего
${totals.avg_daily_calories.toLocaleString()}
ккал в день (среднее)
${totals.protein}г
Белки
${totals.fat}г
Жиры
${totals.carbs}г
Углеводы
${totals.cost.toLocaleString()} ₸
Примерная стоимость
`; } function renderWeekPlan(plan) { const container = document.getElementById("week-plan"); container.innerHTML = plan.map(day => `

${day.day} ${day.date}

🌅 Завтрак ${day.breakfast.name} ${day.breakfast.calories} ккал | Б:${day.breakfast.protein}г Ж:${day.breakfast.fat}г У:${day.breakfast.carbs}г
☀️ Обед ${day.lunch.name} ${day.lunch.calories} ккал | Б:${day.lunch.protein}г Ж:${day.lunch.fat}г У:${day.lunch.carbs}г
🌙 Ужин ${day.dinner.name} ${day.dinner.calories} ккал | Б:${day.dinner.protein}г Ж:${day.dinner.fat}г У:${day.dinner.carbs}г
Итого за день: ${day.daily_total.calories} ккал Б:${day.daily_total.protein}г | Ж:${day.daily_total.fat}г | У:${day.daily_total.carbs}г | ~${day.daily_total.cost} ₸
`).join(""); } function renderShoppingList(shopping) { const container = document.getElementById("shopping-list"); const summary = document.getElementById("shopping-summary"); summary.innerHTML = `

🛒 Список продуктов на неделю

${shopping.total_cost.toLocaleString()} ₸
Общая стоимость
${shopping.budget.toLocaleString()} ₸
Бюджет
${shopping.remaining.toLocaleString()} ₸
Остаток
`; const byCategory = {}; shopping.items.forEach(item => { if (!byCategory[item.category]) byCategory[item.category] = []; byCategory[item.category].push(item); }); container.innerHTML = Object.entries(byCategory).map(([cat, items]) => `

${cat}

${items.map(p => `
${p.name} ${p.amount >= 1000 ? (p.amount/1000).toFixed(2) + ' кг' : p.amount + ' г'} ${p.cost.toLocaleString()} ₸
`).join("")}
`).join(""); } function renderTimeline(timeline) { const container = document.getElementById("timeline-list"); container.innerHTML = timeline.map(item => `
${item.day} ${item.action}
${item.details}
${item.ingredients ? `
📝 Продукты: ${item.ingredients.slice(0, 5).join(", ")}${item.ingredients.length > 5 ? "..." : ""}
` : ""}
⏱ ${item.time_min} мин
`).join(""); } function exportToExcel() { const shopping = document.getElementById("shopping-list"); if (!shopping || shopping.children.length === 0) { alert("Сначала сгенерируйте план питания!"); return; } let csv = "\uFEFF"; csv += "Категория;Продукт;Количество;Стоимость (₸)\n"; document.querySelectorAll(".category-group").forEach(group => { const category = group.querySelector("h3").textContent; group.querySelectorAll(".product-item").forEach(item => { const name = item.querySelector(".name").textContent; const amount = item.querySelector(".amount").textContent; const cost = item.querySelector(".cost").textContent.replace(" ₸", ""); csv += `${category};${name};${amount};${cost}\n`; }); }); const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" }); const link = document.createElement("a"); link.href = URL.createObjectURL(blob); link.download = "spisok_produktov.csv"; link.click(); } window.showRecipe = showRecipe;