macros/index.html
index.htmlRaw
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" />
6 <meta name="theme-color" content="#0f766e" />
7 <meta name="apple-mobile-web-app-capable" content="yes" />
8 <meta name="apple-mobile-web-app-status-bar-style" content="default" />
9 <meta name="apple-mobile-web-app-title" content="macros" />
10 <title>macros</title>
11 <link rel="manifest" href="manifest.json" />
12 <link rel="icon" href="icons/logo.svg" type="image/svg+xml" />
13 <link rel="apple-touch-icon" href="icons/logo.svg" />
14 <link rel="stylesheet" href="styles.css" />
15 </head>
16 <body>
17 <div class="app">
18 <header class="topbar">
19 <div class="brand">
20 <img class="brand-logo" src="icons/logo.svg" alt="macros logo" />
21 <div>
22 <h1>macros</h1>
23 <p>Lightweight food intake tracker</p>
24 </div>
25 </div>
26 <div class="topbar-actions">
27 <button id="theme-toggle" class="ghost icon-button" type="button" aria-label="Switch to dark mode" title="Switch to dark mode">
28 <span class="theme-icon icon-moon" aria-hidden="true">
29 <svg viewBox="0 0 24 24" focusable="false">
30 <path d="M15 2.8c-2.2.8-3.8 2.9-3.8 5.5 0 3.3 2.7 6 6 6 1.4 0 2.6-.4 3.7-1.2-1 4.7-5.1 8.2-10.1 8.2-5.7 0-10.3-4.6-10.3-10.3 0-5.3 4-9.7 9.2-10.3.2 0 .4 0 .5-.1H15z"></path>
31 </svg>
32 </span>
33 <span class="theme-icon icon-sun" aria-hidden="true">
34 <svg viewBox="0 0 24 24" focusable="false">
35 <path d="M12 7a5 5 0 100 10 5 5 0 000-10zm0-5a1 1 0 011 1v2a1 1 0 11-2 0V3a1 1 0 011-1zm0 17a1 1 0 011 1v2a1 1 0 11-2 0v-2a1 1 0 011-1zm9-8a1 1 0 110 2h-2a1 1 0 110-2h2zM5 12a1 1 0 110 2H3a1 1 0 110-2h2zm12.4-6.4a1 1 0 011.4 1.4l-1.4 1.4A1 1 0 0116 7.6l1.4-1.4zM8 16a1 1 0 011.4 1.4L8 18.8a1 1 0 01-1.4-1.4L8 16zm10.8 1.4a1 1 0 01-1.4 1.4L16 17.4a1 1 0 011.4-1.4l1.4 1.4zM9.4 8a1 1 0 01-1.4 1.4L6.6 8A1 1 0 018 6.6L9.4 8z"></path>
36 </svg>
37 </span>
38 </button>
39 <nav class="nav">
40 <button class="tab active" data-view="today">Today</button>
41 <button class="tab" data-view="history">History</button>
42 <button class="tab" data-view="settings">Settings</button>
43 </nav>
44 </div>
45 </header>
46
47 <main>
48 <section class="card" id="intake-form">
49 <div class="card-header">
50 <h2>Add Intake</h2>
51 <p>Pick a food and log the grams you ate.</p>
52 </div>
53 <form id="add-intake">
54 <label>
55 Food
56 <div class="food-combobox">
57 <input name="food" id="food-input" placeholder="Start typing..." autocomplete="off" required />
58 <div id="food-suggestions" class="food-suggestions hidden"></div>
59 </div>
60 </label>
61 <label>
62 Amount (grams)
63 <input type="number" min="1" step="1" name="grams" id="grams-input" value="100" required />
64 </label>
65 <label>
66 Log date
67 <input type="date" name="entry-date" id="entry-date" />
68 </label>
69 <button type="submit" class="primary">Add</button>
70 </form>
71 <div id="intake-preview" class="intake-preview">
72 <p class="preview-title">Nutrition preview</p>
73 <div class="preview-grid">
74 <div class="preview-block">
75 <p class="preview-block-title">Per 100g</p>
76 <p id="preview-base" class="preview-values">Select a food to preview macros.</p>
77 </div>
78 <div class="preview-block">
79 <p class="preview-block-title">For selected amount</p>
80 <p id="preview-scaled" class="preview-values">Enter grams to see calculated macros.</p>
81 </div>
82 </div>
83 </div>
84 <div class="hint" id="food-hint">Loading foods...</div>
85 </section>
86
87 <section class="card" id="today-view">
88 <div class="card-header">
89 <h2>Day</h2>
90 <p id="today-date"></p>
91 </div>
92 <div class="history-controls">
93 <label>
94 Select day
95 <input type="date" id="today-select-date" />
96 </label>
97 </div>
98 <div class="totals" id="today-totals"></div>
99 <div class="list" id="today-list"></div>
100 </section>
101
102 <section class="card hidden" id="history-view">
103 <div class="card-header">
104 <h2>History</h2>
105 <p>Zoom by day, week, month, or quarter.</p>
106 </div>
107 <div class="history-controls">
108 <label>
109 Range
110 <select id="range-select">
111 <option value="day">Day</option>
112 <option value="week" selected>Week</option>
113 <option value="month">Month</option>
114 <option value="quarter">Quarter</option>
115 </select>
116 </label>
117 <label>
118 Anchor date
119 <input type="date" id="anchor-date" />
120 </label>
121 </div>
122 <div class="history-charts">
123 <div class="chart-card" id="kcal-chart-card">
124 <h3>Calories by day</h3>
125 <div id="history-kcal-chart" class="chart-grid"></div>
126 </div>
127 <div class="chart-card" id="macro-chart-card">
128 <h3>Macro split by day</h3>
129 <div id="history-macro-chart" class="chart-grid"></div>
130 <div class="chart-legend">
131 <span><i class="legend-dot protein"></i>Protein</span>
132 <span><i class="legend-dot carbs"></i>Carbs</span>
133 <span><i class="legend-dot fat"></i>Fat</span>
134 </div>
135 </div>
136 </div>
137 <div class="totals" id="history-totals"></div>
138 <div class="list" id="history-breakdown"></div>
139 </section>
140
141 <section class="card hidden" id="settings-view">
142 <div class="card-header">
143 <h2>Settings</h2>
144 <p>Data migration and daily goals.</p>
145 </div>
146 <p class="hint">
147 This app is a PWA, so you can install it on your phone from the browser menu (Add to Home Screen / Install app). All your data stays locally on your device only and is never sent to any server.
148 </p>
149 <br>
150 <div class="settings-panels">
151 <div class="settings-panel">
152 <h3>Data migration</h3>
153 <div class="settings-actions">
154 <button id="export-data" class="ghost" type="button">Export local data</button>
155 <button id="import-data" class="ghost" type="button">Import local data</button>
156 <input id="import-file" type="file" accept="application/json" class="file-input-hidden" />
157 </div>
158 </div>
159 <div class="settings-panel">
160 <h3>Daily goals</h3>
161 <form id="goals-form" class="goals-form">
162 <label>
163 Calories (kcal)
164 <input type="number" min="0" step="1" id="goal-kcal" required />
165 </label>
166 <label>
167 Protein (g)
168 <input type="number" min="0" step="1" id="goal-protein" required />
169 </label>
170 <label>
171 Carbs (g)
172 <input type="number" min="0" step="1" id="goal-carbs" required />
173 </label>
174 <label>
175 Fat (g)
176 <input type="number" min="0" step="1" id="goal-fat" required />
177 </label>
178 <label>
179 Sugar (g)
180 <input type="number" min="0" step="1" id="goal-sugar" required />
181 </label>
182 <button type="submit" class="primary">Save goals</button>
183 </form>
184 <p class="hint" id="goals-hint"></p>
185 </div>
186 </div>
187 </section>
188 </main>
189 </div>
190
191 <template id="intake-row">
192 <div class="row">
193 <div>
194 <div class="row-title"></div>
195 <div class="row-sub"></div>
196 </div>
197 <div class="row-actions">
198 <div class="row-kcal"></div>
199 <button type="button" class="row-edit hidden icon-action" aria-label="Edit entry" title="Edit entry">
200 <svg viewBox="0 0 24 24" focusable="false" aria-hidden="true">
201 <path d="M3 17.25V21h3.75L17.8 9.94l-3.75-3.75L3 17.25zm2.92 2.33H5v-.92l9.06-9.06.92.92L5.92 19.58zM20.71 7.04a1 1 0 000-1.41l-2.34-2.34a1 1 0 00-1.41 0l-1.13 1.13 3.75 3.75 1.13-1.13z"></path>
202 </svg>
203 </button>
204 <button type="button" class="row-delete hidden icon-action" aria-label="Delete entry" title="Delete entry">
205 <svg viewBox="0 0 24 24" focusable="false" aria-hidden="true">
206 <path d="M6 7h12l-1 13a2 2 0 01-2 2H9a2 2 0 01-2-2L6 7zm3-4h6l1 2h4v2H4V5h4l1-2zm1 6h2v9h-2V9zm4 0h2v9h-2V9z"></path>
207 </svg>
208 </button>
209 </div>
210 </div>
211 </template>
212
213 <script src="app.js"></script>
214 </body>
215</html>