Compare commits

1 Commits

View File

@@ -16,9 +16,9 @@ import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"; import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
interface SetForm { interface ExerciseRow {
exercise_id: number; exercise_id: number;
set_number: number; sets: string;
reps: string; reps: string;
weight_lbs: string; weight_lbs: string;
duration_min: string; duration_min: string;
@@ -30,7 +30,7 @@ export default function Workouts() {
const [date, setDate] = useState(today()); const [date, setDate] = useState(today());
const [name, setName] = useState(""); const [name, setName] = useState("");
const [wNotes, setWNotes] = useState(""); const [wNotes, setWNotes] = useState("");
const [sets, setSets] = useState<SetForm[]>([]); const [rows, setRows] = useState<ExerciseRow[]>([]);
const [newExName, setNewExName] = useState(""); const [newExName, setNewExName] = useState("");
const [newExCategory, setNewExCategory] = useState(""); const [newExCategory, setNewExCategory] = useState("");
const [showNewExercise, setShowNewExercise] = useState(false); const [showNewExercise, setShowNewExercise] = useState(false);
@@ -44,12 +44,12 @@ export default function Workouts() {
load(); load();
}, []); }, []);
const addSet = () => { const addRow = () => {
setSets([ setRows([
...sets, ...rows,
{ {
exercise_id: exercises[0]?.id || 0, exercise_id: exercises[0]?.id || 0,
set_number: sets.length + 1, sets: "3",
reps: "", reps: "",
weight_lbs: "", weight_lbs: "",
duration_min: "", duration_min: "",
@@ -57,34 +57,42 @@ export default function Workouts() {
]); ]);
}; };
const updateSet = (i: number, field: keyof SetForm, value: string | number) => { const updateRow = (i: number, field: keyof ExerciseRow, value: string | number) => {
const next = [...sets]; const next = [...rows];
(next[i] as any)[field] = value; (next[i] as any)[field] = value;
next[i].set_number = i + 1; setRows(next);
setSets(next);
}; };
const removeSet = (i: number) => { const removeRow = (i: number) => {
setSets(sets.filter((_, idx) => idx !== i).map((s, idx) => ({ ...s, set_number: idx + 1 }))); setRows(rows.filter((_, idx) => idx !== i));
}; };
const handleSubmit = async (e: React.FormEvent) => { const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
// Expand each row into individual sets
const allSets: { exercise_id: number; set_number: number; reps: number | null; weight_lbs: number | null; duration_min: number | null }[] = [];
let setNum = 1;
for (const row of rows) {
const numSets = parseInt(row.sets) || 1;
for (let s = 0; s < numSets; s++) {
allSets.push({
exercise_id: row.exercise_id,
set_number: setNum++,
reps: row.reps ? parseInt(row.reps) : null,
weight_lbs: row.weight_lbs ? parseFloat(row.weight_lbs) : null,
duration_min: row.duration_min ? parseFloat(row.duration_min) : null,
});
}
}
await api.post("/workouts", { await api.post("/workouts", {
date, date,
name: name || null, name: name || null,
notes: wNotes || null, notes: wNotes || null,
sets: sets.map((s) => ({ sets: allSets,
exercise_id: s.exercise_id,
set_number: s.set_number,
reps: s.reps ? parseInt(s.reps) : null,
weight_lbs: s.weight_lbs ? parseFloat(s.weight_lbs) : null,
duration_min: s.duration_min ? parseFloat(s.duration_min) : null,
})),
}); });
setName(""); setName("");
setWNotes(""); setWNotes("");
setSets([]); setRows([]);
load(); load();
}; };
@@ -132,31 +140,45 @@ export default function Workouts() {
<div className="space-y-2"> <div className="space-y-2">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<Label>Sets</Label> <Label>Exercises</Label>
<Button type="button" variant="ghost" size="sm" onClick={addSet} disabled={exercises.length === 0}> <Button type="button" variant="ghost" size="sm" onClick={addRow} disabled={exercises.length === 0}>
<Plus className="h-4 w-4 mr-1" /> Add Set <Plus className="h-4 w-4 mr-1" /> Add Exercise
</Button> </Button>
</div> </div>
{exercises.length === 0 && ( {exercises.length === 0 && (
<p className="text-xs text-muted-foreground">Create an exercise first</p> <p className="text-xs text-muted-foreground">Create an exercise first</p>
)} )}
{sets.map((s, i) => ( {rows.map((r, i) => (
<div key={i} className="flex gap-2 items-end"> <div key={i} className="space-y-2 border rounded-md p-2">
<div className="flex gap-2 items-center">
<select <select
className="flex h-9 w-full rounded-md border border-input bg-transparent px-2 text-sm" className="flex h-9 w-full rounded-md border border-input bg-transparent px-2 text-sm"
value={s.exercise_id} value={r.exercise_id}
onChange={(e) => updateSet(i, "exercise_id", parseInt(e.target.value))} onChange={(e) => updateRow(i, "exercise_id", parseInt(e.target.value))}
> >
{exercises.map((ex) => ( {exercises.map((ex) => (
<option key={ex.id} value={ex.id}>{ex.name}</option> <option key={ex.id} value={ex.id}>{ex.name}</option>
))} ))}
</select> </select>
<Input className="w-16" placeholder="Reps" value={s.reps} onChange={(e) => updateSet(i, "reps", e.target.value)} /> <Button type="button" variant="ghost" size="icon" onClick={() => removeRow(i)}>
<Input className="w-20" placeholder="Wt (lbs)" value={s.weight_lbs} onChange={(e) => updateSet(i, "weight_lbs", e.target.value)} />
<Button type="button" variant="ghost" size="icon" onClick={() => removeSet(i)}>
<Trash2 className="h-3 w-3" /> <Trash2 className="h-3 w-3" />
</Button> </Button>
</div> </div>
<div className="flex gap-2">
<div className="flex-1">
<Label className="text-xs text-muted-foreground">Sets</Label>
<Input type="number" min="1" value={r.sets} onChange={(e) => updateRow(i, "sets", e.target.value)} />
</div>
<div className="flex-1">
<Label className="text-xs text-muted-foreground">Reps</Label>
<Input type="number" value={r.reps} onChange={(e) => updateRow(i, "reps", e.target.value)} />
</div>
<div className="flex-1">
<Label className="text-xs text-muted-foreground">Weight</Label>
<Input type="number" step="0.1" value={r.weight_lbs} onChange={(e) => updateRow(i, "weight_lbs", e.target.value)} placeholder="lbs" />
</div>
</div>
</div>
))} ))}
</div> </div>