import { foodDatabase } from './foodDatabase.js'; import { getButtonById, getButtonListByClassName, getDivById, getInputById, showFoodPreview } from './HtmlUtil.js'; import { FoodItem, FoodStorage } from './types.js'; // App state let selectedDate = new Date().toISOString().split('T')[0]; let currentViewDate = new Date(); // Initialize the app const init = () => { populateFoodSelect(); updateCurrentDate(); loadDayData(selectedDate); renderCalendar(); addEvents(); } const getFoodProportion = (grams: number, foodData: FoodItem): FoodItem => { const multiplier = grams / 100; // Database values are per 100g return { ...foodData, info: { calories: Math.round(foodData.info.calories * multiplier), protein: Math.round(foodData.info.protein * multiplier * 10) / 10, fat: Math.round(foodData.info.fat * multiplier * 10) / 10, carbs: Math.round(foodData.info.carbs * multiplier * 10) / 10, fiber: Math.round(foodData.info.fiber * multiplier * 10) / 10 } }; } const getFoodItemByName = (foodName: string): FoodItem => { const foodDataSearch: FoodItem[] = foodDatabase.filter(f => f.name === foodName); if (foodDataSearch.length === 0) { throw new Error(`Food not found for name ${name}`); } return foodDataSearch[0]; } const previewCalories = () => { const foodSelect = getInputById('foodSelect'); const gramAmount = getInputById('gramAmount'); if (!foodSelect.value) { showFoodPreview(false); return; } let grams = 100; if (gramAmount && gramAmount.value && parseFloat(gramAmount.value) > 0) { grams = parseFloat(gramAmount.value); } const foodData: FoodItem = getFoodItemByName(foodSelect.value); const proportion = getFoodProportion(grams, foodData); const textArray: string[] = []; textArray.push(`Calories in ${grams}g: ${proportion.info.calories}; `); textArray.push(`Protein: ${proportion.info.protein}g; `); textArray.push(`Fat: ${proportion.info.fat}g; `); textArray.push(`Carbohydrates: ${proportion.info.carbs}g; `); textArray.push(`Fiber: ${proportion.info.fiber}g;`); getDivById('food-preview').innerHTML = textArray.join(''); showFoodPreview(true); } const addEvents = () => { getInputById('foodSelect').addEventListener('change', () => { previewCalories(); }); getInputById('gramAmount')?.addEventListener('change', () => { previewCalories(); }); getButtonById('add-food-btn').addEventListener('click', () => { addFood(); }); getButtonById('next-month-btn').addEventListener('click', () => { nextMonth(); }); getButtonById('previous-month-btn').addEventListener('click', () => { previousMonth(); }); } const addDeleteEvents = () => { const elements = getButtonListByClassName('delete-food-entry'); Array.from(elements).forEach((el: HTMLButtonElement) => { el.addEventListener('click', (e) => { const target = e.target as HTMLElement; const row = target.closest('tr'); const entryId = row?.querySelector('.hidden-column')?.textContent; const entryIdNumber = entryId ? parseInt(entryId) : 0; if (entryIdNumber) { deleteEntry(selectedDate, entryIdNumber); } }); }); } // Populate food select dropdown const populateFoodSelect = () => { const select = getInputById('foodSelect'); select.innerHTML = ''; const sortedFoods = foodDatabase.sort((f1, f2) => f1.name.localeCompare(f2.name)); sortedFoods.forEach((food: FoodItem) => { const option = document.createElement('option') as HTMLOptionElement; option.value = food.name; option.textContent = food.name; select.appendChild(option); }); } // Update current date display const updateCurrentDate = () => { const date = new Date(selectedDate); getDivById('currentDate').textContent = date.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }); } // Add food to the log const addFood = () => { const foodSelect = getInputById('foodSelect'); const gramAmount = getInputById('gramAmount'); if (!foodSelect.value || !gramAmount.value) { alert('Please select a food item and enter amount'); return; } const grams: number = parseFloat(gramAmount.value); const foodData: FoodItem = getFoodItemByName(foodSelect.value); // Calculate nutrition for the amount const proportion: FoodItem = getFoodProportion(grams, foodData); const entry: FoodStorage = { id: Date.now(), name: foodSelect.value, grams: grams, calories: proportion.info.calories, protein: proportion.info.protein, fat: proportion.info.fat, carbs: proportion.info.carbs, fiber: proportion.info.fiber, time: new Date().toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit' }) }; // Save to localStorage const dayData = getDayData(selectedDate); dayData.push(entry); saveDayData(selectedDate, dayData); // Update display loadDayData(selectedDate); renderCalendar(); // Reset form foodSelect.value = ''; gramAmount.value = '100'; showFoodPreview(false); } // Get day data from localStorage const getDayData = (date: string): FoodStorage[] => { const key = `calories_${date}`; const saved = localStorage.getItem(key); if (!saved) { return []; } return JSON.parse(saved); } // Save day data to localStorage const saveDayData = (date: string, data: FoodStorage[]) => { const key = `calories_${date}`; localStorage.setItem(key, JSON.stringify(data)); } // Load and display day data const loadDayData = (date: string) => { const dayData = getDayData(date); // Update counters let totalCalories = 0; let totalProtein = 0; let totalFat = 0; let totalCarbs = 0; let totalFiber = 0; dayData.forEach(entry => { totalCalories += entry.calories; totalProtein += entry.protein; totalFat += entry.fat; totalCarbs += entry.carbs; totalFiber += entry.fiber; }); getDivById('caloriesCounter').textContent = totalCalories.toString(); getDivById('proteinValue').textContent = (Math.round(totalProtein * 10) / 10).toString (); getDivById('fatValue').textContent = (Math.round(totalFat * 10) / 10).toString (); getDivById('carboValue').textContent = (Math.round(totalCarbs * 10) / 10).toString (); getDivById('fiberValue').textContent = (Math.round(totalFiber * 10) / 10).toString (); // Update table const tbody = document.getElementById('foodTableBody'); if (!tbody) { throw Error('Unable to create row tables!'); } tbody.innerHTML = ''; dayData.forEach(entry => { const row = document.createElement('tr'); row.innerHTML = `