diff --git a/assets/controllers/game_config_controller.js b/assets/controllers/game_config_controller.js new file mode 100644 index 0000000..ada75ff --- /dev/null +++ b/assets/controllers/game_config_controller.js @@ -0,0 +1,41 @@ +import { Controller } from '@hotwired/stimulus'; + +export default class extends Controller { + static targets = ['hintType', 'awardSection', 'allAwards', 'awardType']; + + toggleAwardSection() { + const awardChecked = this.hintTypeTargets.find( + (el) => el.name === 'hint_award' + )?.checked; + + this.awardSectionTarget.style.display = awardChecked ? '' : 'none'; + } + + toggleAllAwards() { + const checked = this.allAwardsTarget.checked; + this.awardTypeTargets.forEach((el) => { + el.checked = checked; + }); + } + + syncAllAwards() { + const allChecked = this.awardTypeTargets.every((el) => el.checked); + this.allAwardsTarget.checked = allChecked; + } + + hintTypeTargetConnected() { + this.#bindMinOneChecked(); + } + + #bindMinOneChecked() { + this.hintTypeTargets.forEach((el) => { + el.addEventListener('change', () => { + const checked = this.hintTypeTargets.filter((e) => e.checked); + if (checked.length === 0) { + el.checked = true; + } + this.toggleAwardSection(); + }); + }); + } +} diff --git a/assets/styles/app.css b/assets/styles/app.css index d76d27c..bcedeec 100644 --- a/assets/styles/app.css +++ b/assets/styles/app.css @@ -732,6 +732,140 @@ body { font-size: 16px; } +/* ── Game config panel ── */ + +.config-panel { + width: 100%; + max-width: 360px; + margin-bottom: 24px; +} + +.config-section { + padding: 12px 0; +} + +.config-section + .config-section { + border-top: 1px solid var(--border); +} + +.config-section-title { + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--text-muted); + margin-bottom: 10px; +} + +.config-section-subtitle { + font-size: 11px; + font-weight: 600; + color: var(--text-muted); + margin: 10px 0 6px; +} + +/* Toggle switch */ + +.config-toggle { + display: flex; + align-items: center; + justify-content: space-between; + cursor: pointer; +} + +.config-toggle-label { + font-size: 14px; + font-weight: 500; + color: var(--text); +} + +.toggle-switch { + appearance: none; + width: 40px; + height: 22px; + background: var(--border); + border-radius: 100px; + position: relative; + cursor: pointer; + transition: background 0.2s; +} + +.toggle-switch::before { + content: ''; + position: absolute; + top: 2px; + left: 2px; + width: 18px; + height: 18px; + background: white; + border-radius: 50%; + transition: transform 0.2s; +} + +.toggle-switch:checked { + background: var(--orange); +} + +.toggle-switch:checked::before { + transform: translateX(18px); +} + +/* Hint type checkboxes */ + +.config-hint-types { + display: flex; + gap: 16px; +} + +.config-checkbox { + display: flex; + align-items: center; + gap: 6px; + font-size: 13px; + color: var(--text); + cursor: pointer; +} + +.config-checkbox input[type="checkbox"] { + accent-color: var(--orange); +} + +/* Award type list */ + +.config-award-types { + margin-top: 4px; +} + +.config-award-list { + border: 1px solid var(--border); + border-radius: var(--radius-sm); + max-height: 150px; + overflow-y: auto; + padding: 6px 0; +} + +.config-award-list .config-checkbox { + padding: 4px 12px; +} + +.config-award-list .config-checkbox:first-child { + padding-bottom: 6px; + margin-bottom: 2px; + border-bottom: 1px solid var(--border); +} + +/* Flash messages */ + +.flash-error { + margin-top: 16px; + padding: 10px 16px; + background: #fef2f2; + color: #991b1b; + border: 1px solid #fecaca; + border-radius: var(--radius-sm); + font-size: 13px; +} + .start-loader { display: none; width: 48px; diff --git a/templates/homepage/index.html.twig b/templates/homepage/index.html.twig index 6cbc65c..13c8ace 100644 --- a/templates/homepage/index.html.twig +++ b/templates/homepage/index.html.twig @@ -56,8 +56,64 @@ {% else %}