source: frontend/src/pages/Trainer.jsx@ 2e0035f

Last change on this file since 2e0035f was 2e0035f, checked in by Acko <lavurovski.a65@…>, 8 days ago

Initial Commit

  • Property mode set to 100644
File size: 3.9 KB
RevLine 
[2e0035f]1import { useEffect, useState } from 'react'
2import { api } from '../lib/api.js'
3
4/** UseCase3001, 3002 and 3004. Read-only by design: see TrainerController. */
5export default function Trainer() {
6 const [email, setEmail] = useState('marija.trajkovska@gmail.com')
7 const [from, setFrom] = useState('2026-01-20')
8 const [to, setTo] = useState('2026-02-01')
9 const [intake, setIntake] = useState([])
10 const [macros, setMacros] = useState([])
11 const [progress, setProgress] = useState([])
12 const [density, setDensity] = useState([])
13 const [nutrient, setNutrient] = useState('Protein')
14 const [error, setError] = useState(null)
15
16 const loadClient = async () => {
17 setError(null)
18 try {
19 setIntake(await api.get(`/trainer/clients/${email}/intake?from=${from}&to=${to}`))
20 setMacros(await api.get(`/trainer/clients/${email}/macros?from=${from}&to=${to}`))
21 setProgress(await api.get(`/trainer/clients/${email}/progress`))
22 } catch (e) { setError(e.message) }
23 }
24
25 const loadDensity = () =>
26 api.get(`/trainer/analysis/nutrient-density?nutrient=${nutrient}&limit=8`)
27 .then(setDensity).catch(e => setError(e.message))
28
29 useEffect(() => { loadDensity() }, [])
30
31 return (
32 <div>
33 {error && <div className="error">{error}</div>}
34
35 <div className="card">
36 <h3>Client report</h3>
37 <div className="row">
38 <input style={{ flex: 1, minWidth: 240 }} value={email}
39 onChange={e => setEmail(e.target.value)} placeholder="client email" />
40 <input type="date" value={from} onChange={e => setFrom(e.target.value)} />
41 <input type="date" value={to} onChange={e => setTo(e.target.value)} />
42 <button className="primary" onClick={loadClient}>Load</button>
43 </div>
44 </div>
45
46 {intake.length > 0 && (
47 <div className="card">
48 <h3>Daily intake</h3>
49 <table>
50 <thead><tr><th>day</th><th>kcal</th><th>meals</th></tr></thead>
51 <tbody>
52 {intake.map(d => (
53 <tr key={d.day}><td>{d.day}</td>
54 <td className="kcal">{d.kcalConsumed}</td><td>{d.mealsLogged}</td></tr>
55 ))}
56 </tbody>
57 </table>
58 </div>
59 )}
60
61 {macros.length > 0 && (
62 <div className="card">
63 <h3>Macronutrients over the period</h3>
64 <table>
65 <tbody>
66 {macros.map(m => (
67 <tr key={m.nutrient}><td>{m.nutrient}</td><td>{m.total} {m.unit}</td></tr>
68 ))}
69 </tbody>
70 </table>
71 </div>
72 )}
73
74 {progress.length > 0 && (
75 <div className="card">
76 <h3>Biometric progress</h3>
77 <table>
78 <thead><tr><th>date</th><th>weight</th><th>change</th><th>BMI</th></tr></thead>
79 <tbody>
80 {progress.map(p => (
81 <tr key={p.id}><td>{p.date}</td><td>{p.weight}</td>
82 <td>{p.changeSincePrevious ?? '—'}</td><td>{p.bmi ?? '—'}</td></tr>
83 ))}
84 </tbody>
85 </table>
86 </div>
87 )}
88
89 <div className="card">
90 <h3>Recipe analysis</h3>
91 <div className="row" style={{ marginBottom: 8 }}>
92 <input value={nutrient} onChange={e => setNutrient(e.target.value)}
93 placeholder="nutrient, e.g. Protein" />
94 <button className="primary" onClick={loadDensity}>Rank</button>
95 </div>
96 <table>
97 <thead>
98 <tr><th>recipe</th><th>kcal/portion</th><th>per portion</th><th>per 100 kcal</th></tr>
99 </thead>
100 <tbody>
101 {density.map(d => (
102 <tr key={d.recipe}>
103 <td>{d.recipe}</td><td>{d.kcalPerServing}</td>
104 <td>{d.amountPerServing}</td><td className="kcal">{d.amountPer100Kcal}</td>
105 </tr>
106 ))}
107 </tbody>
108 </table>
109 </div>
110 </div>
111 )
112}
Note: See TracBrowser for help on using the repository browser.