feat: organize functions and add type to foods
This commit is contained in:
+6
-6
@@ -221,27 +221,27 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<h1>⚙️ Settings</h1>
|
<h1>⚙️ Settings</h1>
|
||||||
|
|
||||||
<div class="date-display">Define your macros goal</div>
|
<div class="date-display">Define your daily macros goal</div>
|
||||||
|
|
||||||
<form id="settingsForm" class="settings-form">
|
<form id="settingsForm" class="settings-form">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="caloriesGoal">Calories goal</label>
|
<label for="caloriesGoal">Daily calorie goal</label>
|
||||||
<input type="number" id="caloriesGoal" placeholder="Calories" required>
|
<input type="number" id="caloriesGoal" placeholder="Calories" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="proteinGoal">Protein goal</label>
|
<label for="proteinGoal">Daily protein goal</label>
|
||||||
<input type="number" id="proteinGoal" placeholder="Proteins in grams" required>
|
<input type="number" id="proteinGoal" placeholder="Proteins in grams" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="proteinGoal">Fat goal</label>
|
<label for="fatGoal">Daily fat goal</label>
|
||||||
<input type="number" id="fatGoal" placeholder="Fat in grams" required>
|
<input type="number" id="fatGoal" placeholder="Fat in grams" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="proteinGoal">Carbs goal</label>
|
<label for="carboGoal">Daily carbs goal</label>
|
||||||
<input type="number" id="carboGoal" placeholder="Carbo in grams" required>
|
<input type="number" id="carboGoal" placeholder="Carbo in grams" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="proteinGoal">Fiber goal</label>
|
<label for="fiberGoal">Daily fiber goal</label>
|
||||||
<input type="number" id="fiberGoal" placeholder="Fiber in grams" required>
|
<input type="number" id="fiberGoal" placeholder="Fiber in grams" required>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="settings-btn">Save</button>
|
<button type="submit" class="settings-btn">Save</button>
|
||||||
|
|||||||
+110
@@ -0,0 +1,110 @@
|
|||||||
|
import { getDivById } from "./DomUtils";
|
||||||
|
import { appState } from "./state";
|
||||||
|
|
||||||
|
export const SECOND = 1000;
|
||||||
|
export const QUICK_DELAY = 0.3 * SECOND;
|
||||||
|
|
||||||
|
export function showLoading() {
|
||||||
|
getDivById('loading-overlay').classList.remove('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hideLoading() {
|
||||||
|
getDivById('loading-overlay').classList.add('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function scrollToCalendarView() {
|
||||||
|
const calendarSection = document.querySelector('.calendar-section') as HTMLElement;
|
||||||
|
if (calendarSection) {
|
||||||
|
calendarSection.scrollIntoView({
|
||||||
|
behavior: 'smooth',
|
||||||
|
block: 'start'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handleMobileCalendarClick() {
|
||||||
|
closeMobileMenu();
|
||||||
|
scrollToCalendarView();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toggleMobileMenu() {
|
||||||
|
const mobileMenu = document.getElementById('mobileMenu');
|
||||||
|
if (mobileMenu) {
|
||||||
|
mobileMenu.classList.toggle('hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function closeMobileMenu() {
|
||||||
|
const mobileMenu = document.getElementById('mobileMenu');
|
||||||
|
if (mobileMenu) {
|
||||||
|
mobileMenu.classList.add('hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCleanName(foodName: string): string {
|
||||||
|
const newName = foodName
|
||||||
|
.replace(/á/g, 'a')
|
||||||
|
.replace(/ã/g, 'a')
|
||||||
|
.replace(/â/g, 'a')
|
||||||
|
.replace(/ê/g, 'e')
|
||||||
|
.replace(/é/g, 'e')
|
||||||
|
.replace(/ó/g, 'o')
|
||||||
|
.replace(/ú/g, 'u')
|
||||||
|
.replace(/ç/g, 'c');
|
||||||
|
return newName.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function navigateResultsKeyboard(direction: number) {
|
||||||
|
const items = getDivById('searchResults').querySelectorAll('.search-result-item');
|
||||||
|
if (items.length === 0) return;
|
||||||
|
|
||||||
|
// Remove current highlight
|
||||||
|
if (appState.currentHighlightIndex >= 0) {
|
||||||
|
items[appState.currentHighlightIndex].classList.remove('highlighted');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate new index
|
||||||
|
appState.currentHighlightIndex += direction;
|
||||||
|
if (appState.currentHighlightIndex < 0) appState.currentHighlightIndex = items.length - 1;
|
||||||
|
if (appState.currentHighlightIndex >= items.length) appState.currentHighlightIndex = 0;
|
||||||
|
|
||||||
|
// Add new highlight
|
||||||
|
items[appState.currentHighlightIndex].classList.add('highlighted');
|
||||||
|
items[appState.currentHighlightIndex].scrollIntoView({ block: 'nearest' });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hideSearchResults() {
|
||||||
|
getDivById('searchResults').classList.remove('show');
|
||||||
|
appState.currentHighlightIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toggleCardHandler(e: Event) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
const card = e.currentTarget as HTMLElement;
|
||||||
|
card.classList.toggle('expanded');
|
||||||
|
|
||||||
|
const cardDetails = card.nextElementSibling as HTMLElement;
|
||||||
|
if (cardDetails && cardDetails.classList.contains('card-details')) {
|
||||||
|
cardDetails.classList.toggle('expanded');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function delay(seconds: number) {
|
||||||
|
return new Promise(resolve => setTimeout(resolve, seconds * 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getIcon(category: string) {
|
||||||
|
const icons = {
|
||||||
|
'fats': '🥑 🍳 🍟',
|
||||||
|
'proteins': '🫘 🥩 🥚',
|
||||||
|
'carbs (high)': '🍞 🥔 🍠',
|
||||||
|
'leaves': '🥬 🥗 🌿',
|
||||||
|
'fruits': '🍊 🍇 🍎',
|
||||||
|
'carbs (low)': '🥦 🍅 🍓',
|
||||||
|
'dairy': '🧀 🧈 🥛'
|
||||||
|
};
|
||||||
|
|
||||||
|
return icons[category];
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
import { getDivById } from "./DomUtils";
|
||||||
|
|
||||||
|
export function showAuthForms() {
|
||||||
|
getDivById('auth-section').classList.remove('hidden');
|
||||||
|
getDivById('user-info').classList.add('hidden');
|
||||||
|
getDivById('app-content').classList.add('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toggleAuthForms() {
|
||||||
|
document.getElementById('login-form')?.classList.toggle('hidden');
|
||||||
|
document.getElementById('register-form')?.classList.toggle('hidden');
|
||||||
|
|
||||||
|
const logForm = document.getElementById('loginForm') as HTMLFormElement;
|
||||||
|
logForm.reset();
|
||||||
|
|
||||||
|
const resetForm = document.getElementById('registerForm') as HTMLFormElement;
|
||||||
|
resetForm.reset();
|
||||||
|
}
|
||||||
@@ -72,6 +72,8 @@ export const foodDatabase: FoodItem[] = [
|
|||||||
{ name: 'Pão, de queijo, assado', info: { calories: 363, protein: 5.1, fat: 24.6, carbs: 34.2, fiber: 0.6, category: 'carbs (high)', alkaline: false } },
|
{ name: 'Pão, de queijo, assado', info: { calories: 363, protein: 5.1, fat: 24.6, carbs: 34.2, fiber: 0.6, category: 'carbs (high)', alkaline: false } },
|
||||||
{ name: 'Cuscuz, de milho , cozido com sal', info: { calories: 113, protein: 2.2, fat: 0.7, carbs: 25.3, fiber: 2.1, category: 'carbs (high)', alkaline: false } },
|
{ name: 'Cuscuz, de milho , cozido com sal', info: { calories: 113, protein: 2.2, fat: 0.7, carbs: 25.3, fiber: 2.1, category: 'carbs (high)', alkaline: false } },
|
||||||
{ name: 'Paçoca, amendoim', info: { calories: 487, protein: 16, fat: 26.1, carbs: 52.4, fiber: 7.3, category: 'carbs (high)', alkaline: false } },
|
{ name: 'Paçoca, amendoim', info: { calories: 487, protein: 16, fat: 26.1, carbs: 52.4, fiber: 7.3, category: 'carbs (high)', alkaline: false } },
|
||||||
|
{ name: 'Tortelete de mousse chocolate zero Quiero Café', info: { calories: 250, protein: 2.3, fat: 8.9, carbs: 40, fiber: 5, category: 'carbs (high)', alkaline: false } },
|
||||||
|
{ name: 'Pão de beijo com chia e pequi Empório Veggie', info: { calories: 316, protein: 0.6, fat: 14, carbs: 47, fiber: 1, category: 'carbs (high)', alkaline: false } },
|
||||||
|
|
||||||
// Folhas e verduras - Leaves
|
// Folhas e verduras - Leaves
|
||||||
{ name: 'Agrião', info: { calories: 17, protein: 2.7, fat: 0.2, carbs: 2.3, fiber: 2.1, category: 'leaves', alkaline: true } },
|
{ name: 'Agrião', info: { calories: 17, protein: 2.7, fat: 0.2, carbs: 2.3, fiber: 2.1, category: 'leaves', alkaline: true } },
|
||||||
|
|||||||
+67
-232
@@ -1,34 +1,18 @@
|
|||||||
import { foodDatabase } from './foodDatabase.js';
|
import { foodDatabase } from './foodDatabase.js';
|
||||||
import { getButtonById, getButtonListByClassName, getDivById, getInputById, showFoodPreview } from './HtmlUtil.ts';
|
import { getButtonById, getButtonListByClassName, getDivById, getInputById, showFoodPreview } from './DomUtils.ts';
|
||||||
import { DailyTotalCalories, FoodItem, FoodStorage } from './types.js';
|
import { DailyTotalCalories, FoodItem, FoodStorage } from './types.js';
|
||||||
import { AppwriteAuth, AppwriteDB } from './appwrite.js';
|
import { AppwriteAuth, AppwriteDB } from './appwrite.js';
|
||||||
import swal from 'sweetalert';
|
import swal from 'sweetalert';
|
||||||
import { Models } from 'appwrite';
|
import { closeMobileMenu, delay, getCleanName, getIcon, handleMobileCalendarClick, hideLoading, hideSearchResults, navigateResultsKeyboard, QUICK_DELAY, scrollToCalendarView, showLoading, toggleCardHandler, toggleMobileMenu } from './Utils.ts';
|
||||||
|
import { showAuthForms, toggleAuthForms } from './auth.ts';
|
||||||
|
import { appState } from "./state";
|
||||||
|
|
||||||
// App state
|
// App state
|
||||||
let selectedDate = new Date();
|
let selectedDate = new Date();
|
||||||
let currentViewDate = new Date();
|
let currentViewDate = new Date();
|
||||||
let searchTimeout: number | null = null;
|
|
||||||
let selectedFood: FoodItem | null = null; // review here
|
let selectedFood: FoodItem | null = null; // review here
|
||||||
let currentHighlightIndex: number = -1;
|
|
||||||
let currentResults: FoodItem[] = [];
|
|
||||||
let calendarMonthlyCalories: DailyTotalCalories[] = [];
|
|
||||||
|
|
||||||
// Authentication state
|
|
||||||
let currentUser: any | null = null;
|
let currentUser: any | null = null;
|
||||||
|
|
||||||
// DOM Elements
|
|
||||||
const authSection = document.getElementById('auth-section');
|
|
||||||
const userInfo = document.getElementById('user-info');
|
|
||||||
const appContent = document.getElementById('app-content');
|
|
||||||
const settingsContent = document.getElementById('settings-content');
|
|
||||||
const loadingOverlay = getDivById('loading-overlay');
|
|
||||||
const loginForm = document.getElementById('login-form');
|
|
||||||
const registerForm = document.getElementById('register-form');
|
|
||||||
const searchInput = getInputById('foodSearchInput');
|
|
||||||
const searchLoading = document.getElementById('searchLoading');
|
|
||||||
const searchResults = getDivById('searchResults');
|
|
||||||
|
|
||||||
// Initialize when page loads
|
// Initialize when page loads
|
||||||
document.addEventListener('DOMContentLoaded', async function() {
|
document.addEventListener('DOMContentLoaded', async function() {
|
||||||
await initializeAuth();
|
await initializeAuth();
|
||||||
@@ -36,12 +20,10 @@ document.addEventListener('DOMContentLoaded', async function() {
|
|||||||
setupEventListeners();
|
setupEventListeners();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initialize application
|
|
||||||
async function initializeAuth() {
|
async function initializeAuth() {
|
||||||
showLoading();
|
showLoading();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Check if user is already logged in
|
|
||||||
const isLoggedIn = await AppwriteAuth.isLoggedIn();
|
const isLoggedIn = await AppwriteAuth.isLoggedIn();
|
||||||
|
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
@@ -59,20 +41,8 @@ async function initializeAuth() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle between login and register forms
|
|
||||||
function toggleAuthForms() {
|
|
||||||
loginForm?.classList.toggle('hidden');
|
|
||||||
registerForm?.classList.toggle('hidden');
|
|
||||||
|
|
||||||
// Clear form data
|
|
||||||
const logForm = document.getElementById('loginForm') as HTMLFormElement;
|
|
||||||
logForm.reset();
|
|
||||||
|
|
||||||
const resetForm = document.getElementById('registerForm') as HTMLFormElement;
|
|
||||||
resetForm.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle user registration
|
|
||||||
async function handleRegister(e: SubmitEvent) {
|
async function handleRegister(e: SubmitEvent) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
showLoading();
|
showLoading();
|
||||||
@@ -100,7 +70,6 @@ async function handleRegister(e: SubmitEvent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle user login
|
|
||||||
async function handleLogin(e: SubmitEvent) {
|
async function handleLogin(e: SubmitEvent) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
showLoading();
|
showLoading();
|
||||||
@@ -141,12 +110,10 @@ async function fetchUserSettings(documentId: string): Promise<any> {
|
|||||||
return AppwriteDB.deleteUserSettings(documentId);
|
return AppwriteDB.deleteUserSettings(documentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main function that processes the response
|
|
||||||
async function handleBulkDelete(idsToDelete: string[]): Promise<void> {
|
async function handleBulkDelete(idsToDelete: string[]): Promise<void> {
|
||||||
try {
|
try {
|
||||||
// This creates and executes all promises concurrently
|
// This creates and executes all promises concurrently
|
||||||
const results = await processResponseItems(idsToDelete, fetchUserSettings);
|
const results = await processResponseItems(idsToDelete, fetchUserSettings);
|
||||||
|
|
||||||
console.debug('All requests completed:', results);
|
console.debug('All requests completed:', results);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('One or more requests failed:', error);
|
console.error('One or more requests failed:', error);
|
||||||
@@ -175,7 +142,6 @@ async function handleSaveSettings(e: SubmitEvent) {
|
|||||||
await handleBulkDelete(documentsToDelete);
|
await handleBulkDelete(documentsToDelete);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save to Appwrite
|
|
||||||
await AppwriteDB.saveUserSettings({
|
await AppwriteDB.saveUserSettings({
|
||||||
caloriesGoal: parseInt(caloriesGoal),
|
caloriesGoal: parseInt(caloriesGoal),
|
||||||
proteinGoal: parseInt(proteinGoal),
|
proteinGoal: parseInt(proteinGoal),
|
||||||
@@ -185,7 +151,7 @@ async function handleSaveSettings(e: SubmitEvent) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
hideLoading();
|
hideLoading();
|
||||||
handleSettings();
|
toggleSettingsView();
|
||||||
selectDate(selectedDate);
|
selectDate(selectedDate);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
@@ -210,14 +176,13 @@ async function handleLogout() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleSettings() {
|
async function toggleSettingsView() {
|
||||||
const showSettings = getButtonById('settingsBtn').textContent.includes('Settings');
|
const showSettings = getButtonById('settingsBtn').textContent.includes('Settings');
|
||||||
|
|
||||||
if (showSettings) {
|
if (showSettings) {
|
||||||
showLoading();
|
showLoading();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Fetch goals from settings
|
|
||||||
const settings = await AppwriteDB.getUserSettings();
|
const settings = await AppwriteDB.getUserSettings();
|
||||||
const hasGoals = Array.isArray(settings) && settings.length > 0;
|
const hasGoals = Array.isArray(settings) && settings.length > 0;
|
||||||
if (hasGoals) {
|
if (hasGoals) {
|
||||||
@@ -238,8 +203,8 @@ async function handleSettings() {
|
|||||||
getButtonById('settingsBtn').textContent = '🔙 Back';
|
getButtonById('settingsBtn').textContent = '🔙 Back';
|
||||||
getButtonById('settingsBtnMobile').textContent = '🔙 Back';
|
getButtonById('settingsBtnMobile').textContent = '🔙 Back';
|
||||||
|
|
||||||
appContent?.classList.add('hidden');
|
getDivById('app-content').classList.add('hidden');
|
||||||
settingsContent?.classList.remove('hidden');
|
getDivById('settings-content').classList.remove('hidden');
|
||||||
hideLoading();
|
hideLoading();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
@@ -248,73 +213,30 @@ async function handleSettings() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
appContent?.classList.remove('hidden');
|
getDivById('app-content').classList.remove('hidden');
|
||||||
settingsContent?.classList.add('hidden');
|
getDivById('settings-content').classList.add('hidden');
|
||||||
getButtonById('settingsBtn').textContent = '⚙️ Settings';
|
getButtonById('settingsBtn').textContent = '⚙️ Settings';
|
||||||
getButtonById('settingsBtnMobile').textContent = '⚙️ Settings';
|
getButtonById('settingsBtnMobile').textContent = '⚙️ Settings';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle settings for mobile (same logic but different button)
|
async function handleMobileSettingsClick() {
|
||||||
async function handleSettingsMobile() {
|
|
||||||
closeMobileMenu();
|
closeMobileMenu();
|
||||||
await handleSettings();
|
await toggleSettingsView();
|
||||||
}
|
|
||||||
|
|
||||||
// Handle calendar button - scroll to calendar section
|
|
||||||
function handleCalendar() {
|
|
||||||
const calendarSection = document.querySelector('.calendar-section') as HTMLElement;
|
|
||||||
if (calendarSection) {
|
|
||||||
calendarSection.scrollIntoView({
|
|
||||||
behavior: 'smooth',
|
|
||||||
block: 'start'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle calendar for mobile
|
|
||||||
function handleCalendarMobile() {
|
|
||||||
closeMobileMenu();
|
|
||||||
handleCalendar();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Toggle mobile menu
|
|
||||||
function toggleMobileMenu() {
|
|
||||||
const mobileMenu = document.getElementById('mobileMenu');
|
|
||||||
if (mobileMenu) {
|
|
||||||
mobileMenu.classList.toggle('hidden');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close mobile menu
|
|
||||||
function closeMobileMenu() {
|
|
||||||
const mobileMenu = document.getElementById('mobileMenu');
|
|
||||||
if (mobileMenu) {
|
|
||||||
mobileMenu.classList.add('hidden');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show authentication forms
|
|
||||||
function showAuthForms() {
|
|
||||||
authSection?.classList.remove('hidden');
|
|
||||||
userInfo?.classList.add('hidden');
|
|
||||||
appContent?.classList.add('hidden');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function showMainApp() {
|
async function showMainApp() {
|
||||||
authSection?.classList.add('hidden');
|
getDivById('auth-section').classList.add('hidden');
|
||||||
userInfo?.classList.remove('hidden');
|
getDivById('user-info').classList.remove('hidden');
|
||||||
appContent?.classList.remove('hidden');
|
getDivById('app-content').classList.remove('hidden');
|
||||||
|
|
||||||
// Update user info display
|
|
||||||
if (currentUser) {
|
if (currentUser) {
|
||||||
getDivById('userName').textContent = `Welcome, ${currentUser.name}!`;
|
getDivById('userName').textContent = `Welcome, ${currentUser.name}!`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update date display
|
|
||||||
updateCurrentDate();
|
updateCurrentDate();
|
||||||
|
|
||||||
// Get entries with total
|
// Get daily entries with total from Appwrite to display in calendar
|
||||||
const entries = await AppwriteDB.getMonthlyCalories(selectedDate);
|
const entries = await AppwriteDB.getMonthlyCalories(selectedDate);
|
||||||
entries.forEach((entry) => {
|
entries.forEach((entry) => {
|
||||||
const calories = parseInt(entry.totalCalories);
|
const calories = parseInt(entry.totalCalories);
|
||||||
@@ -323,17 +245,8 @@ async function showMainApp() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show/hide loading overlay
|
|
||||||
function showLoading() {
|
|
||||||
loadingOverlay.classList.remove('hidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideLoading() {
|
|
||||||
loadingOverlay.classList.add('hidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearEditing() {
|
function clearEditing() {
|
||||||
searchInput.value = '';
|
getInputById('foodSearchInput').value = '';
|
||||||
getInputById('gramAmount').value = '100';
|
getInputById('gramAmount').value = '100';
|
||||||
showFoodPreview(false);
|
showFoodPreview(false);
|
||||||
getDivById('add-foot-title').innerHTML = 'Add Food Entry';
|
getDivById('add-foot-title').innerHTML = 'Add Food Entry';
|
||||||
@@ -456,13 +369,13 @@ const setupEventListeners = () => {
|
|||||||
|
|
||||||
// Desktop header buttons
|
// Desktop header buttons
|
||||||
document.getElementById('logoutBtn')?.addEventListener('click', handleLogout);
|
document.getElementById('logoutBtn')?.addEventListener('click', handleLogout);
|
||||||
document.getElementById('settingsBtn')?.addEventListener('click', handleSettings);
|
document.getElementById('settingsBtn')?.addEventListener('click', toggleSettingsView);
|
||||||
document.getElementById('calendarBtn')?.addEventListener('click', handleCalendar);
|
document.getElementById('calendarBtn')?.addEventListener('click', scrollToCalendarView);
|
||||||
|
|
||||||
// Mobile header buttons
|
// Mobile header buttons
|
||||||
document.getElementById('logoutBtnMobile')?.addEventListener('click', handleLogout);
|
document.getElementById('logoutBtnMobile')?.addEventListener('click', handleLogout);
|
||||||
document.getElementById('settingsBtnMobile')?.addEventListener('click', handleSettingsMobile);
|
document.getElementById('settingsBtnMobile')?.addEventListener('click', handleMobileSettingsClick);
|
||||||
document.getElementById('calendarBtnMobile')?.addEventListener('click', handleCalendarMobile);
|
document.getElementById('calendarBtnMobile')?.addEventListener('click', handleMobileCalendarClick);
|
||||||
|
|
||||||
// Mobile menu toggle
|
// Mobile menu toggle
|
||||||
document.getElementById('mobileMenuToggle')?.addEventListener('click', toggleMobileMenu);
|
document.getElementById('mobileMenuToggle')?.addEventListener('click', toggleMobileMenu);
|
||||||
@@ -471,7 +384,7 @@ const setupEventListeners = () => {
|
|||||||
document.getElementById('settingsForm')?.addEventListener('submit', handleSaveSettings);
|
document.getElementById('settingsForm')?.addEventListener('submit', handleSaveSettings);
|
||||||
|
|
||||||
// Search functionality
|
// Search functionality
|
||||||
searchInput.addEventListener('input', function(e: Event) {
|
getInputById('foodSearchInput').addEventListener('input', function(e: Event) {
|
||||||
const target = e.target as HTMLInputElement;
|
const target = e.target as HTMLInputElement;
|
||||||
const query = target.value.trim();
|
const query = target.value.trim();
|
||||||
|
|
||||||
@@ -481,36 +394,36 @@ const setupEventListeners = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Show loading
|
// Show loading
|
||||||
searchLoading?.classList.add('show');
|
getDivById('searchLoading').classList.add('show');
|
||||||
|
|
||||||
// Clear previous timeout
|
// Clear previous timeout
|
||||||
if (searchTimeout) {
|
if (appState.searchTimeout) {
|
||||||
clearTimeout(searchTimeout);
|
clearTimeout(appState.searchTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debounce search
|
// Debounce search
|
||||||
searchTimeout = setTimeout(() => {
|
appState.searchTimeout = setTimeout(() => {
|
||||||
performSearch(query);
|
performSearch(query);
|
||||||
}, 300);
|
}, 300);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Keyboard navigation
|
// Keyboard navigation
|
||||||
searchInput?.addEventListener('keydown', function(e) {
|
getInputById('foodSearchInput').addEventListener('keydown', function(e) {
|
||||||
if (!searchResults?.classList.contains('show')) return;
|
if (!getDivById('searchResults').classList.contains('show')) return;
|
||||||
|
|
||||||
switch(e.key) {
|
switch(e.key) {
|
||||||
case 'ArrowDown':
|
case 'ArrowDown':
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
navigateResults(1);
|
navigateResultsKeyboard(1);
|
||||||
break;
|
break;
|
||||||
case 'ArrowUp':
|
case 'ArrowUp':
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
navigateResults(-1);
|
navigateResultsKeyboard(-1);
|
||||||
break;
|
break;
|
||||||
case 'Enter':
|
case 'Enter':
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (currentHighlightIndex >= 0 && currentResults[currentHighlightIndex]) {
|
if (appState.currentHighlightIndex >= 0 && appState.searchResults[appState.currentHighlightIndex]) {
|
||||||
selectFood(currentResults[currentHighlightIndex]);
|
selectFood(appState.searchResults[appState.currentHighlightIndex]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'Escape':
|
case 'Escape':
|
||||||
@@ -522,7 +435,7 @@ const setupEventListeners = () => {
|
|||||||
// Click outside to close search results
|
// Click outside to close search results
|
||||||
document.addEventListener('click', function(e: Event) {
|
document.addEventListener('click', function(e: Event) {
|
||||||
const target = e.target as HTMLElement;
|
const target = e.target as HTMLElement;
|
||||||
if (!searchResults.contains(target) && !searchInput.contains(target)) {
|
if (!getDivById('searchResults').contains(target) && !getInputById('foodSearchInput').contains(target)) {
|
||||||
hideSearchResults();
|
hideSearchResults();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -541,52 +454,26 @@ const setupEventListeners = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const getCleanName = (foodName: string): string => {
|
|
||||||
const newName = foodName
|
|
||||||
.replace(/á/g, 'a')
|
|
||||||
.replace(/ã/g, 'a')
|
|
||||||
.replace(/â/g, 'a')
|
|
||||||
.replace(/ê/g, 'e')
|
|
||||||
.replace(/é/g, 'e')
|
|
||||||
.replace(/ó/g, 'o')
|
|
||||||
.replace(/ú/g, 'u')
|
|
||||||
.replace(/ç/g, 'c');
|
|
||||||
return newName.toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform search
|
|
||||||
function performSearch(query: string) {
|
function performSearch(query: string) {
|
||||||
// Simulate API call - replace with your actual database search
|
|
||||||
const results: FoodItem[] = foodDatabase.filter(food => {
|
const results: FoodItem[] = foodDatabase.filter(food => {
|
||||||
const cleanName = getCleanName(food.name);
|
const cleanName = getCleanName(food.name);
|
||||||
const category = food.info.category.toLowerCase();
|
const category = food.info.category.toLowerCase();
|
||||||
return cleanName.includes(query.toLowerCase()) || category.includes(query.toLowerCase())
|
return cleanName.includes(query.toLowerCase()) || category.includes(query.toLowerCase())
|
||||||
}).slice(0, 5); // Limit to 5 results
|
}).slice(0, 5); // Limit to 5 results
|
||||||
|
|
||||||
currentResults = results;
|
appState.searchResults = results;
|
||||||
displaySearchResults(results);
|
displaySearchResults(results);
|
||||||
searchLoading?.classList.remove('show');
|
getDivById('searchLoading').classList.remove('show');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display search results
|
|
||||||
function displaySearchResults(results: FoodItem[]) {
|
function displaySearchResults(results: FoodItem[]) {
|
||||||
if (results.length === 0) {
|
if (results.length === 0) {
|
||||||
searchResults.innerHTML = '<div class="no-results">No foods found. Try a different search term.</div>';
|
getDivById('searchResults').innerHTML = '<div class="no-results">No foods found. Try a different search term.</div>';
|
||||||
} else {
|
} else {
|
||||||
const icons = {
|
getDivById('searchResults').innerHTML = results.map((food, index) => `
|
||||||
'fats': '🥑 🍳 🍟',
|
|
||||||
'proteins': '🫘 🥩 🥚',
|
|
||||||
'carbs (high)': '🍞 🥔 🍠',
|
|
||||||
'leaves': '🥬 🥗 🌿',
|
|
||||||
'fruits': '🍊 🍇 🍎',
|
|
||||||
'carbs (low)': '🥦 🍅 🍓',
|
|
||||||
'dairy': '🧀 🧈 🥛'
|
|
||||||
};
|
|
||||||
|
|
||||||
searchResults.innerHTML = results.map((food, index) => `
|
|
||||||
<div class="search-result-item" data-index="${index}" onclick="selectFood(${JSON.stringify(food).replace(/"/g, '"')})">
|
<div class="search-result-item" data-index="${index}" onclick="selectFood(${JSON.stringify(food).replace(/"/g, '"')})">
|
||||||
<div class="food-info">
|
<div class="food-info">
|
||||||
<div class="food-name">${icons[food.info.category]} ${food.name}</div>
|
<div class="food-name">${getIcon(food.info.category)} ${food.name}</div>
|
||||||
<div class="food-details">${food.info.category} • 100 g</div>
|
<div class="food-details">${food.info.category} • 100 g</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="food-calories">${food.info.calories} cal</div>
|
<div class="food-calories">${food.info.calories} cal</div>
|
||||||
@@ -594,42 +481,16 @@ function displaySearchResults(results: FoodItem[]) {
|
|||||||
`).join('');
|
`).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
searchResults.classList.add('show');
|
getDivById('searchResults').classList.add('show');
|
||||||
currentHighlightIndex = -1;
|
appState.currentHighlightIndex = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Navigate results with keyboard
|
|
||||||
function navigateResults(direction: number) {
|
|
||||||
const items = searchResults.querySelectorAll('.search-result-item');
|
|
||||||
if (items.length === 0) return;
|
|
||||||
|
|
||||||
// Remove current highlight
|
|
||||||
if (currentHighlightIndex >= 0) {
|
|
||||||
items[currentHighlightIndex].classList.remove('highlighted');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate new index
|
|
||||||
currentHighlightIndex += direction;
|
|
||||||
if (currentHighlightIndex < 0) currentHighlightIndex = items.length - 1;
|
|
||||||
if (currentHighlightIndex >= items.length) currentHighlightIndex = 0;
|
|
||||||
|
|
||||||
// Add new highlight
|
|
||||||
items[currentHighlightIndex].classList.add('highlighted');
|
|
||||||
items[currentHighlightIndex].scrollIntoView({ block: 'nearest' });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Select food
|
|
||||||
function selectFood(food: FoodItem) {
|
function selectFood(food: FoodItem) {
|
||||||
selectedFood = food;
|
selectedFood = food;
|
||||||
|
|
||||||
// Clear search and hide results
|
getInputById('foodSearchInput').value = food.name;
|
||||||
searchInput.value = food.name;
|
|
||||||
hideSearchResults();
|
hideSearchResults();
|
||||||
|
|
||||||
// Focus on quantity input
|
|
||||||
getInputById('gramAmount').focus();
|
getInputById('gramAmount').focus();
|
||||||
|
|
||||||
// Update calories
|
|
||||||
previewCalories(food);
|
previewCalories(food);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -648,7 +509,7 @@ async function setFoodToEdit(foodId: string) {
|
|||||||
// set the selected food name and quantity
|
// set the selected food name and quantity
|
||||||
const foodData: FoodItem = getFoodItemByName(foodToEdit[0].name);
|
const foodData: FoodItem = getFoodItemByName(foodToEdit[0].name);
|
||||||
selectedFood = foodData;
|
selectedFood = foodData;
|
||||||
searchInput.value = foodToEdit[0].name;
|
getInputById('foodSearchInput').value = foodToEdit[0].name;
|
||||||
getInputById('gramAmount').value = foodToEdit[0].grams;
|
getInputById('gramAmount').value = foodToEdit[0].grams;
|
||||||
previewCalories(foodData)
|
previewCalories(foodData)
|
||||||
|
|
||||||
@@ -676,25 +537,6 @@ async function setFoodToEdit(foodId: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide search results
|
|
||||||
function hideSearchResults() {
|
|
||||||
searchResults.classList.remove('show');
|
|
||||||
currentHighlightIndex = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleCardHandler(e: Event) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
const card = e.currentTarget as HTMLElement;
|
|
||||||
card.classList.toggle('expanded');
|
|
||||||
|
|
||||||
const cardDetails = card.nextElementSibling as HTMLElement;
|
|
||||||
if (cardDetails && cardDetails.classList.contains('card-details')) {
|
|
||||||
cardDetails.classList.toggle('expanded');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteCardHandler(e: Event) {
|
function deleteCardHandler(e: Event) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@@ -719,7 +561,7 @@ function editCardHandler(e: Event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const addDeleteEvents = () => {
|
const setupEditAndDeleteEvents = () => {
|
||||||
// Setup toggle show cards events
|
// Setup toggle show cards events
|
||||||
const cards = getButtonListByClassName('card-header-toggle');
|
const cards = getButtonListByClassName('card-header-toggle');
|
||||||
Array.from(cards).forEach((card: HTMLElement) => {
|
Array.from(cards).forEach((card: HTMLElement) => {
|
||||||
@@ -742,7 +584,6 @@ const addDeleteEvents = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update current date display
|
|
||||||
const updateCurrentDate = () => {
|
const updateCurrentDate = () => {
|
||||||
const date = new Date(selectedDate);
|
const date = new Date(selectedDate);
|
||||||
getDivById('currentDate').textContent = date.toLocaleDateString('en-US', {
|
getDivById('currentDate').textContent = date.toLocaleDateString('en-US', {
|
||||||
@@ -805,7 +646,7 @@ const updateFood = async () => {
|
|||||||
const monthlyUpdated = await AppwriteDB.updateMonthlyCaloryForDay(monthlyDocumentId?.documentId, selectedDate, totalCalories);
|
const monthlyUpdated = await AppwriteDB.updateMonthlyCaloryForDay(monthlyDocumentId?.documentId, selectedDate, totalCalories);
|
||||||
updateDocumentIdForToday(monthlyUpdated.$id, monthlyUpdated.totalCalories);
|
updateDocumentIdForToday(monthlyUpdated.$id, monthlyUpdated.totalCalories);
|
||||||
}
|
}
|
||||||
delay(1);
|
delay(QUICK_DELAY);
|
||||||
clearEditing();
|
clearEditing();
|
||||||
selectDate(selectedDate);
|
selectDate(selectedDate);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -818,7 +659,7 @@ const updateFood = async () => {
|
|||||||
|
|
||||||
const getDocumentIdForToday = (): DailyTotalCalories | null => {
|
const getDocumentIdForToday = (): DailyTotalCalories | null => {
|
||||||
const today = selectedDate.getDate();
|
const today = selectedDate.getDate();
|
||||||
const todayRecord = calendarMonthlyCalories.filter(x => x.day === today);
|
const todayRecord = appState.calendarMonthlyCalories.filter(x => x.day === today);
|
||||||
if (todayRecord.length > 0) {
|
if (todayRecord.length > 0) {
|
||||||
return todayRecord[0];
|
return todayRecord[0];
|
||||||
}
|
}
|
||||||
@@ -826,7 +667,7 @@ const getDocumentIdForToday = (): DailyTotalCalories | null => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const getDocumentIdForDay = (day: number): number => {
|
const getDocumentIdForDay = (day: number): number => {
|
||||||
const todayRecord = calendarMonthlyCalories.filter(x => x.day === day);
|
const todayRecord = appState.calendarMonthlyCalories.filter(x => x.day === day);
|
||||||
return todayRecord.length > 0 ? todayRecord[0].totalCalories : 0;
|
return todayRecord.length > 0 ? todayRecord[0].totalCalories : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -836,15 +677,15 @@ const updateDocumentIdForToday = (id: string, totalCalories: number): void => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const updateDocumentIdForDay = (id: string, totalCalories: number, day: number): void => {
|
const updateDocumentIdForDay = (id: string, totalCalories: number, day: number): void => {
|
||||||
const record = calendarMonthlyCalories.filter(x => x.day === day);
|
const record = appState.calendarMonthlyCalories.filter(x => x.day === day);
|
||||||
if (record.length === 0) {
|
if (record.length === 0) {
|
||||||
calendarMonthlyCalories.push({
|
appState.calendarMonthlyCalories.push({
|
||||||
documentId: id,
|
documentId: id,
|
||||||
day: day,
|
day: day,
|
||||||
totalCalories: totalCalories
|
totalCalories: totalCalories
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
calendarMonthlyCalories.forEach((record) => {
|
appState.calendarMonthlyCalories.forEach((record) => {
|
||||||
if (record.day === day) {
|
if (record.day === day) {
|
||||||
record.documentId = id;
|
record.documentId = id;
|
||||||
record.totalCalories = totalCalories;
|
record.totalCalories = totalCalories;
|
||||||
@@ -853,7 +694,6 @@ const updateDocumentIdForDay = (id: string, totalCalories: number, day: number):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add food to the log
|
|
||||||
const addFood = async () => {
|
const addFood = async () => {
|
||||||
if (!currentUser) {
|
if (!currentUser) {
|
||||||
swal('Hey!', 'Please log in to add food entries.', 'info');
|
swal('Hey!', 'Please log in to add food entries.', 'info');
|
||||||
@@ -911,11 +751,8 @@ const addFood = async () => {
|
|||||||
updateDocumentIdForToday(monthlyCreated.$id, monthlyCreated.totalCalories);
|
updateDocumentIdForToday(monthlyCreated.$id, monthlyCreated.totalCalories);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to HTML table with Appwrite document ID
|
addFoodToView(entry, savedEntry.$id);
|
||||||
addFoodToTable(entry, savedEntry.$id);
|
updateTotalCalories();
|
||||||
|
|
||||||
// Update totals
|
|
||||||
updateTotalCalories([savedEntry]);
|
|
||||||
|
|
||||||
// Update total macros
|
// Update total macros
|
||||||
const proteinDiv: HTMLElement = getDivById('proteinValue');
|
const proteinDiv: HTMLElement = getDivById('proteinValue');
|
||||||
@@ -938,7 +775,7 @@ const addFood = async () => {
|
|||||||
getInputById('foodSearchInput').value = '';
|
getInputById('foodSearchInput').value = '';
|
||||||
gramAmount.value = '100';
|
gramAmount.value = '100';
|
||||||
showFoodPreview(false);
|
showFoodPreview(false);
|
||||||
await delay(1);
|
await delay(QUICK_DELAY);
|
||||||
renderCalendar();
|
renderCalendar();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Add food error:', error);
|
console.error('Add food error:', error);
|
||||||
@@ -948,7 +785,7 @@ const addFood = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load food entries from Appwrite
|
// Load food entries from Appwrite for a given date
|
||||||
async function loadFoodEntries(date: Date) {
|
async function loadFoodEntries(date: Date) {
|
||||||
if (!currentUser) return;
|
if (!currentUser) return;
|
||||||
|
|
||||||
@@ -957,7 +794,6 @@ async function loadFoodEntries(date: Date) {
|
|||||||
try {
|
try {
|
||||||
const entries = await AppwriteDB.getFoodEntries(date);
|
const entries = await AppwriteDB.getFoodEntries(date);
|
||||||
|
|
||||||
// Clear current table
|
|
||||||
getDivById('foodCardsContainer').innerHTML = '';
|
getDivById('foodCardsContainer').innerHTML = '';
|
||||||
|
|
||||||
// Add each entry to table
|
// Add each entry to table
|
||||||
@@ -976,7 +812,7 @@ async function loadFoodEntries(date: Date) {
|
|||||||
alkaline: entry.alkaline,
|
alkaline: entry.alkaline,
|
||||||
};
|
};
|
||||||
|
|
||||||
addFoodToTable(foodData, entry.$id);
|
addFoodToView(foodData, entry.$id);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (entries.length === 0) {
|
if (entries.length === 0) {
|
||||||
@@ -989,11 +825,8 @@ async function loadFoodEntries(date: Date) {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup Delete events
|
setupEditAndDeleteEvents();
|
||||||
addDeleteEvents();
|
updateTotalCalories();
|
||||||
|
|
||||||
// Update total calories
|
|
||||||
updateTotalCalories(entries);
|
|
||||||
|
|
||||||
// Update counters
|
// Update counters
|
||||||
let totalCalories = 0;
|
let totalCalories = 0;
|
||||||
@@ -1063,8 +896,6 @@ async function loadFoodEntries(date: Date) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const delay = (seconds: number) => new Promise(resolve => setTimeout(resolve, seconds * 1000));
|
|
||||||
|
|
||||||
// Handle food deletion
|
// Handle food deletion
|
||||||
async function handleDeleteFood(documentId: string) {
|
async function handleDeleteFood(documentId: string) {
|
||||||
if (!documentId) return;
|
if (!documentId) return;
|
||||||
@@ -1101,7 +932,7 @@ async function handleDeleteFood(documentId: string) {
|
|||||||
const totalCalories = monthlyDocumentId?.totalCalories - existingToDelete;
|
const totalCalories = monthlyDocumentId?.totalCalories - existingToDelete;
|
||||||
const monthlyCreated = await AppwriteDB.updateMonthlyCaloryForDay(monthlyDocumentId?.documentId, selectedDate, totalCalories);
|
const monthlyCreated = await AppwriteDB.updateMonthlyCaloryForDay(monthlyDocumentId?.documentId, selectedDate, totalCalories);
|
||||||
updateDocumentIdForToday(monthlyCreated.$id, monthlyCreated.totalCalories);
|
updateDocumentIdForToday(monthlyCreated.$id, monthlyCreated.totalCalories);
|
||||||
await delay(1);
|
await delay(QUICK_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
selectDate(selectedDate);
|
selectDate(selectedDate);
|
||||||
@@ -1113,8 +944,7 @@ async function handleDeleteFood(documentId: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add food to table (existing function - update to use document ID)
|
function addFoodToView(foodData: FoodStorage, documentId: string) {
|
||||||
function addFoodToTable(foodData: FoodStorage, documentId: string) {
|
|
||||||
// New Food card
|
// New Food card
|
||||||
const container = getDivById('foodCardsContainer');
|
const container = getDivById('foodCardsContainer');
|
||||||
const card = document.createElement('div');
|
const card = document.createElement('div');
|
||||||
@@ -1125,6 +955,8 @@ function addFoodToTable(foodData: FoodStorage, documentId: string) {
|
|||||||
container.innerHTML = '';
|
container.innerHTML = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const foodFromDatabase = getFoodItemByName(foodData.name);
|
||||||
|
|
||||||
card.innerHTML = `
|
card.innerHTML = `
|
||||||
<div class="card-header card-header-toggle">
|
<div class="card-header card-header-toggle">
|
||||||
<div class="card-main-info">
|
<div class="card-main-info">
|
||||||
@@ -1158,21 +990,24 @@ function addFoodToTable(foodData: FoodStorage, documentId: string) {
|
|||||||
<div class="food-is-alkaline hidden">${foodData.alkaline ? 'alkaline' : ''}</div>
|
<div class="food-is-alkaline hidden">${foodData.alkaline ? 'alkaline' : ''}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-actions">
|
<div class="card-actions">
|
||||||
|
<span class="muted">${getIcon(foodFromDatabase.info.category)} ${foodFromDatabase.info.category}</span>
|
||||||
|
<div>
|
||||||
<button class="btn btn-edit" data-food-id="${documentId}">Edit</button>
|
<button class="btn btn-edit" data-food-id="${documentId}">Edit</button>
|
||||||
<button class="btn btn-delete" data-food-id="${documentId}">Delete</button>
|
<button class="btn btn-delete" data-food-id="${documentId}">Delete</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
container?.appendChild(card);
|
container?.appendChild(card);
|
||||||
|
|
||||||
// Setup Delete events
|
setupEditAndDeleteEvents();
|
||||||
addDeleteEvents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update total calories
|
// Update total calories and display it in the counter
|
||||||
function updateTotalCalories(entries: Models.DefaultDocument[]) {
|
// Also updates alkaline level percentage
|
||||||
|
function updateTotalCalories() {
|
||||||
const caloriesDiv = document.querySelectorAll('.calories-display');
|
const caloriesDiv = document.querySelectorAll('.calories-display');
|
||||||
let total = 0;
|
let total = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { DailyTotalCalories, FoodItem } from "./types";
|
||||||
|
|
||||||
|
interface AppState {
|
||||||
|
currentHighlightIndex: number;
|
||||||
|
searchTimeout: number | null;
|
||||||
|
searchResults: FoodItem[];
|
||||||
|
calendarMonthlyCalories: DailyTotalCalories[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const appState: AppState = {
|
||||||
|
currentHighlightIndex: -1,
|
||||||
|
searchTimeout: null,
|
||||||
|
searchResults: [],
|
||||||
|
calendarMonthlyCalories: []
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user