source: frontend/src/pages/Biometrics.jsx

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

Initial Commit

  • Property mode set to 100644
File size: 2.9 KB
RevLine 
[2e0035f]1import { useEffect, useState } from 'react'
2import { api } from '../lib/api.js'
3
4export default function Biometrics() {
5 const [rows, setRows] = useState([])
6 const [error, setError] = useState(null)
7 const [form, setForm] = useState({
8 date: new Date().toISOString().slice(0, 10),
9 weight: '', height: '', age: '', muscleFatRatio: ''
10 })
11
12 const load = () => api.get('/biometrics').then(setRows).catch(e => setError(e.message))
13 useEffect(() => { load() }, [])
14
15 const set = (k) => (e) => setForm({ ...form, [k]: e.target.value })
16
17 const save = async () => {
18 setError(null)
19 try {
20 await api.post('/biometrics', {
21 date: form.date,
22 weight: form.weight ? Number(form.weight) : null,
23 height: form.height ? Number(form.height) : null,
24 age: form.age ? Number(form.age) : null,
25 muscleFatRatio: form.muscleFatRatio ? Number(form.muscleFatRatio) : null
26 })
27 load()
28 } catch (e) { setError(e.message) }
29 }
30
31 return (
32 <div>
33 {error && <div className="error">{error}</div>}
34
35 <div className="card">
36 <h3>Record a measurement</h3>
37 <p className="muted">One per day. Saving the same date again updates that entry.</p>
38 <div className="row">
39 <input type="date" value={form.date} onChange={set('date')} />
40 <input type="number" step="0.1" placeholder="weight kg" style={{ width: 120 }}
41 value={form.weight} onChange={set('weight')} />
42 <input type="number" placeholder="height cm" style={{ width: 120 }}
43 value={form.height} onChange={set('height')} />
44 <input type="number" placeholder="age" style={{ width: 90 }}
45 value={form.age} onChange={set('age')} />
46 <input type="number" step="0.01" placeholder="muscle/fat" style={{ width: 120 }}
47 value={form.muscleFatRatio} onChange={set('muscleFatRatio')} />
48 <button className="primary" onClick={save}>Save</button>
49 </div>
50 </div>
51
52 <div className="card">
53 <h3>Progress</h3>
54 <table>
55 <thead>
56 <tr><th>date</th><th>weight</th><th>change</th><th>BMI</th><th>muscle/fat</th><th></th></tr>
57 </thead>
58 <tbody>
59 {rows.map(r => (
60 <tr key={r.id}>
61 <td>{r.date}</td>
62 <td>{r.weight}</td>
63 <td className={r.changeSincePrevious < 0 ? 'kcal' : 'muted'}>
64 {r.changeSincePrevious ?? '—'}
65 </td>
66 <td>{r.bmi ?? '—'}</td>
67 <td>{r.muscleFatRatio ?? '—'}</td>
68 <td style={{ width: 1 }}>
69 <button className="small"
70 onClick={() => api.del(`/biometrics/${r.id}`).then(load)}>delete</button>
71 </td>
72 </tr>
73 ))}
74 </tbody>
75 </table>
76 {rows.length === 0 && <p className="muted">No measurements yet.</p>}
77 </div>
78 </div>
79 )
80}
Note: See TracBrowser for help on using the repository browser.