source: frontend/src/pages/Planner.jsx

Last change on this file was 98cd519, checked in by Acko <lavurovski.a65@…>, 12 hours ago

Shema update + project push

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