index.html 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>LocalFoodAI Chat</title>
  7. <meta name="description" content="LocalFoodAI Assistant for Nutritional Information and Menu Proposals">
  8. <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
  9. <link rel="stylesheet" href="/static/style.css">
  10. </head>
  11. <body>
  12. <div class="app-container" id="chat-app" style="display: none;">
  13. <header class="chat-header">
  14. <div class="brand">
  15. <div class="logo">🍳</div>
  16. <div>
  17. <h1>LocalFoodAI</h1>
  18. <span class="status-indicator" id="status-dot"></span><span class="status-text" id="status-text">Local LLM Ready</span>
  19. </div>
  20. </div>
  21. <div class="actions">
  22. <span id="user-greeting" style="margin-right:15px; font-size: 0.9rem; color: var(--text-muted);"></span>
  23. <button id="nav-logout-btn" class="nav-btn">Logout</button>
  24. <button id="clear-chat" title="Clear Chat">
  25. <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 6h18M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"></path></svg>
  26. </button>
  27. </div>
  28. </header>
  29. <!-- New Visual Food Search Component -->
  30. <div class="search-module" id="food-search-module">
  31. <div class="search-input-wrapper">
  32. <svg class="search-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
  33. <input type="text" id="food-search-input" placeholder="Search for standard foods or raw ingredients..." autocomplete="off">
  34. <button id="clear-search-btn" style="display: none;" title="Clear search">
  35. <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
  36. </button>
  37. </div>
  38. <div class="search-results-dropdown" id="search-results-dropdown" style="display: none;">
  39. <!-- Dynamically populated by JS fetch -->
  40. </div>
  41. </div>
  42. <!-- Meal Builder Component (US-10 Task #46) -->
  43. <div class="meal-builder-tray" id="meal-builder">
  44. <div class="meal-builder-header">
  45. <div class="tray-title">
  46. <span class="icon">🍽️</span>
  47. <h3>Meal Builder</h3>
  48. <span class="item-count" id="meal-item-count">0 items</span>
  49. </div>
  50. <button id="toggle-meal-btn" class="icon-btn" title="Toggle Meal Builder">
  51. <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M19 9l-7 7-7-7"></path></svg>
  52. </button>
  53. </div>
  54. <div class="meal-content collapsed" id="meal-content">
  55. <div class="meal-items-list" id="meal-items-list">
  56. <!-- Dynamic food rows added here -->
  57. <div class="empty-meal-msg" id="empty-meal-msg">No foods added yet. Use the search + button to build a meal.</div>
  58. </div>
  59. <div class="meal-builder-footer" id="meal-builder-footer" style="display: none;">
  60. <div class="meal-totals-banner" id="meal-totals-banner">
  61. <div class="totals-header">
  62. <span class="totals-title">Total Macros</span>
  63. <span class="totals-weight" id="meal-total-weight">0g</span>
  64. </div>
  65. <div class="totals-grid">
  66. <div class="total-card">
  67. <span class="total-val" id="meal-total-cal">0</span>
  68. <span class="total-lbl">kcal</span>
  69. </div>
  70. <div class="total-card protein-highlight">
  71. <span class="total-val" id="meal-total-pro">0</span>
  72. <span class="total-lbl">Protein</span>
  73. </div>
  74. <div class="total-card">
  75. <span class="total-val" id="meal-total-fat">0</span>
  76. <span class="total-lbl">Fat</span>
  77. </div>
  78. <div class="total-card">
  79. <span class="total-val" id="meal-total-carb">0</span>
  80. <span class="total-lbl">Carbs</span>
  81. </div>
  82. </div>
  83. </div>
  84. <button id="generate-recipe-btn" class="primary-btn-sm">🍲 Generate Recipe Prompt</button>
  85. </div>
  86. </div>
  87. </div>
  88. <!-- Macro Dashboard UI (US-07 Task #38) -->
  89. <div class="macro-dashboard" id="macro-dashboard" style="display: none;">
  90. <div class="macro-card">
  91. <div class="macro-label">Calories</div>
  92. <div class="macro-value" id="macro-calories">-- kcal</div>
  93. </div>
  94. <div class="macro-card">
  95. <div class="macro-label">Protein</div>
  96. <div class="macro-value" id="macro-protein">-- g</div>
  97. </div>
  98. <div class="macro-card">
  99. <div class="macro-label">Carbs</div>
  100. <div class="macro-value" id="macro-carbs">-- g</div>
  101. </div>
  102. <div class="macro-card">
  103. <div class="macro-label">Fat</div>
  104. <div class="macro-value" id="macro-fat">-- g</div>
  105. </div>
  106. </div>
  107. <main class="chat-container" id="chat-container">
  108. <div class="message system">
  109. <div class="avatar">🤖</div>
  110. <div class="message-content">
  111. <p>Hello! I am LocalFoodAI, your completely local nutrition and menu assistant. How can I help you today?</p>
  112. </div>
  113. </div>
  114. </main>
  115. <footer class="chat-input-area">
  116. <form id="chat-form" class="input-form">
  117. <textarea id="user-input" placeholder="Ask about recipes, nutrition, menus..." rows="1" required></textarea>
  118. <button type="submit" id="send-btn" class="send-btn" aria-label="Send message">
  119. <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg>
  120. </button>
  121. </form>
  122. <div class="footer-note">Powered by Qwen 3.5:4B running locally on Ubuntu 24.04 via Ollama</div>
  123. </footer>
  124. </div>
  125. <!-- Save Meal Modal (Sprint 8) -->
  126. <div id="save-meal-modal" class="modal" style="display: none;">
  127. <div class="modal-content">
  128. <div class="modal-header">
  129. <h3>Save Current Meal</h3>
  130. <button class="close-btn" id="cancel-save-btn">&times;</button>
  131. </div>
  132. <div class="modal-body">
  133. <p>Give this meal a name to save it to your dashboard.</p>
  134. <div class="input-group">
  135. <input type="text" id="meal-name-input" placeholder="e.g., Healthy Monday Lunch" autofocus>
  136. </div>
  137. <div id="save-meal-error" class="error-text"></div>
  138. </div>
  139. <div class="modal-footer">
  140. <button id="confirm-save-btn" class="primary-btn">Save to Dashboard</button>
  141. </div>
  142. </div>
  143. </div>
  144. <!-- Authentication Gateway -->
  145. <div class="auth-container" id="auth-screen">
  146. <div class="auth-header">
  147. <div class="logo" style="margin-bottom: 10px;">🍳</div>
  148. <h2>Welcome to LocalFoodAI</h2>
  149. <p>Please log in or create an account to continue.</p>
  150. </div>
  151. <!-- Login Form -->
  152. <form id="login-form">
  153. <div class="input-group">
  154. <label for="login-username">Username</label>
  155. <input type="text" id="login-username" required>
  156. </div>
  157. <div class="input-group">
  158. <label for="login-password">Password</label>
  159. <input type="password" id="login-password" required>
  160. </div>
  161. <div id="login-error" class="error-text"></div>
  162. <button type="submit" class="primary-btn" id="login-submit-btn">Login</button>
  163. <p class="auth-toggle">Don't have an account? <a href="#" id="show-register">Register here</a></p>
  164. </form>
  165. <!-- Registration Form (Hidden by default) -->
  166. <form id="register-form" style="display: none;">
  167. <div class="input-group">
  168. <label for="reg-username">Username</label>
  169. <input type="text" id="reg-username" required minlength="3">
  170. </div>
  171. <div class="input-group">
  172. <label for="reg-password">Password</label>
  173. <input type="password" id="reg-password" required minlength="6">
  174. </div>
  175. <div class="input-group">
  176. <label for="reg-confirm">Confirm Password</label>
  177. <input type="password" id="reg-confirm" required minlength="6">
  178. </div>
  179. <div id="reg-error" class="error-text"></div>
  180. <div id="reg-success" class="success-text"></div>
  181. <button type="submit" class="primary-btn" id="reg-submit-btn">Register</button>
  182. <p class="auth-toggle">Already have an account? <a href="#" id="show-login">Login here</a></p>
  183. </form>
  184. </div>
  185. <script src="/static/script.js"></script>
  186. </body>
  187. </html>