- 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 11 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>
-
Mahmoud Aglan authored
- Moved sidebar from left to right for proper RTL layout - Added full customization panel at /branding with 20 live UI preferences: sidebar width, font size, card style, animation speed, accent color, table density, toast position, content width, sidebar style, border radius, time format, number format, reduce motion, high contrast, color blind modes, focus mode, sounds, auto save, page transitions, compact header - All preferences persist in localStorage and apply instantly - Added customization.css + customization.js engine Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
-