diff --git a/CLAUDE.md b/CLAUDE.md index 87f1ea27..2a01ba87 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -138,6 +138,7 @@ Feature design documents and implementation plans are in `docs/features/`. Each - **API & OAuth2**: `docs/features/api/` — Public REST API (V1), OAuth2 server, Swagger docs, internal APIs, deprecated V0 - **Stripe Payments**: `docs/features/stripe.md` — Stripe integration for premium membership - **Opt-Out Features**: `docs/features/opt-out.md` — Streak and ranking opt-out for players +- **Competitions Management**: `docs/features/competitions-management/` — Community-driven event creation with admin approval, round management, puzzle assignment, table layout planning, and live stopwatch ### Feature Flags Active feature flags are documented in `docs/features/feature_flags.md`. **Always read and update this file** when adding, modifying, or removing feature flags. It tracks which files are gated, what feature each flag belongs to, and when it can be removed. diff --git a/assets/controllers/colorpicker_controller.js b/assets/controllers/colorpicker_controller.js new file mode 100644 index 00000000..0b33003f --- /dev/null +++ b/assets/controllers/colorpicker_controller.js @@ -0,0 +1,27 @@ +import { Controller } from '@hotwired/stimulus'; + +export default class extends Controller { + async connect() { + const [{ default: Coloris }] = await Promise.all([ + import('@melloware/coloris'), + import('@melloware/coloris/dist/coloris.css'), + ]); + + Coloris.init(); + Coloris({ + el: '#' + this.element.id, + format: 'hex', + alpha: false, + swatches: [ + '#fe696a', + '#ffffff', + '#000000', + '#0d6efd', + '#198754', + '#ffc107', + '#dc3545', + '#6c757d', + ], + }); + } +} diff --git a/assets/controllers/competition_form_controller.js b/assets/controllers/competition_form_controller.js new file mode 100644 index 00000000..fb3588ed --- /dev/null +++ b/assets/controllers/competition_form_controller.js @@ -0,0 +1,29 @@ +import { Controller } from '@hotwired/stimulus'; + +export default class extends Controller { + static targets = ['offlineFields', 'recurringField', 'typeSelectedFields']; + + connect() { + this._toggle(); + } + + toggle() { + this._toggle(); + } + + _toggle() { + const checkedRadio = this.element.querySelector('input[type="radio"]:checked'); + const hasSelection = checkedRadio !== null; + const isOnline = checkedRadio !== null && checkedRadio.value === '1'; + + this.offlineFieldsTargets.forEach(el => { + el.style.display = hasSelection && !isOnline ? '' : 'none'; + }); + + this.recurringFieldTarget.style.display = hasSelection && isOnline ? '' : 'none'; + + this.typeSelectedFieldsTargets.forEach(el => { + el.style.display = hasSelection ? '' : 'none'; + }); + } +} diff --git a/assets/controllers/marketplace_country_filter_controller.js b/assets/controllers/country_select_controller.js similarity index 100% rename from assets/controllers/marketplace_country_filter_controller.js rename to assets/controllers/country_select_controller.js diff --git a/assets/controllers/player_search_autocomplete_controller.js b/assets/controllers/player_search_autocomplete_controller.js new file mode 100644 index 00000000..f057cac4 --- /dev/null +++ b/assets/controllers/player_search_autocomplete_controller.js @@ -0,0 +1,40 @@ +import { Controller } from '@hotwired/stimulus'; + +export default class extends Controller { + static values = { + url: String, + }; + + initialize() { + this._onPreConnect = this._onPreConnect.bind(this); + } + + connect() { + this.element.addEventListener('autocomplete:pre-connect', this._onPreConnect); + } + + disconnect() { + this.element.removeEventListener('autocomplete:pre-connect', this._onPreConnect); + } + + _onPreConnect(event) { + const url = this.urlValue; + + event.detail.options.shouldLoad = (query) => query.length >= 2; + + event.detail.options.score = () => () => 1; + + event.detail.options.render = { + ...event.detail.options.render, + option: (item) => `
{{ 'competition.add_event_info'|trans }}
+ + {% for flash_message in app.flashes('success') %} +{{ competition.name }}
+ +{{ competition.name }} - {{ round.name }}
+ +| Name | +Location | +Dates | +Created | ++ |
|---|---|---|---|---|
| {{ competition.name }} | ++ {% if competition.locationCountryCode %} + + {% endif %} + {{ competition.location }} + | ++ {% if competition.dateFrom %} + {{ competition.dateFrom|date('d.m.Y') }} + {% if competition.dateTo %} + - {{ competition.dateTo|date('d.m.Y') }} + {% endif %} + {% else %} + - + {% endif %} + | ++ {% if competition.createdAt %} + {{ competition.createdAt|date('d.m.Y H:i') }} + {% endif %} + | ++ + View + + + + | +
| + + | +||||
No competitions pending approval.
+ {% endif %} +