Skip to content

Conversation

anettkva
Copy link
Member

Closes #95.

The calculator page builds a routine on one apparatus and shows its D-value, with each element marked as counted or not. Nothing is saved yet: the "Save to a gymnast" button is a placeholder for #152.

The layout follows the Figma design, not the issue text

The issue description describes a different layout than the Figma design. I built it from the Figma design, so the page differs from the issue in these ways:

  • One table with Order, Element, Value and Counted, instead of a separate list and routine.
  • An "Add element" row that opens a popup with search, instead of a list next to the routine.
  • The apparatus as pill tabs.
  • An editable routine name (pencil icon).
  • The D-value box under the table.
  • "Log in to save routine" for visitors.

The colours are the same as on the gymnast pages and the rest of the site.

What is in this PR

API

  • New query scoreRoutine(itemIds) returns the D-score, which items count (counted), and which element the dismount replaced (replacedByDismount). calculateDScore gives the same score as before.
  • The rule is in one place, scoreItems in backend/src/dscore.ts: the eight highest values, each code once, and the dismount always counts. If the dismount isn't among the eight highest, it takes the place of the lowest of them.
  • This also changes saved routines: Routine.dScore now counts the dismount the same way.

Calculator page

  • Add elements from the popup with search. "+" adds and the check mark removes.
  • Change the order by dragging a row, or with Move up / Move down (keyboard and WCAG 2.5.7).
  • The Counted column says "Included", "Not in top 8", "Same code counted" or "Replaced by dismount".
  • Rules when adding:
    • one apparatus per routine
    • one vault on vault
    • at most one mount and one dismount
    • at most 50 items
    • elements that are no longer in the Code of Points can't be added
    • a refused element is shown as a warning in the popup
  • Changing the apparatus when the routine has elements asks first.
  • Removing an element uses the same trash button as the gymnast page.
  • The routine is kept when you go to another page and come back. A reload starts with an empty routine.

Changes outside the calculator

  • ApparatusTabs: new pill look. The gymnast page still uses the line look and is unchanged.
  • ConfirmDialog: long button text now wraps inside the button.
  • TrashButton: only its comment changed.
  • shared/routines.ts: the 50-item limit, the Mounts/Dismounts group names and apparatusOfId, shared by the backend and the frontend.
  • searchOperations.ts: the search query now also asks for removed, so the popup can turn off removed elements. The Elements page doesn't use it.
  • App.tsx: wrapped in CalculatorRoutineProvider, so the calculator keeps its routine when you go to another page and back. The routes are unchanged.
  • The element page is not changed.

Questions for the reviewers

Pagination (#162). The popup's element list uses "Load more elements", copied from the Elements page's search (marked TODO(#162) in AddElementsList.tsx). It should use the same pagination as #162. What do you prefer?

  1. Merge feat: replace Load more with pagination on the Elements page #162 first, then update the popup in this PR.
  2. Merge this PR as it is and make a separate issue for switching the popup to pagination.

Not in this PR (follow-ups)

  • Composition requirements are not checked. The calculator only counts the eight highest values with the dismount rule. Rules such as requiring 3 dance elements and 3 acrobatic elements on balance beam are missing. I suggest a separate issue.
  • Saving (Create functionality for adding a routine to a gymnast #152).
    • "Save to a gymnast" says that saving isn't ready yet.
    • When saving is built, it should warn before saving a routine on uneven bars or balance beam without a dismount (noted in the code and in docs/UI_PLANS.md).
  • "Try in a routine" on the element page is not connected yet (Implement functionality for "try in a routine"-button component #91). The calculator's routine is ready for it.
  • The API doesn't enforce the mount/dismount limit. The calculator allows at most one mount and one dismount, but setRoutineItems doesn't check this.

How to test

  1. Run npm run codegen in backend/ (the schema has a new query), then start the backend and the frontend.
  2. Open Calculator and choose Uneven bars.
  3. Add a few elements with "Add element", including a mount and a dismount, and check the D-value and the Counted column.
  4. Try to add a second mount: a warning should appear in the popup.
  5. Reorder rows by dragging and with the arrow buttons. Rename the routine. Remove an element with the trash button.
  6. Switch to another apparatus: it should ask first.
  7. Go to another page and back: the routine is still there.
  8. Log in: "Save to a gymnast" says saving isn't ready yet. Logged out, it says "Log in to save routine".

Checks

  • Type checks (frontend and backend), ESLint, Prettier and the build pass.
  • 712 frontend tests and 258 backend tests pass. Run the backend tests with --no-file-parallelism: in parallel, two files report rows that other files added to the same database.
  • Each new behaviour was checked by removing it and confirming a test fails.
  • axe-core found no violations in light mode, dark mode, or at 320 px wide.

🤖 Generated with Claude Code

@anettkva anettkva requested a review from a team as a code owner November 11, 2026 10:43
Copy link
Member

@ronjalh ronjalh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude review mm:
High: kommer til å feile ved merge med #189 (pagineringen). Dette er en semantisk konflikt. Git viser ingen tekstkonflikt, men det knekker bygget:

  • AddElementsList.tsx importerer SEARCH_CATALOG_MORE_QUERY og kaller fetchMore. #189 sletter den spørringen og endrer Apollo-cachen til én side om gangen, så «Load more» i popupen slutter å fungere eller kompilerer ikke.
  • Elements-siden og popupen deler searchCatalog i cachen. Med #189 overskriver de hverandres side.
  • Anette spør selv om rekkefølgen (valg 1 eller 2 i PR-teksten). Mitt råd: merge #189 først, og la Anette gi popupen en egen enkel løsning, for eksempel en query som ikke deler cache-nøkkel med Elements-siden.

Low: Popupen skriver Showing 20 of {totalCount} uten formatTotal, så tallet kan vise 1001 i stedet for «1000+» (nås ikke med dagens 562 elementer). Å bytte apparat på en tom rutine tilbakestiller navnet, også om brukeren har endret det. Vanskelighetene bruker håndskrevne typer i calculatorOperations.ts i stedet for codegen, men searchOperations.ts gjør det samme, så det er ikke noe avvik.
optional: Hvis dere ønsker en felles dialog senere, ville jeg trukket ut bare skallet (Portal, Backdrop, Popup-posisjonen) og latt de to innholdene være.

@anettkva
Copy link
Member Author

Thanks! I've fixed the small points (formatTotal in the popup, and keeping a given routine name on another apparatus). I'll wait for #189 to be merged and then update the popup to match.

Copy link
Member

@ronjalh ronjalh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be merged after 189, lgtm just solve conflicts

Sign in to join this conversation on GitHub.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants