Files
Copilot 6837e4f139 feat: Add "Show other options" to surface nutritionally equivalent food alternatives (#10)
* Initial plan

* feat: Add 'Show other options' feature to find similar foods by category and bestFor

Agent-Logs-Url: https://github.com/RMCampos/calories-tracker/sessions/00437e19-3c33-48b4-8d15-f29ac843a20f

Co-authored-by: RMCampos <2219519+RMCampos@users.noreply.github.com>

* fix: Address code review issues - string type, dedup logic, HTML escaping

Agent-Logs-Url: https://github.com/RMCampos/calories-tracker/sessions/00437e19-3c33-48b4-8d15-f29ac843a20f

Co-authored-by: RMCampos <2219519+RMCampos@users.noreply.github.com>

* fix: Add full HTML escaping including quotes in alternatives display

Agent-Logs-Url: https://github.com/RMCampos/calories-tracker/sessions/00437e19-3c33-48b4-8d15-f29ac843a20f

Co-authored-by: RMCampos <2219519+RMCampos@users.noreply.github.com>

* feat: improve food options by food type

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: RMCampos <2219519+RMCampos@users.noreply.github.com>
Co-authored-by: Ricardo Campos <ricardompcampos@gmail.com>
2026-04-28 11:07:34 -03:00

538 lines
27 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Daily Calorie Tracker</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="auth.css">
<link rel="stylesheet" href="settings.css">
<link rel="apple-touch-icon" sizes="57x57" href="/assets/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/assets/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/assets/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/assets/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/assets/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/assets/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/assets/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/assets/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/assets/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192" href="/assets/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="/assets/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="/assets/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="/assets/favicon-16x16.png">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="/assets/ms-icon-144x144.png">
<meta name="theme-color" content="#121212">
<!-- PWA Meta Tags -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="Food Tracker">
<meta name="mobile-web-app-capable" content="yes">
</head>
<body>
<!-- Authentication Header -->
<header class="auth-header">
<div class="auth-container">
<div class="logo">
<h1>🍎 Food Tracker</h1>
</div>
<!-- Authentication Buttons (shown when not logged in) -->
<div id="auth-buttons" class="auth-buttons">
<button id="open-login-btn" class="header-btn">Login</button>
<button id="open-register-btn" class="header-btn primary">Get Started</button>
</div>
<!-- User Info (shown when logged in) -->
<div id="user-info" class="user-info hidden">
<div class="user-details">
<span id="userName">Welcome, User!</span>
<div class="header-buttons">
<button id="shareBtn" class="header-btn">🔗 Share</button>
<button id="calendarBtn" class="header-btn">📅 Calendar</button>
<button id="settingsBtn" class="header-btn">⚙️ Settings</button>
<button id="logoutBtn" class="header-btn logout">🚪 Logout</button>
</div>
</div>
<!-- Mobile menu toggle -->
<button id="mobileMenuToggle" class="mobile-menu-toggle hidden"></button>
<!-- Mobile dropdown menu -->
<div id="mobileMenu" class="mobile-menu hidden">
<button id="shareBtnMobile" class="mobile-menu-item">🔗 Share</button>
<button id="calendarBtnMobile" class="mobile-menu-item">📅 Calendar</button>
<button id="settingsBtnMobile" class="mobile-menu-item">⚙️ Settings</button>
<button id="logoutBtnMobile" class="mobile-menu-item logout">🚪 Logout</button>
</div>
</div>
</div>
</header>
<!-- Authentication Modal -->
<div id="auth-modal" class="auth-modal hidden">
<div class="auth-modal-content">
<button id="close-auth-modal" class="close-modal-btn">×</button>
<!-- Login Form -->
<div id="login-form" class="auth-form">
<h3>Welcome Back</h3>
<form id="loginForm">
<div class="form-group">
<input type="email" id="loginEmail" placeholder="Email" required>
</div>
<div class="form-group">
<input type="password" id="loginPassword" placeholder="Password" required>
</div>
<button type="submit" class="auth-btn">Login</button>
<p class="auth-switch">
Don't have an account?
<a href="#" id="showRegister">Register here</a>
</p>
</form>
</div>
<!-- Register Form -->
<div id="register-form" class="auth-form hidden">
<h3>Create Your Account</h3>
<form id="registerForm">
<div class="form-group">
<input type="text" id="registerName" placeholder="Name" required>
</div>
<div class="form-group">
<input type="email" id="registerEmail" placeholder="Email" required>
</div>
<div class="form-group">
<input type="password" id="registerPassword" placeholder="Password" required minlength="8">
</div>
<button type="submit" class="auth-btn">Register</button>
<p class="auth-switch">
Already have an account?
<a href="#" id="showLogin">Login here</a>
</p>
</form>
</div>
</div>
</div>
<!-- Landing Page Content (shown when not logged in) -->
<section id="landing-page" class="landing-page hidden">
<div class="landing-container">
<div class="landing-hero">
<h1 class="landing-title">Track Your Nutrition, Transform Your Health</h1>
<p class="landing-subtitle">Take control of your diet with our comprehensive calorie and nutrition tracker. Perfect for anyone who wants to maintain a balanced diet and achieve their health goals.</p>
</div>
<div class="landing-features">
<div class="feature-card">
<div class="feature-icon">📊</div>
<h3>Detailed Tracking</h3>
<p>Monitor calories, protein, fat, carbs, and fiber for every meal. Get a complete picture of your daily nutrition.</p>
</div>
<div class="feature-card">
<div class="feature-icon">🎯</div>
<h3>Set Goals</h3>
<p>Define your daily macros targets and track your progress. Stay motivated and on track with your health journey.</p>
</div>
<div class="feature-card">
<div class="feature-icon">📅</div>
<h3>Calendar View</h3>
<p>Visualize your nutrition history with an intuitive calendar. See patterns and maintain consistency over time.</p>
</div>
<div class="feature-card">
<div class="feature-icon">🥗</div>
<h3>Alkaline Balance</h3>
<p>Track your alkaline food intake to maintain a healthy pH balance and support overall wellness.</p>
</div>
<div class="feature-card">
<div class="feature-icon">🔍</div>
<h3>Smart Search</h3>
<p>Quickly find and log foods from our comprehensive database. Make tracking effortless and accurate.</p>
</div>
<div class="feature-card">
<div class="feature-icon">🔗</div>
<h3>Share Progress</h3>
<p>Share your daily food log with friends, trainers, or nutritionists. Get support and accountability.</p>
</div>
</div>
<div class="landing-cta">
<h2>Ready to Start Your Health Journey?</h2>
<p>Join today and take the first step towards a healthier, more balanced lifestyle.</p>
<div class="cta-buttons">
<button id="cta-register-btn" class="cta-btn primary">Get Started Free</button>
<button id="cta-login-btn" class="cta-btn secondary">Already Have an Account?</button>
</div>
</div>
</div>
</section>
<!-- Loading Overlay -->
<div id="loading-overlay" class="loading-overlay hidden">
<div class="loading-spinner"></div>
<p>Loading...</p>
</div>
<!-- Share Modal -->
<div id="share-modal" class="modal-overlay hidden">
<div class="modal-content">
<h2>🔗 Share This Day</h2>
<p>Share your food log for this day with others!</p>
<div class="share-link-container">
<input
type="text"
id="share-link-input"
class="share-link-input"
readonly
placeholder="Generating share link..."
>
<button id="copy-share-link" class="copy-btn">Copy</button>
</div>
<div class="modal-buttons">
<button id="close-share-modal" class="modal-btn">Close</button>
</div>
</div>
</div>
<!-- Shared View Banner -->
<div id="shared-view-banner" class="shared-view-banner hidden">
<span id="shared-view-text">👁️ Viewing shared day from <strong id="shared-user-name"></strong> on <strong id="shared-date"></strong></span>
</div>
<!-- Main App Content -->
<main id="app-content" class="hidden">
<div class="container">
<div class="date-display" id="currentDate"></div>
<div class="calories-banner">
<div class="calories-number" id="caloriesCounter">0</div>
<div class="calories-text">Calories Today</div>
<div class="calories-text-goal" id="caloriesGoalText">of 0</div>
<div class="calories-text-alkaline" id="alkaline-level">80% Alkaline</div>
</div>
<div class="nutrition-summary" id="nutritionSummary">
<div class="nutrition-item">
<div class="nutrition-label">Protein (g)</div>
<div class="nutrition-value" id="proteinValue">0</div>
<div class="nutrition-label hidden" id="proteinGoalText">of 190</div>
</div>
<div class="nutrition-item">
<div class="nutrition-label">Fat (g)</div>
<div class="nutrition-value" id="fatValue">0</div>
<div class="nutrition-label hidden" id="fatGoalText">of 190</div>
</div>
<div class="nutrition-item">
<div class="nutrition-label">Carbs (g)</div>
<div class="nutrition-value" id="carboValue">0</div>
<div class="nutrition-label hidden" id="carboGoalText">of 190</div>
</div>
<div class="nutrition-item">
<div class="nutrition-label">Fiber (g)</div>
<div class="nutrition-value" id="fiberValue">0</div>
<div class="nutrition-label hidden" id="fiberGoalText">of 190</div>
</div>
</div>
<div class="add-food-section">
<h2 class="add-food-title" id="add-foot-title">Add Food Entry</h2>
<div class="add-food-form">
<div class="form-group">
<label for="foodSelect">Food Item</label>
<div class="food-search-container">
<input
type="text"
class="food-search-input"
id="foodSearchInput"
placeholder="Search food (e.g., apple, chicken breast, rice...)"
autocomplete="off"
>
<div class="search-loading" id="searchLoading"></div>
<!-- Search Results Overlay -->
<div class="search-results" id="searchResults">
<!-- Results will be populated here -->
</div>
<!-- Hidden inputs for state -->
<input type="hidden" id="foodIdToUpdate">
<input type="hidden" id="foodTimeToUpdate">
<input type="hidden" id="foodCaloriesToUpdate">
</div>
</div>
<div class="form-group">
<label for="gramAmount">Amount (grams)</label>
<input type="number" id="gramAmount" min="1" step="1" value="100">
</div>
<div class="form-group hidden" id="foodTimeGroup">
<label for="foodEntryTime">Time</label>
<input type="time" id="foodEntryTime">
</div>
<button class="add-btn" id="add-food-btn">Add Food</button>
<button class="cancel-btn" id="cancel-food-btn">Cancel</button>
</div>
<div class="display-none" id="food-preview">
<div class="nutrition-summary">
<div class="nutrition-item">
<div class="nutrition-value" id="calorieValuePreview">0</div>
<div class="nutrition-label">Calories</div>
</div>
<div class="nutrition-item">
<div class="nutrition-value" id="proteinValuePreview">0</div>
<div class="nutrition-label">Protein (g)</div>
</div>
<div class="nutrition-item">
<div class="nutrition-value" id="fatValuePreview">0</div>
<div class="nutrition-label">Fat (g)</div>
</div>
<div class="nutrition-item">
<div class="nutrition-value" id="carboValuePreview">0</div>
<div class="nutrition-label">Carbs (g)</div>
</div>
<div class="nutrition-item">
<div class="nutrition-value" id="fiberValuePreview">0</div>
<div class="nutrition-label">Fiber (g)</div>
</div>
</div>
</div>
<div class="form-group checkbox-group">
<label class="checkbox-label">
<input type="checkbox" id="enableAlternatives" class="ai-checkbox">
<span>Show other options</span>
</label>
</div>
<!-- Alternatives Container -->
<div class="display-none" id="alternatives-container">
<div class="alternatives-list-container">
<h3 class="alternatives-title">Similar Food Options</h3>
<div id="alternatives-list"></div>
</div>
</div>
<div class="form-group checkbox-group">
<label class="checkbox-label">
<input type="checkbox" id="enableAINutrition" class="ai-checkbox">
<span>Show AI nutrition information</span>
</label>
</div>
<!-- AI Nutrition Info Card -->
<div class="display-none" id="ai-nutrition-card">
<div class="ai-nutrition-container">
<h3 class="ai-nutrition-title">
<span class="ai-badge">AI</span>
Detailed Nutrition Information
</h3>
<!-- Loading State -->
<div id="ai-nutrition-loading" class="ai-loading">
<div class="ai-spinner"></div>
<p>Analyzing nutritional content...</p>
</div>
<!-- Error State -->
<div id="ai-nutrition-error" class="ai-error hidden">
<p>Unable to load detailed nutrition info. Please try again.</p>
</div>
<!-- Content -->
<div id="ai-nutrition-content" class="ai-nutrition-content hidden">
<!-- Vitamins Section -->
<div class="ai-nutrition-section">
<h4 class="ai-section-title">Vitamins</h4>
<ul id="ai-vitamins-list" class="ai-list"></ul>
</div>
<!-- Minerals Section -->
<div class="ai-nutrition-section">
<h4 class="ai-section-title">Minerals</h4>
<ul id="ai-minerals-list" class="ai-list"></ul>
</div>
<!-- Benefits Section -->
<div class="ai-nutrition-section">
<h4 class="ai-section-title">Health Benefits</h4>
<ul id="ai-benefits-list" class="ai-list"></ul>
</div>
<!-- Notes Section -->
<div class="ai-nutrition-section" id="ai-notes-section">
<h4 class="ai-section-title">Notes</h4>
<p id="ai-notes-text" class="ai-notes"></p>
</div>
</div>
</div>
</div>
</div>
<div class="section-title">Food Log</div>
<div class="food-cards-container" id="foodCardsContainer">
<!-- Food cards will be added here -->
</div>
<div class="calendar-section">
<div class="calendar-header">
<button class="calendar-nav" id="previous-month-btn"></button>
<div class="calendar-title" id="calendarTitle">Month Year</div>
<button class="calendar-nav" id="next-month-btn"></button>
</div>
<div class="calendar-grid" id="calendarGrid">
<!-- Calendar will be generated here -->
</div>
</div>
</div>
</main>
<!-- Settings -->
<section id="settings-content" class="hidden">
<div class="container">
<h1>⚙️ Settings</h1>
<div class="date-display">Body Metrics</div>
<form id="settingsForm" class="settings-form">
<div class="form-group">
<label for="bodyWeight">Body Weight (kg)</label>
<input type="text" id="bodyWeight" placeholder="Body Weight">
</div>
<div class="form-group">
<label for="height">Height (cm)</label>
<input type="number" id="height" placeholder="Height">
</div>
<div class="form-group">
<label for="bmi">Body Mass Index (BMI)</label>
<input type="number" id="bmi" placeholder="BMI" readonly>
</div>
<div class="form-group">
<label for="bmiResult">Body Mass Index (BMI) Result</label>
<input type="text" id="bmiResult" placeholder="BMI Result" readonly>
</div>
<div class="form-group">
<label for="timezone">Timezone</label>
<select id="timezone">
<option value="">— Use browser time —</option>
<optgroup label="UTC">
<option value="UTC">UTC</option>
</optgroup>
<optgroup label="Americas">
<option value="America/New_York">America/New_York</option>
<option value="America/Chicago">America/Chicago</option>
<option value="America/Denver">America/Denver</option>
<option value="America/Los_Angeles">America/Los_Angeles</option>
<option value="America/Toronto">America/Toronto</option>
<option value="America/Vancouver">America/Vancouver</option>
<option value="America/Mexico_City">America/Mexico_City</option>
<option value="America/Bogota">America/Bogota</option>
<option value="America/Lima">America/Lima</option>
<option value="America/Caracas">America/Caracas</option>
<option value="America/La_Paz">America/La_Paz</option>
<option value="America/Santiago">America/Santiago</option>
<option value="America/Sao_Paulo">America/Sao_Paulo</option>
<option value="America/Argentina/Buenos_Aires">America/Argentina/Buenos_Aires</option>
</optgroup>
<optgroup label="Europe">
<option value="Europe/London">Europe/London</option>
<option value="Europe/Lisbon">Europe/Lisbon</option>
<option value="Europe/Amsterdam">Europe/Amsterdam</option>
<option value="Europe/Berlin">Europe/Berlin</option>
<option value="Europe/Madrid">Europe/Madrid</option>
<option value="Europe/Paris">Europe/Paris</option>
<option value="Europe/Rome">Europe/Rome</option>
<option value="Europe/Helsinki">Europe/Helsinki</option>
<option value="Europe/Moscow">Europe/Moscow</option>
<option value="Europe/Istanbul">Europe/Istanbul</option>
</optgroup>
<optgroup label="Africa">
<option value="Africa/Cairo">Africa/Cairo</option>
<option value="Africa/Lagos">Africa/Lagos</option>
<option value="Africa/Nairobi">Africa/Nairobi</option>
<option value="Africa/Johannesburg">Africa/Johannesburg</option>
</optgroup>
<optgroup label="Asia">
<option value="Asia/Karachi">Asia/Karachi</option>
<option value="Asia/Kolkata">Asia/Kolkata</option>
<option value="Asia/Dhaka">Asia/Dhaka</option>
<option value="Asia/Bangkok">Asia/Bangkok</option>
<option value="Asia/Jakarta">Asia/Jakarta</option>
<option value="Asia/Singapore">Asia/Singapore</option>
<option value="Asia/Shanghai">Asia/Shanghai</option>
<option value="Asia/Seoul">Asia/Seoul</option>
<option value="Asia/Tokyo">Asia/Tokyo</option>
<option value="Asia/Dubai">Asia/Dubai</option>
</optgroup>
<optgroup label="Oceania">
<option value="Australia/Sydney">Australia/Sydney</option>
<option value="Pacific/Auckland">Pacific/Auckland</option>
</optgroup>
</select>
</div>
<button type="submit" class="settings-btn">Save</button>
</form>
<div class="date-display" style="margin-top: 40px;">Nutrition Goals</div>
<div id="goalsContainer">
<!-- Dynamically rendered list of goals -->
</div>
<button type="button" id="addGoalBtn" class="settings-btn" style="margin-top: 15px;">+ Add Goal</button>
<div id="goalFormContainer" class="hidden">
<form id="goalForm" class="settings-form" style="margin-top: 15px;">
<div class="form-group">
<label for="goalNameInput">Goal Name</label>
<input type="text" id="goalNameInput" placeholder="e.g. Workout Day" required>
</div>
<div class="form-group">
<label for="goalCaloriesInput">Daily calorie goal</label>
<input type="number" id="goalCaloriesInput" placeholder="Calories">
</div>
<div class="form-group">
<label for="goalProteinInput">Daily protein goal (g)</label>
<input type="number" id="goalProteinInput" placeholder="Proteins in grams">
</div>
<div class="form-group">
<label for="goalFatInput">Daily fat goal (g)</label>
<input type="number" id="goalFatInput" placeholder="Fat in grams">
</div>
<div class="form-group">
<label for="goalCarboInput">Daily carbs goal (g)</label>
<input type="number" id="goalCarboInput" placeholder="Carbs in grams">
</div>
<div class="form-group">
<label for="goalFiberInput">Daily fiber goal (g)</label>
<input type="number" id="goalFiberInput" placeholder="Fiber in grams">
</div>
<input type="hidden" id="editingGoalId" value="">
<button type="submit" class="settings-btn">Save Goal</button>
<button type="button" id="cancelGoalBtn" class="settings-btn" style="margin-top: 10px; background: #555; border-color: #555;">Cancel</button>
</form>
</div>
<div class="date-display" style="margin-top: 40px;">AI Nutrition Cache</div>
<div class="cache-info-section">
<div class="cache-stats">
<div class="cache-stat-item">
<span class="cache-stat-label">Cached Items:</span>
<span class="cache-stat-value" id="cacheItemCount">0</span>
</div>
<div class="cache-stat-item">
<span class="cache-stat-label">Cache Size:</span>
<span class="cache-stat-value" id="cacheSize">0 KB</span>
</div>
</div>
<button type="button" id="clearCacheBtn" class="settings-btn clear-cache-btn">Clear Cache</button>
</div>
</div>
</section>
<script type="module" src="src/index.ts"></script>
</body>
</html>