{"repo": "bagoadi/athlion", "files": {"frontend/diet.js": {"d41e20b6871487b2a11594fcd13e4f1df7c213b1": {"t": 1785768936.4513454, "n": 25158, "h": "c66582238817fea9", "c": "// =================================================\n// DIET.HTML LOGIKA (VÉGLEGES JAVÍTOTT VERZIÓ)\n// =================================================\n\n// --- ÁLLAPOT (State) ---\nconst token = localStorage.getItem(\"token\");\nlet selectedDate = new Date();\n// DÁTUM JAVÍTÁS: Kezdeti érték beállítása a javított függvénnyel\nlet selectedDateKey = getLocalISODate(selectedDate); \n\nlet activeMealType = 'breakfast'; \nlet dailyLog = {}; \nlet currentWaterState = 0; \nconst mealTitles = { breakfast: 'Reggeli', lunch: 'Ebéd', dinner: 'Vacsora', snacks: 'Nasi' };\nlet currentSelectedFood = null;\n\n// --- JAVÍTOTT DÁTUM FÜGGVÉNY (Időzóna hiba ellen) ---\n// Ez biztosan a helyi (magyar) napot adja vissza, nem az UTC-t.\nfunction getLocalISODate(d) {\n const year = d.getFullYear();\n const month = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n return `${year}-${month}-${day}`;\n}\n\n// Elemek\nconst dayLabel = document.querySelector('#dayLabel');\nconst modal = document.querySelector('#foodSearchModal');\nconst modalTitle = document.querySelector('#modalTitle');\nconst modalQueryInput = document.querySelector('#modalFoodQuery');\nconst modalResults = document.querySelector('#modalFoodResults');\nconst dailyFoodList = document.querySelector('#dailyFoodList');\nconst emptyListMsg = document.querySelector('#emptyListMsg');\n\n// Modal elemek\nconst foodPlaceholder = document.querySelector('#foodSelectionPlaceholder');\nconst foodDetails = document.querySelector('#foodSelectionDetails');\nconst selFoodName = document.querySelector('#selFoodName');\nconst selBaseMacros = document.querySelector('#selBaseMacros');\nconst selQuantity = document.querySelector('#selQuantity');\nconst btnAddSelection = document.querySelector('#btnAddSelection');\n\n// Preview elemek\nconst prevKcal = document.querySelector('#prevKcal');\nconst prevP = document.querySelector('#prevP');\nconst prevC = document.querySelector('#prevC');\nconst prevF = document.querySelector('#prevF');\n\n// --- TOAST ---\nfunction showToast(message, type = 'success') {\n const toast = document.createElement('div');\n toast.className = `custom-toast ${type}`;\n toast.textContent = message;\n document.body.appendChild(toast);\n requestAnimationFrame(() => toast.classList.add('show'));\n setTimeout(() => {\n toast.classList.remove('show');\n setTimeout(() => document.body.removeChild(toast), 300);\n }, 3000);\n}\n\n// --- CONFIRM ---\nfunction showConfirm() {\n const confirmModal = document.getElementById('confirmModal');\n const confirmYes = document.getElementById('confirmYes');\n const confirmNo = document.getElementById('confirmNo');\n\n return new Promise((resolve) => {\n confirmModal.style.display = 'grid';\n confirmYes.onclick = () => {\n confirmModal.style.display = 'none';\n resolve(true);\n };\n confirmNo.onclick = () => {\n confirmModal.style.display = 'none';\n resolve(false);\n };\n });\n}\n\n// =================================================\n// 1. NAPVÁLASZTÓ\n// =================================================\nfunction initDayNavigator() {\n const prevBtn = document.getElementById('dayPrev');\n const nextBtn = document.getElementById('dayNext');\n const todayBtn = document.getElementById('dayToday');\n\n if (!prevBtn) return;\n\n prevBtn.addEventListener('click', () => {\n selectedDate.setDate(selectedDate.getDate() - 1);\n updateDayView();\n });\n nextBtn.addEventListener('click', () => {\n selectedDate.setDate(selectedDate.getDate() + 1);\n updateDayView();\n });\n todayBtn.addEventListener('click', () => {\n selectedDate = new Date();\n updateDayView();\n });\n\n updateDayView();\n}\n\nfunction updateDayView() {\n if (!dayLabel) return;\n \n const today = new Date();\n selectedDateKey = getLocalISODate(selectedDate); // Használjuk a javított függvényt\n \n if (getLocalISODate(today) === selectedDateKey) {\n dayLabel.textContent = \"Mai nap\";\n } else {\n dayLabel.textContent = selectedDate.toLocaleDateString('hu-HU', {\n month: 'short', day: 'numeric', weekday: 'short'\n });\n }\n\n if (token) {\n fetchDailyLog(); \n fetchDailyWater(); \n } else {\n renderDailyFoodList();\n }\n}\n\n// =================================================\n// 2. SÚLY KEZELÉS\n// =================================================\nfunction initWeightControl() {\n const wInput = document.getElementById('weightInput');\n const wDec = document.getElementById('weightDec');\n const wInc = document.getElementById('weightInc');\n const wStatus = document.getElementById('weightSaveStatus');\n \n if (!wInput || !token) return;\n\n fetch(\"/api/v1/weight/latest\", {\n headers: { \"Authorization\": `Bearer ${token}` }\n })\n .then(res => res.ok ? res.json() : null)\n .then(data => {\n if (data && data.weight_kg) {\n wInput.value = data.weight_kg;\n }\n })\n .catch(console.error);\n\n const saveWeight = async (newVal) => {\n if (!newVal || newVal <= 0) return;\n wInput.style.opacity = \"0.7\";\n\n try {\n const todayISO = getLocalISODate(new Date());\n const res = await fetch(\"/api/v1/weight/\", {\n method: \"POST\",\n headers: { \n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${token}` \n },\n body: JSON.stringify({\n weight_kg: parseFloat(newVal),\n date: todayISO\n })\n });\n\n if (res.ok) {\n wStatus.style.opacity = '1';\n setTimeout(() => { wStatus.style.opacity = '0'; }, 2000);\n if (typeof fetchUserGoals === 'function') await fetchUserGoals(); \n }\n } catch (err) { console.error(err); } \n finally { wInput.style.opacity = \"1\"; }\n };\n\n wDec.addEventListener('click', () => {\n let val = parseFloat(wInput.value) || 0;\n val = Math.max(0, val - 0.5);\n wInput.value = val.toFixed(1);\n saveWeight(val);\n });\n\n wInc.addEventListener('click', () => {\n let val = parseFloat(wInput.value) || 0;\n val += 0.5;\n wInput.value = val.toFixed(1);\n saveWeight(val);\n });\n\n wInput.addEventListener('change', () => saveWeight(parseFloat(wInput.value)));\n}\n\n// =================================================\n// 3. VÍZ KEZELÉS (JAVÍTOTT LEKÉRDEZÉSSEL)\n// =================================================\nfunction initWaterControl() {\n const btnDec = document.getElementById('waterDec');\n const btnInc = document.getElementById('waterInc');\n \n if (btnDec && btnInc) {\n btnDec.addEventListener('click', () => changeWater(-250));\n btnInc.addEventListener('click', () => changeWater(250));\n }\n}\n\nasync function fetchDailyWater() {\n if (!token) return;\n \n // 1. Azonnali reset (hogy ne ragadjon be a régi szám)\n currentWaterState = 0;\n updateWaterDisplay();\n \n const dateKey = getLocalISODate(selectedDate);\n \n try {\n // 2. KÉNYSZERÍTETT FRISSÍTÉS (?temp=...)\n // Minden kérés egyedi lesz, így a böngésző nem tudja cache-ből kiszolgálni.\n const url = `/api/v1/water/daily_sum?date_str=${dateKey}&temp=${Date.now()}`;\n \n const res = await fetch(url, {\n headers: { \"Authorization\": `Bearer ${token}` }\n });\n\n if (res.ok) {\n const data = await res.json();\n console.log(`Víz (${dateKey}):`, data.total_ml); // Ellenőrzés a konzolon\n \n currentWaterState = data.total_ml;\n updateWaterDisplay();\n } else {\n console.error(\"Szerver hiba:\", res.status);\n }\n } catch (err) {\n console.error(\"Hálózati hiba:\", err);\n }\n}\n\nasync function changeWater(amount) {\n if (!token) return;\n \n const originalState = currentWaterState;\n currentWaterState = Math.max(0, currentWaterState + amount);\n updateWaterDisplay();\n\n const dateKey = getLocalISODate(selectedDate); // Itt is a javított dátumot küldjük\n\n try {\n const res = await fetch(\"/api/v1/water/add\", {\n method: \"POST\",\n headers: { \n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${token}` \n },\n body: JSON.stringify({\n amount_ml: amount,\n date: dateKey\n })\n });\n\n if (!res.ok) throw new Error(\"Hiba a mentéskor\");\n \n } catch (err) {\n console.error(err);\n currentWaterState = originalState;\n updateWaterDisplay();\n showToast(\"Hiba a víz mentésekor!\", \"error\");\n }\n}\n\nfunction updateWaterDisplay() {\n const disp = document.getElementById('waterValueDisplay');\n const bar = document.getElementById('waterProgressBarSmall');\n \n if (disp) disp.textContent = currentWaterState;\n \n if (bar) {\n const pct = Math.min(100, (currentWaterState / 2500) * 100);\n bar.style.width = `${pct}%`;\n }\n}\n\n// =================================================\n// 4. ÉTKEZÉS MODAL\n// =================================================\nfunction initMealTabs() {\n const tabs = document.querySelectorAll('#mealTabs .meal-tab');\n const closeBtn = document.getElementById('modalCloseBtn');\n\n if (!tabs.length || !modal || !closeBtn) return;\n\n tabs.forEach(tab => {\n tab.addEventListener('click', () => {\n activeMealType = tab.dataset.meal;\n modalTitle.textContent = tab.textContent;\n resetModalRightSide();\n modalQueryInput.value = '';\n modalResults.innerHTML = `
Írj be legalább 3 karaktert.
`;\n modal.style.display = 'grid';\n modalQueryInput.focus();\n });\n });\n\n const closeModal = () => {\n modal.style.display = 'none';\n resetModalRightSide();\n };\n\n closeBtn.addEventListener('click', closeModal);\n modal.addEventListener('click', (e) => { if (e.target === modal) closeModal(); });\n\n document.addEventListener('keydown', (e) => {\n if (modal.style.display === 'none') return;\n if (e.key === 'Escape') { e.preventDefault(); closeModal(); }\n if (e.key === 'Enter') {\n if (document.activeElement === modalQueryInput) return;\n if (currentSelectedFood) { e.preventDefault(); handleAddSelectionClick(); }\n }\n });\n\n modalQueryInput.addEventListener('input', () => doFoodSearch(true));\n if (selQuantity) selQuantity.addEventListener('input', updatePreviewCalculation);\n if (btnAddSelection) btnAddSelection.addEventListener('click', handleAddSelectionClick);\n}\n\nasync function doFoodSearch(isModal = false) {\n if (!isModal) return;\n const q = (modalQueryInput.value || '').toLowerCase().trim();\n if (q.length < 3) {\n modalResults.innerHTML = `Írj be legalább 3 karaktert.
`;\n return;\n }\n modalResults.innerHTML = `