### Implement the functionality behind the "Try in a routine" button **Goal:** Make the existing "Try in a routine" button on the element page work. Today it only shows the message "The routine builder is not connected yet." (`src/components/elements/ElementActions.tsx`). The button itself (look, icon, accessibility) is done in another issue; this issue is only about what happens when it is used. **What it should do:** Clicking the button puts the element into the *calculator routine*, so a visitor can try it in a routine and see what it is worth. The calculator routine is described in [DATA_MODEL.md](docs/DATA_MODEL.md#calculator-routine-not-stored): an `apparatusId` and a list of `itemIds`, kept only in the client's state, never stored, and usable without logging in. #### Implementation checklist - [ ] **Shared calculator routine state** - [ ] Create the state for the calculator routine (`apparatusId` and ordered `itemIds`) so the element page and the calculator page read the same routine. A React context with a reducer, or a small store, is enough; it is not saved to the database. - [ ] Operations: add an item, remove an item, clear the routine. - [ ] Decide whether to keep it in `sessionStorage` so a reload does not empty it. The docs say the routine is "kept only while the page is open", so the default is memory only. - [ ] **Rules when adding an element** - [ ] The first element sets the apparatus. An element from another apparatus is refused with a clear message, because a routine is on one apparatus. - [ ] On vault the routine holds exactly one vault, and a vault cannot be mixed with elements. - [ ] At most 50 items, the limit of `calculateDScore`. - [ ] The same element may be added twice; it counts once in the D-score (see "User data" in [API.md](docs/API.md)). - [ ] These are constraints 7 and 8 in [DATA_MODEL.md](docs/DATA_MODEL.md). Check them in the frontend so the coach gets a message before the request. The backend checks them again (`INVALID_ITEMS`), and the frontend shows that error too. - [ ] **The button** - [ ] Connect `ElementActions` to the state. Replace the "not connected yet" message with a message that says the element was added (and to which apparatus), or why it was refused. - [ ] Show whether the element is already in the routine (for example "In the routine" and a way to remove it), and keep `aria-pressed` in step with it if it works as a toggle. - [ ] Announce the result in the existing `role="status"` region so screen reader users hear it. - [ ] Give the visitor a way to reach the routine after adding an element (a link to the calculator, or the navbar showing the number of items). - [ ] **D-score** - [ ] Read the D-score from the `calculateDScore(itemIds)` query, so the calculator and saved routines use the same calculation. Do not calculate it in the frontend. - [ ] Handle `INVALID_ITEMS` (for example an element that has been removed from the Code of Points) and `BAD_USER_INPUT` without crashing. - [ ] **Tests** - [ ] Unit tests for the state: add, remove, clear, the apparatus rule, the vault rules, the limit of 50 and adding the same element twice. - [ ] A component test: clicking the button adds the element, the label and `aria-pressed` change, and the status message is announced. - [ ] A test that the refused cases show a message and do not change the routine. - [ ] Keyboard: `Enter` and `Space` activate the button. #### Depends on - The calculator page (#95), where the routine is shown and scored. This issue owns the shared calculator-routine state and the button; #95 uses that state. Until #95 is done, the routine can be shown in a simple list, or this issue can be limited to the state and the button. - `calculateDScore` (#72) and Apollo Client (#75) are in `dev`. #### Not in this issue - Saving the routine to a gymnast (needs login, and is part of the "Add to gymnast" button). - The look and the accessibility of the button itself.