* feat: quiz page question rework (#181)
- Replace Bootstrap accordion with flat card list for questions
- Add HTML5 drag-and-drop reordering with placeholder-between-cards UX
and amber/green/red save status indicator next to the heading
- Add edit button per question opening a Bootstrap modal (bo--modal-form
Stimulus controller with X-Modal-Request header pattern)
- Show read-only view button instead of edit for locked/finalized quizzes
- Add BankQuestion edit modal in question bank tab using same infrastructure
- Move modal action buttons into modal-footer via <template data-modal-footer>
- Fix IS_AUTHENTICATED_FULLY 403: replace ROLE_USER with IS_AUTHENTICATED
on all backoffice controllers and in security.yaml access_control
* feat: answer field UX improvements
- Auto-add one empty answer field when opening a blank question form
- Auto-append new empty field when typing in the last answer field
- Strip empty answer rows before submit (novalidate + JS cleanup)
- Tab key skips correct/delete buttons, jumping straight to next answer
* feat: add bank question via modal + dirty modal guard
- Add question in question bank now opens a modal instead of navigating
to a full-page form, consistent with the edit modal pattern
- Modal closes are blocked by static backdrop once the user has made any
change (input, checkbox, drag-reorder, sort, randomize, remove answer)
- Dirty state resets when the modal is fully hidden
* fix: modal save button + missing translations
- Replace form="id" cross-element approach with requestSubmit() for
reliable save button wiring in modal footer
- Re-call _bindDirty after validation-error re-render so dirty guard
is preserved across save attempts
- Translate missing Dutch strings: Order saved, Error saving order,
Question details, View
* feat: replace fetch-based modal forms with Turbo Frames (#181)
Enable @hotwired/turbo with Drive explicitly disabled, then migrate the
bo--modal-form Stimulus controller (custom fetch + X-Modal-Request pattern)
to a thin bo--modal controller that lets Turbo handle HTTP and DOM swap.
Adds frame templates for quiz questions and bank questions; controllers now
detect Turbo-Frame header instead of X-Modal-Request.
* fix: exclude auto-generated reference.php from pre-commit CS-fixer
* fix: use correct Turbo v8 session export to disable Drive
* fix: address CodeRabbit review findings on PR #183
- Add SeasonVoter::EDIT guard to QuizQuestionController::view()
- Add full-count check in reorder() to reject partial ordering payloads
- Retry once in _persistOrder(); lock drag and show dismissible alert on failure
- Remove tabindex="-1" from correct-answer toggle button (accessibility)
- Replace 'EMPTY'|trans placeholder with proper copy
- Add data-modal-title to question bank Edit button to prevent stale title
* fix: correct Dutch translations flagged in review
- 'Error saving order': 'Fout bij het opslaan van de volgorde' (consistent with sibling strings)
- 'Owner(s)': 'Eigenaar/Eigenaren' (unambiguous, correct Dutch plural)
* fix: set explicit form action URLs for Turbo Frame modal forms
When a form has no explicit action, Symfony renders action="" which the
browser resolves to the page URL, not the URL the Turbo Frame was
fetched from. This caused edits submitted via the modal to POST to the
wrong route and silently discard changes.
* fix: preserve answer ordering on save and add coverage for all sort operations
- Enable Turbo Drive and use visit() in modal controller so submit redirects to the page under the modal
- Add removeAnswer() to Question entity so Symfony form can manage the collection with PHP 8.5 private(set)
- Remove applyAnswerOrdering() from QuizQuestionController and QuestionBankController — it iterated the Doctrine collection in its old DB order and overwrote the ordering values submitted from the form
- Add QuizQuestionControllerTest covering answer ordering preservation and question reordering within a quiz
- Extend QuestionBankControllerTest with answer ordering tests for both new and edit bank questions
* fix: translate three missing Dutch strings in nl.xliff
* Updated CLAUDE.md
* refactor: replace addEventListener with Stimulus data-action in modal and question-list controllers
* refactor: replace addEventListener with Stimulus data-action in form-collection controller
Move drag-and-drop and auto-expand event handling from imperative addEventListener
calls to declarative data-action descriptors in answer_row.html.twig and the
collection target templates. Stimulus MutationObserver picks up the descriptors on
dynamically added rows, removing the need for _makeDraggable(). The ancestor-form
submit listener stays as addEventListener since Stimulus data-action cannot reach
elements outside the controller's subtree.
* feat: show label colour badges in question bank edit form
Replace plain checkbox text with coloured Bootstrap badge pills in the
labels section of the bank question edit form (both standalone and modal
frame variants). Adds choice_attr to pass data-colour to each checkbox,
then renders the input manually so the label can hold the badge without
the Bootstrap 5 form theme wrapping in a second plain-text label.
* Add CLAUDE.md, replace Makefile with Justfile, remove .junie
- Add CLAUDE.md with project overview, commands, architecture, and domain entity docs
- Remove Makefile in favour of the existing Justfile
- Remove .junie/AGENTS.md (knowledge transferred to CLAUDE.md)
- Update .gitignore: drop .junie/ entries, add .claude/settings.local.json
- Minor doc fixes in config/reference.php (typo, type correction)
* Clean up templates and CSS
- season.html.twig: remove dead empty column, drop redundant flex-row
- tab_overview.html.twig: extract Twig macro for confirm modals, fix duplicate aria-labelledby IDs
- tab_result.html.twig: remove dead comment, replace inline widths with CSS classes, simplify nested row/col forms to d-flex gap-1
- backoffice.scss: add col-result-xs/sm/md column width classes
- quiz.scss: replace broken display:grid + justify-self:center with flexbox centering
* Implement quizToXlsx() export and add export button
- QuizSpreadsheetService: implement quizToXlsx() as the inverse of
fillQuizFromArray() — writes quiz questions and answers to XLSX using
the same column layout as the import template
- BackofficeController: add exportQuiz() action at GET /backoffice/quiz/{quiz}/export
- tab_overview.html.twig: add Export to XLSX button in Quick actions
* Add unit tests for QuizSpreadsheetService
7 tests covering generateTemplate(), quizToXlsx(), and xlsxToQuiz():
- valid XLSX output and MIME type
- template without example reimports as empty
- template example data survives a reimport
- round-trip (export → reimport) preserves questions, answers, and correct flags
- empty quiz exports and reimports cleanly
- invalid MIME type throws InvalidArgumentException
- question with no answers throws SpreadsheetDataException with error list
* Fix quiz page vertical centering regression
The CSS cleanup broke vertical centering: flex on body causes main to
stretch full-width; place-items:center on a grid body only centers
items within their auto-sized track (not the track within body).
Fix: move background/color to html (full-viewport grid that centers
body), give body height:100% + display:grid + align-content:center
(centers the content track within full-height body) + justify-self:center
(shrink-wraps body width). Matches production behavior exactly.
* Improve quiz page layouts: WIDM-style answers and responsive centering
- Add green square answer buttons styled after the TV show
- Two-column answer grid for 6+ answers, single column on mobile
- fit-content centering for question pages so block matches question width
- Narrow fixed-width centering for form pages (enter name, select season)
* Use HeaderUtils::makeDisposition() for safe Content-Disposition filename
* Fix quizToXlsx to support unlimited answers and add header count tests
- Replace hardcoded 6-column arrays with dynamic Coordinate arithmetic
- Write data rows first to determine max answer count, write headers last
- Replace try/catch ErrorException in fillQuizFromArray with array_key_exists
- Add data-provider test covering 2, 6, 7, and 10 answers
- Add cross-question max-header and 7-answer round-trip tests
* Fix Sass healthcheck
* Improve quiz layout: add fixed topbar, include navigation, and clean up unused elements
- Add `.quiz-topbar` with fixed positioning and spacing in `quiz.scss`
- Update `base.html.twig` to include `quiz/nav.html.twig` in a new `nav` block
- Remove unused "Manage Quiz" button from `select_season.html.twig`
* Refactor generateTemplate to reuse quizToXlsx and add second example question
- generateTemplate now builds an in-memory Quiz entity and delegates to
quizToXlsx, eliminating duplicate spreadsheet-building logic
- Adds a second example question "Wie is de mol?" with 10 Dutch names
(5 male, 5 female) to better illustrate the import format
- Updates tests to assert both example questions and adds a test for the
blank-row halt behaviour in fillQuizFromArray (achieving 100% coverage)
* Move PHPUnit cache to /tmp to avoid writing into the mounted volume
* Update src/Service/QuizSpreadsheetService.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
---------
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit switches translations from YAML to XLIFF format for better standardization, updates the elimination preparation process with UI and functionality improvements, tweaks form structures, adjusts compose.override.yaml for improved asset handling, and optimizes back office usability with refined translation handling.
This commit adds initial importmap configuration to manage assets, updates the elimination preparation workflow with form enhancements and database changes, introduces new styles and JS assets, refines translations, and improves entity handling with an input bag update method.
This commit introduces a refactored EliminationFactory for better modularity, updates the elimination preparation process, and adds functionality to view eliminations. Backoffice templates and forms have been reorganized, minor translations were corrected, and additional assets like styles and flashes were included for enhanced user experience.