document.addEventListener('DOMContentLoaded', function () { // --- Snowflakes Effect --- function createSnowflakes() { const snowContainer = document.getElementById('snow-container'); if (!snowContainer) return; snowContainer.innerHTML = ''; const numberOfSnowflakes = 50; for (let i = 0; i < numberOfSnowflakes; i++) { const snowflake = document.createElement('div'); snowflake.className = 'snowflake'; const size = Math.random() * 4 + 2; // size from 2px to 6px snowflake.style.width = `${size}px`; snowflake.style.height = `${size}px`; snowflake.style.left = Math.random() * 100 + 'vw'; const animationDuration = Math.random() * 5 + 5; // 5 to 10 seconds snowflake.style.animationDuration = `${animationDuration}s`; const animationDelay = Math.random() * 5; // 0 to 5 seconds snowflake.style.animationDelay = `${animationDelay}s`; snowflake.style.opacity = Math.random() * 0.7 + 0.3; // 0.3 to 1.0 snowContainer.appendChild(snowflake); } } createSnowflakes(); // --- DOM Elements --- const recipeNameInput = document.getElementById('recipeName'); const guestCountInput = document.getElementById('guestCount'); const ingredientsContainer = document.getElementById('ingredients-container'); const addIngredientBtn = document.getElementById('add-ingredient'); const calculateBtn = document.getElementById('calculate-btn'); const newRecipeBtn = document.getElementById('new-recipe-btn'); const shoppingListContainer = document.getElementById('shopping-list-container'); const recipeCardsContainer = document.getElementById('recipe-cards-container'); // --- Core Functions --- async function loadRecipes() { try { const response = await fetch('api/get_recipes.php'); const data = await response.json(); if (data.success) { renderRecipeCards(data.recipes); } else { console.error('Failed to load recipes:', data.error); recipeCardsContainer.innerHTML = '

Error loading recipes.

'; } } catch (error) { console.error('Error:', error); recipeCardsContainer.innerHTML = '

Could not connect to the server.

'; } } function addIngredientRow(ingredient = { name: '', quantity: '', unit: '' }) { const row = document.createElement('div'); row.className = 'ingredient-row mb-2'; row.innerHTML = ` `; ingredientsContainer.appendChild(row); } function clearForm() { recipeNameInput.value = ''; guestCountInput.value = '1'; ingredientsContainer.innerHTML = ''; addIngredientRow(); shoppingListContainer.innerHTML = `

Your Shopping List

Your calculated list will appear here.

`; } function renderRecipeCards(recipes) { recipeCardsContainer.innerHTML = ''; if (!recipes || recipes.length === 0) { recipeCardsContainer.innerHTML = '

Здесь будут появляться ваши сохраненные рецепты.

'; return; } recipes.forEach(recipe => { const cardCol = document.createElement('div'); cardCol.className = 'col-lg-4 col-md-6 mb-4'; cardCol.setAttribute('data-id', recipe.id); const card = document.createElement('div'); card.className = 'card h-100'; const cardBody = document.createElement('div'); cardBody.className = 'card-body d-flex flex-column'; const title = document.createElement('h5'); title.className = 'card-title'; title.textContent = recipe.name; const subtitle = document.createElement('h6'); subtitle.className = 'card-subtitle mb-2 text-muted'; subtitle.textContent = `${recipe.guests} guest(s)`; const text = document.createElement('p'); text.className = 'card-text'; text.textContent = `${recipe.ingredients.length} ingredients`; const buttonGroup = document.createElement('div'); buttonGroup.className = 'mt-auto'; buttonGroup.innerHTML = ` `; cardBody.appendChild(title); cardBody.appendChild(subtitle); cardBody.appendChild(text); cardBody.appendChild(buttonGroup); card.appendChild(cardBody); cardCol.appendChild(card); recipeCardsContainer.appendChild(cardCol); }); } function renderShoppingList(list) { let html = '

Общий список покупок


'; if (list.length === 0) { html += '

Нет ингредиентов для расчета.

'; } else { html += ''; } shoppingListContainer.innerHTML = html; } function getRecipeDataFromForm() { const recipeName = recipeNameInput.value.trim(); const guests = parseInt(guestCountInput.value, 10) || 0; const ingredients = []; const rows = ingredientsContainer.querySelectorAll('.ingredient-row'); rows.forEach(row => { const name = row.querySelector('input[placeholder="Ingredient Name"]').value.trim(); const qty = parseFloat(row.querySelector('input[placeholder="Qty"]').value); const unit = row.querySelector('input[placeholder="Unit (e.g., grams, ml)"]').value.trim(); if (name && !isNaN(qty) && qty > 0) { ingredients.push({ name, quantity: qty, unit }); } }); if (recipeName && guests > 0 && ingredients.length > 0) { return { name: recipeName, guests, ingredients }; } return null; } // --- Event Listeners --- addIngredientBtn.addEventListener('click', () => addIngredientRow()); ingredientsContainer.addEventListener('click', function(e) { if (e.target.classList.contains('remove-ingredient')) { e.target.closest('.ingredient-row').remove(); } }); recipeCardsContainer.addEventListener('click', async function(e) { const target = e.target; const card = target.closest('.col-lg-4'); if (!card) return; const recipeId = card.getAttribute('data-id'); if (target.classList.contains('delete-recipe-btn')) { if (confirm('Are you sure you want to delete this recipe?')) { try { const response = await fetch('api/delete_recipe.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: recipeId }) }); const data = await response.json(); if (data.success) { card.remove(); } else { alert('Failed to delete recipe: ' + data.error); } } catch (error) { alert('Error: ' + error.message); } } } if (target.classList.contains('edit-recipe-btn')) { // Find the recipe data from the currently rendered cards const response = await fetch('api/get_recipes.php'); const data = await response.json(); if(!data.success) return; const recipeToEdit = data.recipes.find(r => r.id == recipeId); if (recipeToEdit) { // Populate form recipeNameInput.value = recipeToEdit.name; guestCountInput.value = recipeToEdit.guests; ingredientsContainer.innerHTML = ''; recipeToEdit.ingredients.forEach(ing => addIngredientRow(ing)); // Delete the old recipe from DB try { await fetch('api/delete_recipe.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: recipeId }) }); card.remove(); // Remove from UI immediately } catch (error) { alert('Error preparing for edit: ' + error.message); } } } }); newRecipeBtn.addEventListener('click', async function() { const recipeData = getRecipeDataFromForm(); if (recipeData) { try { const response = await fetch('api/save_recipe.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(recipeData) }); const data = await response.json(); if (data.success) { await loadRecipes(); // Reload all recipes to show the new one clearForm(); } else { alert('Failed to save recipe: ' + data.error); } } catch (error) { alert('Error: ' + error.message); } } else { alert('Please fill out the recipe name, guests, and at least one ingredient before saving.'); } }); calculateBtn.addEventListener('click', async function() { try { const response = await fetch('api/get_recipes.php'); const data = await response.json(); if (!data.success) { alert('Could not get recipes for calculation.'); return; } const allRecipesToCalculate = data.recipes; const currentRecipe = getRecipeDataFromForm(); if (currentRecipe) { // Give it a temporary ID to avoid collisions currentRecipe.id = 'current'; allRecipesToCalculate.push(currentRecipe); } if (allRecipesToCalculate.length === 0) { alert('There are no recipes to calculate. Please fill out the form or save a recipe.'); return; } const combinedIngredients = new Map(); allRecipesToCalculate.forEach(recipe => { const multiplier = recipe.guests; recipe.ingredients.forEach(ing => { const ingName = ing.name || ''; const ingUnit = ing.unit || ''; const key = `${ingName.trim().toLowerCase()}|${ingUnit.trim().toLowerCase()}`; const existing = combinedIngredients.get(key); if (existing) { existing.qty += (ing.quantity || 0) * multiplier; } else { combinedIngredients.set(key, { name: ing.name, qty: (ing.quantity || 0) * multiplier, unit: ing.unit }); } }); }); renderShoppingList(Array.from(combinedIngredients.values())); } catch(error) { alert('Calculation Error: ' + error.message); } }); // --- Initial State --- addIngredientRow(); loadRecipes(); });