1. 27 Jul, 2026 7 commits
    • Mahmoud Aglan's avatar
      Harden Paymob integration with 4-tier credential fallback · 0aea2391
      Mahmoud Aglan authored
      Credential resolution order: academy system_settings → current_academy
      setting → config/services.php → env variable. Callback endpoint now
      resolves academy from the payment record itself (no auth context needed).
      Failed payments are explicitly marked with failure reason. Added HTTP
      timeouts to all Paymob API calls.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      0aea2391
    • Mahmoud Aglan's avatar
      Mobile API Phase 4+5: Paymob payments, absence reporting, messaging · ef15aa1b
      Mahmoud Aglan authored
      - Paymob gateway integration (auth→order→payment key→HMAC callback)
      - Payment initiation endpoint with pending record + iframe URL
      - Webhook callback with double-processing prevention
      - Guardian absence reporting (excused status for future sessions)
      - Contact messages (send + list with reply support)
      - System settings migration seeding all mobile/payment config keys
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      ef15aa1b
    • Mahmoud Aglan's avatar
      Mobile API Phase 3: Academy explore + shop endpoints · 40734561
      Mahmoud Aglan authored
      - Create AcademyController (public, no auth required):
        - GET academy/news — paginated news articles with images
        - GET academy/news/{uuid} — full article body
        - GET academy/programs — active training programs with activity info
        - GET academy/events — upcoming published events with registration status
        - GET academy/gallery — paginated media gallery
      - Create ShopController (auth required):
        - GET products — essential products with purchase history check
          (includes already_purchased_at per participant per year)
      - Total: 26 API endpoints
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      40734561
    • Mahmoud Aglan's avatar
      Mobile API Phase 2: Push notifications via Firebase Cloud Messaging · 0b2c6122
      Mahmoud Aglan authored
      - Install kreait/firebase-php SDK
      - Create PushNotificationService with 3-tier credential resolution
        (system_settings → storage file → env var, graceful degradation)
      - Auto-deactivate invalid/unregistered FCM tokens on send failure
      - Add Push case to NotificationChannel enum
      - Create 6 event listeners for push notifications:
        - AttendanceMarked → notify guardians (present/absent)
        - PaymentReceived → confirm payment to guardians
        - InvoiceCreated → alert guardians of new invoice
        - SessionCancelled → notify all group participants
        - EnrollmentCreated → confirm enrollment to guardians
        - EvaluationShared → notify guardians of new evaluation
      - Register all listeners in EventServiceProvider (queued)
      - Create NotificationController API endpoints:
        - GET notifications (paginated + unread count)
        - PATCH notifications/{id}/read
        - POST notifications/read-all
        - GET/POST notifications/preferences
      - Create scheduled push commands:
        - push:session-reminder (every minute, 30min before session)
        - push:installment-due (daily, 1 and 3 days before due)
      - Add channel_push column to notification_preferences
      - Total: 20 API endpoints now live
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      0b2c6122
    • Mahmoud Aglan's avatar
      Mobile API Phase 1: Sanctum auth, OTP flow, participant endpoints · 7a8a5594
      Mahmoud Aglan authored
      - Install Laravel Sanctum, add HasApiTokens to User model
      - Register API routes under /api/v1/ prefix in bootstrap/app.php
      - Create AppConfigController (public): academy branding, feature flags, auth mode
      - Create AuthOtpController: OTP request/verify with demo mode, rate limiting
      - Create DeviceController: FCM token register/refresh/delete
      - Create ParticipantController: children, show, summary, schedule, attendance, invoices, enrollments
      - Create API Resources (User, Participant, Session, Attendance, Invoice, Enrollment)
      - Create device_tokens migration with platform CHECK constraint
      - Create DeviceToken model with BelongsToAcademy trait
      - Add mobile API implementation plan document
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      7a8a5594
    • Mahmoud Aglan's avatar
      Rewrite mobile app plan — per-instance architecture + Firebase + demo auth · 0da841fd
      Mahmoud Aglan authored
      - One app per client: single instance.dart config file change = new build
      - Firebase: one project per client, service account JSON uploaded to system settings
      - Auth: demo mode (OTP=123456) for testing, real SMS when provider configured
      - Runtime branding: logo/colors fetched from /api/v1/app/config, not hardcoded
      - Full Firebase setup checklist, notification flow diagram, deployment checklist
      - New client deployment: Firebase (5min) + Flutter build (5min) + config (2min)
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      0da841fd
    • Mahmoud Aglan's avatar
      Add essential product duplicate warning in POS + update mobile app plan · 733ed4d3
      Mahmoud Aglan authored
      POS Terminal now checks if an essential product was already purchased by
      the selected participant this year. Shows amber warning with the purchase
      date — allows the sale to proceed, just warns the admin.
      
      Also expanded mobile app plan with: explore academy (news, gallery),
      shop for essential products from app, event registration, and the
      corresponding API endpoints needed on the system side.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      733ed4d3
  2. 26 Jul, 2026 14 commits
  3. 25 Jul, 2026 14 commits
  4. 24 Jul, 2026 5 commits
    • Mahmoud Aglan's avatar
      Fix guardian relationship_type CHECK violation — use 'father' instead of invalid 'guardian' · 1cae2631
      Mahmoud Aglan authored
      The guardians_relationship_type_check constraint allows: father, mother,
      grandfather, grandmother, uncle, aunt, sibling, legal_guardian, other.
      The ParticipantForm was inserting 'guardian' which isn't a valid value.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      1cae2631
    • Mahmoud Aglan's avatar
      Allow event deletion from any status + default website is_published to true · a4e6d437
      Mahmoud Aglan authored
      - Remove draft-only restriction on delete button in EventShow
      - EventService::delete() no longer blocks deletion based on status
      - Migration sets website_settings.is_published default to true and updates existing rows
      - Fixes 404 on public event pages caused by unpublished website settings
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      a4e6d437
    • Mahmoud Aglan's avatar
      Upgrade event form builder with 20+ new features — radio, uniqueness, maps, conditionals · ce5c6e89
      Mahmoud Aglan authored
      - Add radio, national_id, location, section_divider, terms field types to FormFieldType enum
      - Add field uniqueness constraint (blocks duplicate registrations per unique field)
      - Add Google Maps locations support (JSONB column + map embed on public page)
      - Add conditional field visibility (show field only when another field equals a value)
      - Add min/max length, min/max value, regex pattern validation per field
      - Add allow_other option for select/radio/multi_select fields
      - Add field description/help text, placeholder, default value
      - Add duplicate field action in form builder
      - Add section dividers for visual grouping
      - Add terms acceptance field type with URL link
      - Sanitize form fields before save (auto-fill values, strip invalid options)
      - Public registration form uses Alpine.js for conditional visibility
      - Character counters shown when max_length is set
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      ce5c6e89
    • Mahmoud Aglan's avatar
      Fix website builder audit issues — missing $sections + forbidden href=# · a26be026
      Mahmoud Aglan authored
      - PublicEventController: pass $sections to views (navbar/footer crash without it)
      - Navbar: replace href="#" with href="#section-hero" (forbidden pattern)
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      a26be026
    • Mahmoud Aglan's avatar
      Add Events/Tournaments system — full vertical slice · 44c8d8aa
      Mahmoud Aglan authored
      Complete events module with admin CRUD, public registration, and management:
      - Migrations: events, event_registrations, media collections, permissions
      - Domain: Event/Enums (5), Models (2), Services (EventService, EventRegistrationService)
      - Admin: EventList, CreateEventWizard (4-step with form builder), EventShow, EventRegistrationList
      - Public: event listing + detail pages under /site/{slug}/events with Livewire registration form
      - Form builder: button-based add/remove/reorder fields stored as JSONB
      - Registration: dynamic validation from form_fields, person matching, registration numbers
      - Admin registrations: dynamic columns, bulk confirm/cancel, CSV export
      - Livewire scripts added to website layout for public forms
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      44c8d8aa