Compare commits
1 Commits
feature/cs
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3504093c33 |
@@ -16,9 +16,9 @@ import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
|
||||
|
||||
interface SetForm {
|
||||
interface ExerciseRow {
|
||||
exercise_id: number;
|
||||
set_number: number;
|
||||
sets: string;
|
||||
reps: string;
|
||||
weight_lbs: string;
|
||||
duration_min: string;
|
||||
@@ -30,7 +30,7 @@ export default function Workouts() {
|
||||
const [date, setDate] = useState(today());
|
||||
const [name, setName] = useState("");
|
||||
const [wNotes, setWNotes] = useState("");
|
||||
const [sets, setSets] = useState<SetForm[]>([]);
|
||||
const [rows, setRows] = useState<ExerciseRow[]>([]);
|
||||
const [newExName, setNewExName] = useState("");
|
||||
const [newExCategory, setNewExCategory] = useState("");
|
||||
const [showNewExercise, setShowNewExercise] = useState(false);
|
||||
@@ -44,12 +44,12 @@ export default function Workouts() {
|
||||
load();
|
||||
}, []);
|
||||
|
||||
const addSet = () => {
|
||||
setSets([
|
||||
...sets,
|
||||
const addRow = () => {
|
||||
setRows([
|
||||
...rows,
|
||||
{
|
||||
exercise_id: exercises[0]?.id || 0,
|
||||
set_number: sets.length + 1,
|
||||
sets: "3",
|
||||
reps: "",
|
||||
weight_lbs: "",
|
||||
duration_min: "",
|
||||
@@ -57,34 +57,42 @@ export default function Workouts() {
|
||||
]);
|
||||
};
|
||||
|
||||
const updateSet = (i: number, field: keyof SetForm, value: string | number) => {
|
||||
const next = [...sets];
|
||||
const updateRow = (i: number, field: keyof ExerciseRow, value: string | number) => {
|
||||
const next = [...rows];
|
||||
(next[i] as any)[field] = value;
|
||||
next[i].set_number = i + 1;
|
||||
setSets(next);
|
||||
setRows(next);
|
||||
};
|
||||
|
||||
const removeSet = (i: number) => {
|
||||
setSets(sets.filter((_, idx) => idx !== i).map((s, idx) => ({ ...s, set_number: idx + 1 })));
|
||||
const removeRow = (i: number) => {
|
||||
setRows(rows.filter((_, idx) => idx !== i));
|
||||
};
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
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", {
|
||||
date,
|
||||
name: name || null,
|
||||
notes: wNotes || null,
|
||||
sets: sets.map((s) => ({
|
||||
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,
|
||||
})),
|
||||
sets: allSets,
|
||||
});
|
||||
setName("");
|
||||
setWNotes("");
|
||||
setSets([]);
|
||||
setRows([]);
|
||||
load();
|
||||
};
|
||||
|
||||
@@ -132,31 +140,45 @@ export default function Workouts() {
|
||||
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<Label>Sets</Label>
|
||||
<Button type="button" variant="ghost" size="sm" onClick={addSet} disabled={exercises.length === 0}>
|
||||
<Plus className="h-4 w-4 mr-1" /> Add Set
|
||||
<Label>Exercises</Label>
|
||||
<Button type="button" variant="ghost" size="sm" onClick={addRow} disabled={exercises.length === 0}>
|
||||
<Plus className="h-4 w-4 mr-1" /> Add Exercise
|
||||
</Button>
|
||||
</div>
|
||||
{exercises.length === 0 && (
|
||||
<p className="text-xs text-muted-foreground">Create an exercise first</p>
|
||||
)}
|
||||
{sets.map((s, i) => (
|
||||
<div key={i} className="flex gap-2 items-end">
|
||||
{rows.map((r, i) => (
|
||||
<div key={i} className="space-y-2 border rounded-md p-2">
|
||||
<div className="flex gap-2 items-center">
|
||||
<select
|
||||
className="flex h-9 w-full rounded-md border border-input bg-transparent px-2 text-sm"
|
||||
value={s.exercise_id}
|
||||
onChange={(e) => updateSet(i, "exercise_id", parseInt(e.target.value))}
|
||||
value={r.exercise_id}
|
||||
onChange={(e) => updateRow(i, "exercise_id", parseInt(e.target.value))}
|
||||
>
|
||||
{exercises.map((ex) => (
|
||||
<option key={ex.id} value={ex.id}>{ex.name}</option>
|
||||
))}
|
||||
</select>
|
||||
<Input className="w-16" placeholder="Reps" value={s.reps} onChange={(e) => updateSet(i, "reps", e.target.value)} />
|
||||
<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)}>
|
||||
<Button type="button" variant="ghost" size="icon" onClick={() => removeRow(i)}>
|
||||
<Trash2 className="h-3 w-3" />
|
||||
</Button>
|
||||
</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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user