| [2e0035f] | 1 | import { useEffect, useState } from 'react'
|
|---|
| 2 | import { api } from '../lib/api.js'
|
|---|
| 3 |
|
|---|
| 4 | /** UseCase1002 - log a meal and see the daily totals. */
|
|---|
| 5 | export default function Planner() {
|
|---|
| 6 | const [entries, setEntries] = useState([])
|
|---|
| 7 | const [feed, setFeed] = useState([])
|
|---|
| 8 | const [daily, setDaily] = useState([])
|
|---|
| 9 | const [macros, setMacros] = useState([])
|
|---|
| 10 | const [error, setError] = useState(null)
|
|---|
| 11 | const [pick, setPick] = useState([])
|
|---|
| 12 | const [notes, setNotes] = useState('')
|
|---|
| 13 |
|
|---|
| 14 | const today = new Date().toISOString().slice(0, 10)
|
|---|
| 15 | const weekAgo = new Date(Date.now() - 7 * 864e5).toISOString().slice(0, 10)
|
|---|
| 16 |
|
|---|
| 17 | const load = () => {
|
|---|
| 18 | api.get('/planner').then(setEntries).catch(e => setError(e.message))
|
|---|
| 19 | api.get(`/planner/daily?from=${weekAgo}&to=${today}`).then(setDaily).catch(() => {})
|
|---|
| 20 | api.get(`/planner/macros?from=${weekAgo}&to=${today}`).then(setMacros).catch(() => {})
|
|---|
| 21 | }
|
|---|
| 22 |
|
|---|
| 23 | useEffect(() => {
|
|---|
| 24 | load()
|
|---|
| 25 | api.get('/posts/feed').then(setFeed).catch(() => {})
|
|---|
| 26 | }, [])
|
|---|
| 27 |
|
|---|
| 28 | const log = async () => {
|
|---|
| 29 | setError(null)
|
|---|
| 30 | try {
|
|---|
| 31 | await api.post('/planner', {
|
|---|
| 32 | notes,
|
|---|
| 33 | postIds: pick.map(Number),
|
|---|
| 34 | consumed: true
|
|---|
| 35 | })
|
|---|
| 36 | setNotes('')
|
|---|
| 37 | setPick([])
|
|---|
| 38 | load()
|
|---|
| 39 | } catch (e) { setError(e.message) }
|
|---|
| 40 | }
|
|---|
| 41 |
|
|---|
| 42 | return (
|
|---|
| 43 | <div>
|
|---|
| 44 | {error && <div className="error">{error}</div>}
|
|---|
| 45 |
|
|---|
| 46 | <div className="card">
|
|---|
| 47 | <h3>Log a meal</h3>
|
|---|
| 48 | <div className="stack" style={{ maxWidth: 520 }}>
|
|---|
| 49 | <input placeholder="notes, e.g. Lunch at home"
|
|---|
| 50 | value={notes} onChange={e => setNotes(e.target.value)} />
|
|---|
| 51 | <select multiple size={5} value={pick}
|
|---|
| 52 | onChange={e => setPick(Array.from(e.target.selectedOptions, o => o.value))}>
|
|---|
| 53 | {feed.map(p => (
|
|---|
| 54 | <option key={p.id} value={p.id}>
|
|---|
| 55 | {p.recipeName} — {p.kcalPerServing} kcal / portion
|
|---|
| 56 | </option>
|
|---|
| 57 | ))}
|
|---|
| 58 | </select>
|
|---|
| 59 | <span className="muted">One portion is counted per selected meal.</span>
|
|---|
| 60 | <button className="primary" onClick={log}>Log it</button>
|
|---|
| 61 | </div>
|
|---|
| 62 | </div>
|
|---|
| 63 |
|
|---|
| 64 | <div className="card">
|
|---|
| 65 | <h3>Last 7 days</h3>
|
|---|
| 66 | <table>
|
|---|
| 67 | <thead><tr><th>day</th><th>kcal</th><th>meals</th></tr></thead>
|
|---|
| 68 | <tbody>
|
|---|
| 69 | {daily.map(d => (
|
|---|
| 70 | <tr key={d.day}>
|
|---|
| 71 | <td>{d.day}</td><td className="kcal">{d.kcalConsumed}</td><td>{d.mealsLogged}</td>
|
|---|
| 72 | </tr>
|
|---|
| 73 | ))}
|
|---|
| 74 | </tbody>
|
|---|
| 75 | </table>
|
|---|
| 76 | {daily.length === 0 && <p className="muted">Nothing logged in the last week.</p>}
|
|---|
| 77 | </div>
|
|---|
| 78 |
|
|---|
| 79 | {macros.length > 0 && (
|
|---|
| 80 | <div className="card">
|
|---|
| 81 | <h3>Macronutrients supplied this week</h3>
|
|---|
| 82 | <table>
|
|---|
| 83 | <tbody>
|
|---|
| 84 | {macros.map(m => (
|
|---|
| 85 | <tr key={m.nutrient}><td>{m.nutrient}</td><td>{m.total} {m.unit}</td></tr>
|
|---|
| 86 | ))}
|
|---|
| 87 | </tbody>
|
|---|
| 88 | </table>
|
|---|
| 89 | </div>
|
|---|
| 90 | )}
|
|---|
| 91 |
|
|---|
| 92 | <div className="card">
|
|---|
| 93 | <h3>Diary</h3>
|
|---|
| 94 | <table>
|
|---|
| 95 | <tbody>
|
|---|
| 96 | {entries.map(e => (
|
|---|
| 97 | <tr key={e.id}>
|
|---|
| 98 | <td>{new Date(e.dateTime).toLocaleString()}</td>
|
|---|
| 99 | <td>{e.notes}</td>
|
|---|
| 100 | <td className="muted">{e.meals.join(', ')}</td>
|
|---|
| 101 | <td className="kcal">{e.kcal}</td>
|
|---|
| 102 | <td>{e.consumed ? 'eaten' : 'planned'}</td>
|
|---|
| 103 | </tr>
|
|---|
| 104 | ))}
|
|---|
| 105 | </tbody>
|
|---|
| 106 | </table>
|
|---|
| 107 | </div>
|
|---|
| 108 | </div>
|
|---|
| 109 | )
|
|---|
| 110 | }
|
|---|