// 1. ZDJĘCIA Z DATASETU const hardcodedMeals = [ { name: "Stek z warzywami", image: "/test_images/stek_z_warzywami.jpg", macros: { kcal: 525, p: 48, f: 35, c: 6 } }, { name: "Mini pizza salami", image: "/test_images/mini_pizza_salami.jpg", macros: { kcal: 132, p: 6, f: 6, c: 15 } }, { name: "Jajecznica z brokułem", image: "/test_images/jajecznica_z_brokulem.jpg", macros: { kcal: 296, p: 19, f: 21, c: 7 } }, { name: "Mix sałat", image: "/test_images/miska_salaty.jpg", macros: { kcal: 20, p: 1, f: 0, c: 4 } }, { name: "Bekon", image: "/test_images/bekon.jpg", macros: { kcal: 470, p: 32, f: 36, c: 1 } }, { name: "Owsianka z owocami", image: "/test_images/owsianka_z_owocami.jpg", macros: { kcal: 155, p: 5, f: 3, c: 29 } } ]; // 2. ZDJĘCIA SPOZA DATASETU const externalMeals = [ { name: "Burger drwala", image: "/test_images/burger_drwala.png", macros: { kcal: 915, p: 39, f: 52, c: 70 } }, { name: "Kotelty drobiowe z ziemniakami i sałatą", image: "/test_images/kotelty_z_ziemniakami.jpeg", macros: { kcal: 590, p: 61, f: 11, c: 63 } }, { name: "Spaghetti bolognese", image: "/test_images/spaghetti-bolognese.jpg", macros: { kcal: 405, p: 21, f: 17, c: 43 } }, { name: "SUPER bowl", image: "/test_images/super_bowl.png", macros: { kcal: 716, p: 33, f: 42, c: 60 } } ]; // 3. POSIŁKI UŻYTKOWNIKÓW let userMeals = JSON.parse(localStorage.getItem('savedUserMeals')) || []; let currentFile = null; let currentTruth = null; let activeTab = null; // Słownik do przywracania oryginalnych nazw przycisków const btnOriginalText = { test: "🗂️ Dataset", external: "🌍 Spoza Datasetu", user: "👤 Użytkownik" }; window.onload = () => {}; function openSidebar(tab) { const sidebar = document.getElementById('sidebar'); const btns = { test: document.getElementById('btnTest'), external: document.getElementById('btnExternal'), user: document.getElementById('btnUser') }; // Resetujemy wszystkie przyciski do stanu domyślnego for (let key in btns) { btns[key].classList.remove('open'); btns[key].classList.remove('shifted'); // Usuwamy przesunięcie btns[key].style.backgroundColor = "#333"; btns[key].style.color = "white"; btns[key].innerText = btnOriginalText[key]; } // Jeśli kliknięto aktywny panel -> zamknij i przerwij (wszystko wraca na prawo) if (activeTab === tab && sidebar.classList.contains('open')) { sidebar.classList.remove('open'); activeTab = null; return; } // Otwarcie nowego panelu sidebar.classList.add('open'); activeTab = tab; // Otwarcie nowego panelu sidebar.classList.add('open'); activeTab = tab; // JEŚLI TO TELEFON - ZAMKNIJ PRZYCISKI PO WYBORZE if (window.innerWidth <= 800) { document.getElementById('menuContainer').classList.remove('show'); } // Przesuwamy WSZYSTKIE przyciski na lewo (do krawędzi panelu) for (let key in btns) { btns[key].classList.add('shifted'); } // Stylizacja TYLKO aktywnego przycisku i zmiana tekstu na emotkę btns[tab].classList.add('open'); btns[tab].style.backgroundColor = "#00ff88"; btns[tab].style.color = "#121212"; btns[tab].innerText = "▶︎▶︎▶︎"; // Emotka zastępująca ">>> Zamknij" // Wybór odpowiedniej zawartości do wyświetlenia if (tab === 'test') { renderList(hardcodedMeals, 'test'); } else if (tab === 'external') { renderList(externalMeals, 'external'); } else { renderList(userMeals, 'user'); } } function renderList(mealsArray, type) { const list = document.getElementById('mealsList'); const form = document.getElementById('addMealForm'); const title = document.getElementById('sidebarTitle'); const desc = document.getElementById('sidebarDesc'); list.innerHTML = ""; if (type === 'test') { title.innerText = "Baza Datasetu"; desc.innerText = "Oryginalne posiłki wycięte ze zbioru testowego."; form.style.display = 'none'; if(mealsArray.length === 0) list.innerHTML = "

Brak zdjęć w skrypcie.

"; } else if (type === 'external') { title.innerText = "Spoza Datasetu"; desc.innerText = "Testy na zdjęciach spoza zbioru."; form.style.display = 'none'; if(mealsArray.length === 0) list.innerHTML = "

Brak zewnętrznych zdjęć.

"; } else { title.innerText = "Posiłki Użytkownika"; desc.innerText = "Zapisywane lokalnie w przeglądarce."; form.style.display = 'block'; if(mealsArray.length === 0) list.innerHTML = "

Dodaj pierwszy posiłek poniżej!

"; } mealsArray.forEach((meal, index) => { list.innerHTML += `
Zdjęcie
${meal.name}
🔥 ${meal.macros.kcal} kcal | 🍗 ${meal.macros.p}g | 🥑 ${meal.macros.f}g | 🍞 ${meal.macros.c}g
`; }); } function previewNewImage(event) { if(event.target.files.length === 0) return; currentFile = event.target.files[0]; currentTruth = null; setupPreview(URL.createObjectURL(currentFile), "Tryb: Nieznane zdjęcie (Z dysku)"); } async function loadMealIntoAnalyzer(index, type) { let meal; if (type === 'test') meal = hardcodedMeals[index]; else if (type === 'external') meal = externalMeals[index]; else meal = userMeals[index]; currentTruth = meal.macros; try { const res = await fetch(meal.image); const blob = await res.blob(); currentFile = new File([blob], "test_image.jpg", { type: "image/jpeg" }); setupPreview(meal.image, `Tryb: Ground Truth (${meal.name})`); if(window.innerWidth < 800) openSidebar(activeTab); } catch (err) { alert("Błąd ładowania! Upewnij się, że zdjęcie jest fizycznie w folderze."); } } function setupPreview(imageSrc, modeText) { const preview = document.getElementById('preview'); const modeInd = document.getElementById('modeIndicator'); preview.src = imageSrc; preview.style.display = 'block'; document.getElementById('analyzeBtn').disabled = false; document.getElementById('resultsPanel').style.display = 'none'; modeInd.innerText = modeText; modeInd.style.color = currentTruth ? "#ffaa00" : "#aaa"; } async function analyzeImage() { if (!currentFile) return; const btn = document.getElementById('analyzeBtn'); btn.disabled = true; btn.innerText = "⏳ ONNX analizuje..."; const formData = new FormData(); formData.append("file", currentFile); try { const response = await fetch('/predict-macro', { method: 'POST', body: formData }); const data = await response.json(); displayResults(data.predictions); } catch (error) { alert("Błąd serwera! Upewnij się, że FastAPI działa."); console.error(error); } finally { btn.disabled = false; btn.innerText = "Analizuj Makro"; } } function displayResults(preds) { document.getElementById('res-kcal').innerText = preds.kcal + " kcal"; document.getElementById('res-protein').innerText = preds.protein_g + " g"; document.getElementById('res-fat').innerText = preds.fat_g + " g"; document.getElementById('res-carb').innerText = preds.carb_g + " g"; const truthCols = document.querySelectorAll('.truth-col'); if (currentTruth) { truthCols.forEach(col => col.style.display = 'table-cell'); document.getElementById('truth-kcal').innerText = currentTruth.kcal + " kcal"; document.getElementById('truth-protein').innerText = currentTruth.p + " g"; document.getElementById('truth-fat').innerText = currentTruth.f + " g"; document.getElementById('truth-carb').innerText = currentTruth.c + " g"; document.getElementById('diff-kcal').innerText = Math.abs((preds.kcal - currentTruth.kcal).toFixed(1)) + " kcal"; document.getElementById('diff-protein').innerText = Math.abs((preds.protein_g - currentTruth.p).toFixed(1)) + " g"; document.getElementById('diff-fat').innerText = Math.abs((preds.fat_g - currentTruth.f).toFixed(1)) + " g"; document.getElementById('diff-carb').innerText = Math.abs((preds.carb_g - currentTruth.c).toFixed(1)) + " g"; } else { truthCols.forEach(col => col.style.display = 'none'); } document.getElementById('resultsPanel').style.display = 'block'; } function addUserMeal() { const fileInput = document.getElementById('newMealImage'); const name = document.getElementById('newMealName').value; const kcal = document.getElementById('newMealKcal').value; const p = document.getElementById('newMealP').value; const f = document.getElementById('newMealF').value; const c = document.getElementById('newMealC').value; if(!fileInput.files[0] || !name || !kcal) { alert("Wypełnij nazwę, zdjęcie i chociaż kalorie!"); return; } const reader = new FileReader(); reader.onload = function(e) { const newMeal = { name: name, image: e.target.result, macros: { kcal: kcal, p: p||0, f: f||0, c: c||0 } }; userMeals.push(newMeal); localStorage.setItem('savedUserMeals', JSON.stringify(userMeals)); document.getElementById('newMealName').value = ""; fileInput.value = ""; renderList(userMeals, 'user'); }; reader.readAsDataURL(fileInput.files[0]); } // Obsługa menu na telefonach function toggleMobileMenu() { document.getElementById('menuContainer').classList.toggle('show'); }