|
|
@@ -516,6 +516,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
if (totalProEl) totalProEl.textContent = '0';
|
|
|
if (totalFatEl) totalFatEl.textContent = '0';
|
|
|
if (totalCarbEl) totalCarbEl.textContent = '0';
|
|
|
+
|
|
|
+ const saveBtn = document.getElementById('save-meal-btn');
|
|
|
+ if (saveBtn) saveBtn.style.display = 'none';
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -554,6 +557,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
if (totalProEl) animateValue(totalProEl, data.macros.protein_g);
|
|
|
if (totalFatEl) animateValue(totalFatEl, data.macros.fat_g);
|
|
|
if (totalCarbEl) animateValue(totalCarbEl, data.macros.carbs_g);
|
|
|
+
|
|
|
+ // Show Save button (Sprint 8)
|
|
|
+ const saveBtn = document.getElementById('save-meal-btn');
|
|
|
+ if (saveBtn) saveBtn.style.display = 'flex';
|
|
|
} else {
|
|
|
if (totalsBanner) totalsBanner.classList.add('has-error');
|
|
|
}
|
|
|
@@ -876,4 +883,84 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
|
|
// Initialize state
|
|
|
sendBtn.disabled = true;
|
|
|
+
|
|
|
+ // --- Saved Meals Logic (Sprint 8) ---
|
|
|
+ const saveMealModal = document.getElementById('save-meal-modal');
|
|
|
+ const openSaveModalBtn = document.getElementById('save-meal-btn');
|
|
|
+ const cancelSaveBtn = document.getElementById('cancel-save-btn');
|
|
|
+ const confirmSaveBtn = document.getElementById('confirm-save-btn');
|
|
|
+ const mealNameInput = document.getElementById('meal-name-input');
|
|
|
+ const saveMealError = document.getElementById('save-meal-error');
|
|
|
+
|
|
|
+ if (openSaveModalBtn) {
|
|
|
+ openSaveModalBtn.addEventListener('click', (e) => {
|
|
|
+ e.stopPropagation();
|
|
|
+ if (currentMealItems.length === 0) return;
|
|
|
+ saveMealModal.style.display = 'flex';
|
|
|
+ mealNameInput.value = '';
|
|
|
+ saveMealError.textContent = '';
|
|
|
+ mealNameInput.focus();
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ const closeSaveModal = () => {
|
|
|
+ saveMealModal.style.display = 'none';
|
|
|
+ };
|
|
|
+
|
|
|
+ if (cancelSaveBtn) cancelSaveBtn.addEventListener('click', closeSaveModal);
|
|
|
+
|
|
|
+ if (confirmSaveBtn) {
|
|
|
+ confirmSaveBtn.addEventListener('click', async () => {
|
|
|
+ const name = mealNameInput.value.trim();
|
|
|
+ if (!name) {
|
|
|
+ saveMealError.textContent = 'Please enter a name for your meal.';
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ confirmSaveBtn.disabled = true;
|
|
|
+ confirmSaveBtn.textContent = 'Saving...';
|
|
|
+
|
|
|
+ try {
|
|
|
+ const token = localStorage.getItem('localFoodToken');
|
|
|
+ const response = await fetch('/api/meals', {
|
|
|
+ method: 'POST',
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'application/json',
|
|
|
+ 'Authorization': `Bearer ${token}`
|
|
|
+ },
|
|
|
+ body: JSON.stringify({
|
|
|
+ name: name,
|
|
|
+ items: currentMealItems.map(item => ({
|
|
|
+ food_id: item.id,
|
|
|
+ amount_g: item.amount
|
|
|
+ }))
|
|
|
+ })
|
|
|
+ });
|
|
|
+
|
|
|
+ if (response.ok) {
|
|
|
+ closeSaveModal();
|
|
|
+ addMessage('system', `✅ Successfully saved "${name}" to your dashboard!`);
|
|
|
+
|
|
|
+ // Trigger a refresh of the dashboard if it's open
|
|
|
+ if (window.refreshDashboard) window.refreshDashboard();
|
|
|
+ } else {
|
|
|
+ const data = await response.json();
|
|
|
+ saveMealError.textContent = data.detail || 'Failed to save meal.';
|
|
|
+ }
|
|
|
+ } catch (err) {
|
|
|
+ console.error('Save meal error:', err);
|
|
|
+ saveMealError.textContent = 'Server error. Please try again.';
|
|
|
+ } finally {
|
|
|
+ confirmSaveBtn.disabled = false;
|
|
|
+ confirmSaveBtn.textContent = 'Save to Dashboard';
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // Close modal on outside click
|
|
|
+ window.addEventListener('click', (e) => {
|
|
|
+ if (e.target === saveMealModal) {
|
|
|
+ closeSaveModal();
|
|
|
+ }
|
|
|
+ });
|
|
|
});
|