|
@@ -963,4 +963,92 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
closeSaveModal();
|
|
closeSaveModal();
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
|
|
+
|
|
|
|
|
+ // --- Dashboard Logic (Sprint 8) ---
|
|
|
|
|
+ const dashboardOverlay = document.getElementById('dashboard-overlay');
|
|
|
|
|
+ const openDashboardBtn = document.getElementById('nav-dashboard-btn');
|
|
|
|
|
+ const closeDashboardBtn = document.getElementById('close-dashboard-btn');
|
|
|
|
|
+ const dashboardGrid = document.getElementById('dashboard-grid');
|
|
|
|
|
+ const dashboardEmptyMsg = document.getElementById('dashboard-empty-msg');
|
|
|
|
|
+
|
|
|
|
|
+ const toggleDashboard = (show) => {
|
|
|
|
|
+ if (show) {
|
|
|
|
|
+ dashboardOverlay.style.display = 'flex';
|
|
|
|
|
+ loadSavedMeals();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ dashboardOverlay.style.display = 'none';
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ if (openDashboardBtn) openDashboardBtn.addEventListener('click', () => toggleDashboard(true));
|
|
|
|
|
+ if (closeDashboardBtn) closeDashboardBtn.addEventListener('click', () => toggleDashboard(false));
|
|
|
|
|
+
|
|
|
|
|
+ async function loadSavedMeals() {
|
|
|
|
|
+ dashboardGrid.innerHTML = '<div class="search-loading">Loading your meals...</div>';
|
|
|
|
|
+ dashboardEmptyMsg.style.display = 'none';
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const token = localStorage.getItem('localFoodToken');
|
|
|
|
|
+ const response = await fetch('/api/meals', {
|
|
|
|
|
+ headers: { 'Authorization': `Bearer ${token}` }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if (response.ok) {
|
|
|
|
|
+ const data = await response.json();
|
|
|
|
|
+ renderDashboard(data.meals);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ dashboardGrid.innerHTML = '<div class="error-text">Failed to load meals.</div>';
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (err) {
|
|
|
|
|
+ console.error('Dashboard load error:', err);
|
|
|
|
|
+ dashboardGrid.innerHTML = '<div class="error-text">Connection error.</div>';
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function renderDashboard(meals) {
|
|
|
|
|
+ dashboardGrid.innerHTML = '';
|
|
|
|
|
+ if (!meals || meals.length === 0) {
|
|
|
|
|
+ dashboardEmptyMsg.style.display = 'block';
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ meals.forEach((meal, index) => {
|
|
|
|
|
+ const card = document.createElement('div');
|
|
|
|
|
+ card.className = 'meal-card';
|
|
|
|
|
+ card.style.animationDelay = `${index * 0.07}s`;
|
|
|
|
|
+
|
|
|
|
|
+ const dateStr = new Date(meal.created_at).toLocaleDateString(undefined, {
|
|
|
|
|
+ month: 'short', day: 'numeric', year: 'numeric'
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ card.innerHTML = `
|
|
|
|
|
+ <div class="meal-card-header">
|
|
|
|
|
+ <span class="meal-card-name">${meal.name}</span>
|
|
|
|
|
+ <span class="meal-card-date">${dateStr}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="meal-card-macros">
|
|
|
|
|
+ <div class="card-macro kcal">
|
|
|
|
|
+ <span class="card-macro-val">${Math.round(meal.total_calories)}</span>
|
|
|
|
|
+ <span class="card-macro-lbl">kcal</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="card-macro protein">
|
|
|
|
|
+ <span class="card-macro-val">${Math.round(meal.total_protein)}g</span>
|
|
|
|
|
+ <span class="card-macro-lbl">Protein</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="card-macro carbs">
|
|
|
|
|
+ <span class="card-macro-val">${Math.round(meal.total_carbs)}g</span>
|
|
|
|
|
+ <span class="card-macro-lbl">Carbs</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="card-macro fat">
|
|
|
|
|
+ <span class="card-macro-val">${Math.round(meal.total_fat)}g</span>
|
|
|
|
|
+ <span class="card-macro-lbl">Fat</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ `;
|
|
|
|
|
+ dashboardGrid.appendChild(card);
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Attach refresh helper
|
|
|
|
|
+ window.refreshDashboard = loadSavedMeals;
|
|
|
});
|
|
});
|