Övningar
- {exercises.map((exercise, idx) => (
-
setExpandedExercise(
- expandedExercise === exercise.id ? null : exercise.id
- )}
- onLogSet={onLogSet}
- onDeleteSet={onDeleteSet}
- />
- ))}
+ {exercises.map((exercise, idx) => {
+ const swapped = swappedExercises[exercise.id]
+ const displayExercise = swapped
+ ? { ...exercise, name: swapped.name, muscle_group: swapped.muscle_group, description: swapped.description }
+ : exercise
+
+ return (
+ setExpandedExercise(
+ expandedExercise === exercise.id ? null : exercise.id
+ )}
+ onLogSet={onLogSet}
+ onDeleteSet={onDeleteSet}
+ onStartRest={startRest}
+ onSwap={() => openAlternatives(exercise)}
+ />
+ )
+ })}
{/* Avsluta pass */}
@@ -254,13 +364,24 @@ function WorkoutPage({ day, week, logs, onLogSet, onDeleteSet, onBack, fetchProg
: `Avsluta pass (${completedExercises}/${exercises.length} klara)`}
+
+ setSwapExercise(null)}
+ />
)
}
-function ExerciseCard({ exercise, logs, progression, expanded, onToggle, onLogSet, onDeleteSet }) {
+function ExerciseCard({ exercise, logs, progression, expanded, onToggle, onLogSet, onDeleteSet, onSwap, isSwapped, onStartRest }) {
const [setList, setSetList] = useState([])
const [showAddModal, setShowAddModal] = useState(false)
+ const weightStep = 2.5
+ const repsStep = 1
useEffect(() => {
const initial = []
@@ -279,11 +400,34 @@ function ExerciseCard({ exercise, logs, progression, expanded, onToggle, onLogSe
setSetList(prev => prev.map((s, i) => i === idx ? { ...s, [field]: value } : s))
}
+ const parseNumber = (value) => {
+ const parsed = parseFloat(value)
+ return Number.isFinite(parsed) ? parsed : 0
+ }
+
+ const formatWeight = (value) => {
+ const fixed = Number.isInteger(value) ? String(value) : value.toFixed(1)
+ return fixed.replace(/\.0$/, '')
+ }
+
+ const handleAdjust = (idx, field, delta, min = 0) => {
+ const current = parseNumber(setList[idx]?.[field])
+ const next = Math.max(min, current + delta)
+ if (field === 'weight') {
+ handleInputChange(idx, field, formatWeight(next))
+ } else {
+ handleInputChange(idx, field, String(Math.round(next)))
+ }
+ }
+
const handleComplete = (idx) => {
const input = setList[idx]
const newCompleted = !input.completed
setSetList(prev => prev.map((s, i) => i === idx ? { ...s, completed: newCompleted } : s))
onLogSet(exercise.id, idx + 1, input.weight, input.reps, newCompleted)
+ if (newCompleted) {
+ onStartRest?.()
+ }
}
const handleAddNormal = () => {
@@ -320,12 +464,25 @@ function ExerciseCard({ exercise, logs, progression, expanded, onToggle, onLogSe
{exercise.name}
{exercise.muscle_group}
+ {isSwapped && Alternativ}
-
-
{exercise.sets}×{exercise.reps_min}-{exercise.reps_max}
-
- {completedSets}/{setList.length}
-
+
+
+ {exercise.sets}×{exercise.reps_min}-{exercise.reps_max}
+
+ {completedSets}/{setList.length}
+
+
+
@@ -343,31 +500,74 @@ function ExerciseCard({ exercise, logs, progression, expanded, onToggle, onLogSe
{setList.map((input, idx) => (
-
Set {idx + 1}
-
-
handleInputChange(idx, 'weight', val)}
- />
- ×
- handleInputChange(idx, 'reps', val)}
- />
+
+ Set {idx + 1}
+
+
+
+
+
Vikt
+
+
+
+ {input.weight === '' ? '0' : input.weight}
+ kg
+
+
+
+
+
+
Reps
+
+
+
+ {input.reps === '' ? '0' : input.reps}
+
+
+
+
-
))}
diff --git a/frontend/tasks/task-001-workout-ux-redesign.md b/frontend/tasks/task-001-workout-ux-redesign.md
new file mode 100644
index 0000000..87494d0
--- /dev/null
+++ b/frontend/tasks/task-001-workout-ux-redesign.md
@@ -0,0 +1,3 @@
+# Task 001: WorkoutPage UX Redesign
+Single-tap logging with +/- buttons and rest timer
+Notify: openclaw system event --text Done --mode now