Skip to content

fix(workout): Move up/down on a superset member reorders it inside the superset - #443

Merged
DuarteSantos8 merged 1 commit into
DuarteSantos8:mainfrom
kurktchiev:gh/superset-member-move
Oct 9, 2026
Merged

DuarteSantos8 merged 1 commit into
DuarteSantos8:mainfrom
kurktchiev:gh/superset-member-move

Conversation

@kurktchiev

@kurktchiev kurktchiev commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

In a workout, an exercise's ⋯ menu has Move up and Move down. On a superset member they move the whole superset past the block next to it, and the order inside the superset never changes. In a six-exercise circuit, moving a hanging leg raise away from the pull-ups right before it moved the whole circuit above the main lift, and the leg raise still came right after the pull-ups.

#377 reports the same gap in the routine editor, and 06d1853 fixed it there (moveRoutineEntry). This PR does the workout screen with the same swap inside the superset, and keeps today's move at the superset's edge:

  • A superset member swaps places with the member next to it and keeps its superset id, so the superset stays one block. Its layout choice and groupMeta are keyed by that id.
  • On the superset's first or last member, Move takes the whole superset, as it does today. In the editor a member at the edge steps out of its superset instead. During a workout that would change a superset the round-robin is in the middle of, so this PR leaves the edge alone. Matching the editor can be a follow-up if you want the two screens to agree.
  • A lone exercise moves as before.
  • The Move up / Move down buttons below the exercise (Settings → Workout controls) still move the whole unit.

Unlike the editor, the workout screen runs a superset round-robin, and supersetFlowStep decides it by position. The members before the marker have done the current round; the marker's member and the ones after it still owe it. So the marker keeps its position through a swap and points at whichever member now sits there, and the menu disables a swap that would carry a member across the marker in the middle of a round. That swap would skip one member for the round and run the other twice. At the start of a round the marker is on the first member, and every swap is allowed.

I also tried making supersetFlowStep count rounds instead of reading positions. It broke supersets where a later member was ahead, for example when its warm-ups had been ticked early, so this PR leaves supersetFlowStep alone.

The new helpers are moveActiveWorkoutEntry and canMoveActiveWorkoutEntry in lib/active-workout-order.js. They return the same index permutation as moveActiveWorkoutUnit, so moveUnitAt remaps the running rest and the counted-sets marks the same way for both.

Tests:

  • active-workout-order.test.js, 7 new tests: a swap inside the superset; the marker keeping its position; a swap across the marker refused mid-round and allowed at the start of a round; a whole round run through the real supersetFlowStep after a mid-round swap, in which every member gets exactly one set; the superset's edge falling back to the whole-superset move; a lone exercise; two adjacent supersets staying apart.
  • Workout.test.jsx, 4 new tests through the ⋯ menu: a member moved inside its superset; a member swap during a rest; a whole-superset move during a rest; a member swap followed by a tick. Nothing tested the rest and counted-sets remaps in moveUnitAt before: deleting both left every test passing, and the useUI mock had no setState. The mock gets one. Three of the four fail on main. The whole-superset move during a rest passes on main, since it covers code main already has.
  • The full frontend suite passes on 39bc71e.
  • check-locales.mjs and check-source-strings.mjs --strict pass, and no strings change. The production build passes.

Conflicts: two of my own, #409 (views/Workout.test.jsx) and #165 (the import lines at the top of views/Workout.jsx). No other open PR gains a conflict from this branch.

Refs #377.

🤖 Generated with Claude Code

…e superset

The exercise ⋯ menu's Move always moved the whole superset past the
neighbouring block, so a member could never change places inside it. DuarteSantos8#377
reports the same in the routine editor, where moveRoutineEntry (06d1853)
fixed it.

A superset member now swaps with its neighbour and keeps its sg, so the
superset stays one block under the same id. At the superset's first or last
member the move still takes the whole superset. The editor takes a member at
the edge out of its superset instead; during a workout that would change a
superset whose round is under way. A lone exercise moves as before. The buttons below the exercise (Settings → Workout controls) keep
moving the whole unit.

The superset round-robin is positional (supersetFlowStep): the members before
the marker have done the round, the marker's member and those after it owe
it. So the marker keeps its position through a swap, and a swap that would
carry a member across it mid-round is refused (it would skip one member and
run the other twice).

Tests: the member move, the marker rules, a whole round run through
supersetFlowStep after a mid-round swap, and moves during a rest. moveUnitAt's
rest and counted-sets remaps had no test; the useUI mock gains setState so a
move during a rest can be tested.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@kurktchiev
kurktchiev force-pushed the gh/superset-member-move branch from 3d90273 to 2aee8cf Compare October 7, 2026 17:25
crstnmac added a commit to crstnmac/openGym that referenced this pull request Oct 9, 2026
@DuarteSantos8
DuarteSantos8 merged commit f44f2e3 into DuarteSantos8:main Oct 9, 2026
4 checks passed
@kurktchiev
kurktchiev deleted the gh/superset-member-move branch October 9, 2026 15:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants