- 03 Jul, 2026 2 commits
-
-
Mahmoud Aglan authored
- .htaccess: allow fonts.googleapis.com in style-src and fonts.gstatic.com in font-src for IBM Plex Sans Arabic - Add empty org-applications.css/js so module assets don't 404 Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Adds a new tournament workflow step between draft and start: - draft → "فتح التسجيل" → registration (players can join) - registration → "بدء البطولة" → in_progress New route: POST /tournaments/{id}/open-registration Sets status from 'draft' to 'registration' with audit log. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 22 Jun, 2026 1 commit
-
-
Mahmoud Aglan authored
Local uploads were unreachable by the player app on a different domain. Now uploads go to profile-images/branding/ bucket with upsert, producing a full public URL that the player app can load directly. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 21 Jun, 2026 6 commits
-
-
Mahmoud Aglan authored
- last_seen → last_seen_at (explains why stats showed 0) - country → country_code - Updated searchPlayers select and individual view JS Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The notifications.data column is JSONB. Database::insert() already json_encodes the full payload, so passing json_encode() double-encodes it into a string. Mobile app expects a Map, not a string. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- getTargetPlayers now uses select=* (matches working players module) - Removed moduleJS for compose/individual views (JS is inline) - These views were referencing non-existent JS file paths causing 404s Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
csrfField() doesn't exist — the actual pattern is a hidden input with name="_csrf" and value from Auth::csrfToken(). Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Moved level, coins, and created_at to PostgREST `and` operator so min+max ranges work together instead of overwriting each other - Batch-insert campaign recipients (100/batch) instead of N HTTP calls Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Adds campaign management, demographic targeting, individual player notifications, reusable templates, scheduling, and campaign history. All notifications delivered via Supabase Realtime (insert into notifications table). Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 06 Jun, 2026 3 commits
-
-
Mahmoud Aglan authored
Kong requires the apikey query param for public object access via img tags. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Kong gateway requires the apikey header alongside Authorization. Without it, storage uploads fail with "No API key found in request". Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Form now supports file upload (enctype multipart/form-data) - Accepts PNG, JPG, WebP, GIF up to 10MB - Uploads to Supabase Storage (assets bucket, ads/ prefix) - Shows current image preview in edit mode - Falls back to URL field if no file uploaded - List view shows image thumbnails - Added splash and between_games ad slots Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 05 Jun, 2026 1 commit
-
-
Mahmoud Aglan authored
Supports the player app's in-game ad banner system. New columns added to ad_campaigns table via ALTER TABLE. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 31 May, 2026 1 commit
-
-
Mahmoud Aglan authored
The isStalemate() called the Stockfish API on every move just to check if the opponent had legal moves — doubling API calls from 80 to 160 per game. Now relies on the API returning no best_move as game-over signal. Differentiates checkmate vs stalemate by eval magnitude. Also reduced max moves from 80 to 60 — bot games at these levels should resolve well before that. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 30 May, 2026 15 commits
-
-
Mahmoud Aglan authored
Part A - Bot Game Engine (BotGamePlayerService): - Maps player ratings to 7 bot personalities (amina→grandmaster) - Plays actual chess games move-by-move via Stockfish API - Full FEN tracking, UCI→SAN conversion, PGN generation - Game termination: checkmate, stalemate, 50-move, repetition, 80-move adjudication - Stores complete games in existing `matches` table (pgn, moves JSONB, fen) Part B - Game Viewer: - Interactive chessboard (CSS grid + Unicode pieces) - Move-by-move navigation (first/prev/play/next/last + keyboard arrows) - Move list with click-to-jump - Last move highlighting - Auto-play mode (800ms per move) - Uses chess.js for position replay from UCI moves Integration: - "لعب مباريات حقيقية" checkbox in bot testing panel - "♟ عرض" (View Game) button next to each completed pairing with match_id - Route: /tournaments/{id}/game/{matchId} Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
1. Rounds tab now shows White | Result | Black columns with proper result badges (1-0, 0-1, ½-½) instead of raw enum strings. 2. BotSimulationService stores whiteName/blackName in results JSONB. 3. Fixed live-tournaments admin-controller and LiveDataService json_decode crashes on already-decoded JSONB arrays. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
tournament_registrations.player_id had FK to profiles(id) which rejected bot player inserts since bot UUIDs aren't real profiles. Dropped the constraint so bot testing works. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
1. pairings/results JSONB columns already decoded by Supabase — added is_array check before json_decode (same pattern as tiebreak fix). 2. Bot player_id was 'bot_xyz' string but column is UUID type — PostgREST silently rejected every insert. Now generates proper v4 UUIDs. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Controller was passing the raw response body (which has data + roundNumber keys) directly to the view. The foreach iterated over the wrapper object instead of the standings array. Also fixed field name mappings: Swiss API uses 'name' not 'player_name', 'gamesPlayed' not 'games_played', 'tiebreakValues' array not 'tiebreak'. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
If the Swiss tournament was already started (e.g. from a previous attempt), don't fail — just update local status and proceed with round generation. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The API rejects bodiless POSTs without Content-Type (415 Unsupported Media Type) AND rejects Content-Type with literally no body (Body cannot be empty). Solution: always send Content-Type, and for POST/PATCH/PUT with null body, send empty object {} as body. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
1. Content-Type: application/json only sent when body is not null. Swiss API rejects bodiless POST/GET with that header. 2. Controller start() now calls Swiss API /start endpoint. 3. simulateNextRound() auto-starts Swiss tournament if local status is still draft/registration. 4. generateRound response parsing fixed — data is in {round:{id,...}}. 5. getPairings response wrapped in {data:[...]} — now handled. 6. Pairing field names use camelCase (whitePlayerId not white_player_id). 7. Player ratings fetched from listPlayers instead of expecting them embedded in pairing objects. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
1. ApiProxy was sending Content-Type: application/json on GET requests which the Swiss API rejects ("Body cannot be empty when content-type is set to application/json"). Now only sends Content-Type for POST/PATCH/PUT methods. 2. Players tab now reads bot name/rating from bot_metadata JSONB instead of non-existent player_name/rating columns. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Swiss API wraps list responses in {data:[...]}. Also added null checks at each step and detailed error messages so failures are diagnosable. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Previously the bot testing section was hidden when swiss_api_tournament_id was null. Now it always shows, and when you click "Fill with Bots" it auto-creates the Swiss org/event/tournament on the fly. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Supabase returns JSONB columns as native arrays, not JSON strings. json_decode() on an array throws TypeError. Now checks if already array. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Views were referencing columns that don't exist: - rounds_count → rounds_total/swiss_rounds - entry_fee → entry_fee_coins - prize_pool → prize_pool_coins - start_date → starts_at - end_date → registration_closes_at - organization_id → org_id - started_at → removed (column doesn't exist) Also fixed start() to skip bot players (already registered via bulk import) and not crash when player_id doesn't match a real profile. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The store() method used column names that don't exist in the database: - rounds_count → rounds_total + swiss_rounds - entry_fee → entry_fee_coins - prize_pool → prize_pool_coins - start_date → starts_at - organization_id → org_id - swiss_org_id, swiss_event_id → removed (don't exist in table) - created_by → removed (UUID FK to profiles, admin users aren't in profiles) Also: - Time control is now a proper dropdown with all 14 enum values grouped by category (bullet/blitz/rapid/classical) - Format dropdown now uses correct enum values (swiss_to_bracket, team_battle instead of invalid group_stage) - Swiss API tournament creation limited to formats it actually supports (swiss, round_robin) — other formats use local bracket/arena engines - Insert failure now shows error instead of fake success message - On success, redirects to the new tournament page instead of list Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Adds a complete bot testing system to the Arbiter Tools tab: - Fill tournaments with bot players (8-128) with realistic Arabic names and bell-curve rating distribution - Auto-play individual rounds using ELO probability simulation - Simulate entire tournament with progress bar UI (sequential AJAX) - Cleanup bots with one click - Bot players marked with
🤖 badge in players list New files: BotSimulationService.php, _bot_testing.php, migration 005 Also updates EL3AB_PLAYER_APP_DATA.md with domino/ludo/theme/tournament schemas Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 26 May, 2026 2 commits
-
-
Mahmoud Aglan authored
Auth::csrfField() doesn't exist — replaced all 24 occurrences across org modules with the correct <input type="hidden" name="_csrf" value="<?= Auth::csrfToken() ?>">. Also fixed org-leaderboards index.php which was actually the org-board view (using $org variable that wasn't passed by the index action), renamed it to org-board.php and created a proper index.php for global rankings. Fixed org_members column name (user_id → player_id) in org-applications controller. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Full public-facing live tournament system: - Public pages at /live/{slug} with no auth required - 5 visual themes (default, neon, minimal, royal, arena) - Live standings, pairings, bracket with auto-refresh polling - Countdown timer, player roster, results feed, timeline - Prize display, announcements feed, photo gallery - QR code sharing, social share, embeddable widget - SEO meta tags (OG, Twitter Cards, JSON-LD) - Tournament ad slots with impression/click tracking - Analytics tracking (views, sections, referrers) - Admin config panel: visibility toggles, custom CSS, slug management - Mobile responsive with dark/light mode support - Print-optimized view New DB tables: tournament_announcements, tournament_ad_slots, tournament_page_views, tournament_media Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 25 May, 2026 9 commits
-
-
Mahmoud Aglan authored
- Update variables.css surfaces to match brand navy (#152132) - Add sidebar-bg and input-bg CSS variables with fallbacks - Add "Reset to Brand Identity" button in branding settings - Add resetColors controller action that reverts all colors to their default_value from platform_theme - Reset live DB colors to brand defaults Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Add 18 org ecosystem modules: frames, invites, applications, chat, treasury, challenges, achievements, transfers, recruitment, events, content, leaderboards, partnerships, loyalty, rosters, training, media, spotlights (controllers + views + CSS assets) - Add core services: SupabaseStorage, OrgPermissions, ThemeService - Add migration 003 (23 new tables, RLS policies, indexes) - Fix games edit not saving (wrong column names: icon→icon_url, matchmaking_config→config) - Fix branding colors not reflecting (added ThemeService to inject DB theme colors as CSS variable overrides at render time) - Update permissions.php with new module access for admin/org roles - Update sidebar with org ecosystem navigation section - Add 120+ new routes for all org modules Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
-
Mahmoud Aglan authored
API returns {bots: [...], count: N} not a flat array. Also fixed pool stats mapping (pool_alive/pool_idle) and portrait URLs to use full Stockfish API base URL. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- ads: remove non-existent columns (advertiser, placement, cpm, title, body, click_url, image_url), use actual schema (campaign_type, target_slots, target_games, budget_daily) - moderation: resolution→action_taken, resolved_by→reviewed_by (UUID), resolved_at→reviewed_at - tournaments: el3ab_tournament_players→tournament_registrations, swiss_tournament_id→swiss_api_tournament_id - players: remove email from insert (not in profiles), banned_at removed, use ban_expires_at - notifications: remove is_broadcast (not in schema), detect broadcast by null user_id - settings: is_editable→is_secret, handle JSONB value column - auth: last_login→last_login_at - Created el3ab_tournament_rounds table on server Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Table renames: transactions→economy_transactions, organizations→el3ab_organizations Column fixes: user_id→player_id, last_active_at→last_seen_at, reported_id→reported_player_id, organizer_id→created_by, actor→actor_id, entity_type→resource_type, entity_id→resource_id Schema match: economy_transactions uses type credit/debit + reason + source_id, audit_log uses actor_id/resource_type/resource_id/details, org_members uses player_id, ad_campaigns uses spent_total. Created admin_users, approval_requests, workflow_rules tables on server. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
-
Mahmoud Aglan authored
Complete overhaul from single-admin to multi-role multi-org system: - Auth: multi-user login from admin_users table with 9 roles (superadmin, admin, moderator, org_admin, org_manager, tournament_organizer, sponsor, charity, viewer) - Permissions: granular permission matrix with org-scoping - RuleEngine: event-driven workflow automation - Users module: full CRUD for admin user management - Workflows module: approval queue, automation rules, org requests - Dashboard: role-aware with scoped data per role - Sidebar: permission-filtered navigation per role - Topbar: shows role badge next to username - Login: supports all user types Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-