- 01 Jul, 2026 10 commits
-
-
Mahmoud Aglan authored
- All 96 blade views optimized for mobile (touch targets, responsive grids, stacked layouts) - Guest/login layout: respects branding CSS vars, touch-friendly inputs - Sidebar: RTL-correct mobile slide-in with backdrop blur - Topbar: compact mobile layout, overflow actions in user dropdown - All list views: dual layout (desktop table + mobile cards) - All forms: responsive padding, stacked submit buttons, 44px inputs - Attendance: 4-col action grid on mobile for quick marking - POS terminal: sticky bottom cart bar, radio card payment methods - Dashboard/receptionist: 2x2 stat grids, large action cards - app.css: safe-area utilities, print styles, touch min-heights - Zero RTL violations (logical properties only: ms/me/ps/pe/start/end) - Branding CSS vars respected throughout (--brand-primary etc.) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Invoice now includes service_fee_amount via PlatformFeeService (3% env-configurable) - Review step and payment step both show fee breakdown (subtotal + service fee = total) - Payment records the full total (including fee), not just the program price - Success screen shows a proper printable invoice with items table, totals breakdown, payment status badge, and a print button that hides nav/sidebar - Stores invoiceId for the computed invoiceForPrint property Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Wizard now checks on mount: active academy, branch, activities, programs with groups, and base prices. Shows a clear Arabic error screen instead of silently failing at confirm(). Also blocks step 3→4 if no price exists for the selected program. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
invoices.type only allows: standard, recurring, credit_note, proforma. The wizard was passing 'enrollment' which violated the DB constraint, causing a silent failure caught by the try/catch. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Step 2 now shows member vs non-member toggle + membership_id field - Price resolution checks base_prices.metadata->membership_type first, falls back to generic price if no membership-specific price exists - Membership type saved to participant record - Review step shows membership status - Computed property selectedProgramFee updates live when membership changes Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Bugs fixed: - Step 2 was skipped: checkDuplicates() advanced step AND nextStep() advanced again after it returned. Now nextStep() returns early after checkDuplicates() - No invoice was ever created: confirm() now creates a real invoice via InvoiceService with the price resolved from base_prices table - No payment was ever recorded: now uses PaymentService.recordPayment() which creates double-entry transaction and updates invoice paid_amount - fee_amount doesn't exist on training_programs — price comes from base_prices (polymorphic). Added resolveProgramFee() + selectedProgramFee computed property - Success screen now shows: participant number, program, invoice number/amount, payment status (paid vs outstanding) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
A receptionist should only: - Register participants (wizard) - Look up participant info (read-only) - Collect payments on existing invoices - Sell via POS - Open/close their cash session Removed: invoices.list (gates financial overview), invoices.create, wallets.list/view/credit, participants.update, guardians.update, enrollments.list, cash_sessions.manage, payments.list, pos_sessions.open/close/list Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Problems fixed: - MissingRulesException crash on step 4 (empty rules passed to validate()) - Guardian was never actually created as Person + Guardian record - Guardian was never linked to participant via guardian_participant pivot - Enrollment in program never happened (service didn't handle program_id) - medical_notes was passed at wrong level (it's on people table, not participants) - relation 'guardian' missing from validation (exists in DB CHECK constraint) Now the wizard properly: 1. Creates guardian Person + Guardian record (or reuses existing) 2. Creates participant Person record with all fields (phone, national_id, medical_notes) 3. Creates Participant via ParticipantService with guardian linked 4. Attaches guardian via guardian_participant pivot 5. Enrolls in program via EnrollmentService (auto-finds/creates group) 6. Added participant phone + national_id fields to step 2 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
Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 30 Jun, 2026 26 commits
-
-
Mahmoud Aglan authored
1. ParticipantForm: set branch_id from session in mount() so new participants get the active branch (was null, invisible in list) 2. SpaceLayoutService::update: compare config BEFORE updating the model so change detection works (was comparing same value to itself) 3. ReceiptSettings: use session branch_id instead of user->branch_id which could be null, preventing template save Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Livewire reserves $errors for the validation MessageBag. Using the same name as a public property causes a 500 error on render. 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
Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Invoices use billable morph (not direct branch_id). Scope through whereHasMorph on the participant's branch_id instead. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Financial report with daily revenue chart and top programs - Attendance report with per-participant stats and CSV export - Activity log viewer with filters and expandable details - System settings page with grouped tabs - Guardian portal dashboard (children, attendance, invoices) - Payment plan creation UI with installment preview - Coupon validator component - Invoice, group schedule, participant card, and certificate print views - Session rescheduling component - Participant freeze/unfreeze, bulk status change, status timeline - Enrollment history component - Dashboard widgets (revenue, enrollment trends) - Dark mode toggle, language switcher, locale middleware - API stats endpoint for mobile - Parent weekly SMS report command - Group capacity alert command Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
New features: - Waitlist manager with promote/cancel actions - Group transfer (move participant between groups) - Quick attendance marking (mobile-friendly trainer view) - Participant CSV import with preview and validation - User profile page with password change - Daily financial report (printable) - Reconcile group counts command - Deactivate expired enrollments command - Overdue invoice reminders (2x weekly) - Sidebar navigation updates (waitlist, transfer, quick attendance, import) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Major additions: - Branch scoping for all 15 list components via UsesBranchScope trait - Payment notification listener (email/SMS on every payment) - Print receipt button on POS, payment wizard, and invoice show - CSV export for participants, payments, invoices, enrollments - Global search in topbar (participants, invoices, groups) - Bulk messaging component (SMS/email by group, status, membership) - Weekly schedule visual timetable with program/trainer filters - Trainer dashboard (today's sessions, assigned groups, attendance links) - Duplicate participant detection in registration wizard - Enhanced dashboard: today's schedule, overdue invoices, birthdays, recent payments - 7 scheduled commands: daily summary, birthdays, low stock, expiring enrollments, installment reminders, overdue reminders - Health check endpoint (/health) - Participant transfer service and group capacity service - WhatsApp link helper for quick communication - User activity tracking middleware Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Prices are stored as base_prices with metadata.membership_type. Shows two fields: member price and non-member price (EGP). Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- BranchSwitcher component in topbar: select branch or "all branches" - UsesBranchScope trait: all components read active branch from session - Dashboard/Reports: filter by selected branch, show all when "all" - Receptionist wizards: use session branch instead of user->branch_id Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- membership_type now only allows 'member' or 'non_member' - Members must provide membership_id (club card number) - membership_id is unique per branch (same card can't register twice) - Shows membership_id input conditionally when type is 'member' 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
Participants and payments are now branch-scoped: migration adds nullable branch_id FK to both tables, all creation paths (ParticipantForm, receptionist wizards, InvoiceShow, POSService) pass branch_id through. Error page copy button rewritten to use a hidden textarea rendered server-side — eliminates JS string escaping issues with multi-line error messages and special characters. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Super admins and academy owners aren't tied to a branch. Instead of aborting, fall back to the first active branch so they can still access the receptionist desk. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Revenue model: 3% fee on every POS transaction, shown as "مصاريف خدمة" on receipts and invoices. The percentage is controlled ONLY via the PLATFORM_SERVICE_FEE_PERCENT env var — not editable by any admin. - PlatformFeeService: calculates fee from env var (default 3%) - POSService: includes service_fee_amount in transaction + invoice total - POS terminal UI: shows fee line before grand total - Receipt print: displays "مصاريف خدمة" row - Invoice show: displays service fee row - System settings: read-only banner showing the current fee percentage - Migration: adds service_fee_amount column to pos_transactions + invoices 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
- Receipt templates: configurable per-branch with field toggles, section ordering, and appearance settings (paper width, font size, currency symbol) - ReceiptController for printing POS/payment receipts via thermal layout - Receipt settings UI (Livewire) under Settings for branch managers - Branch-scoped receptionist: all 4 wizards enforce user's branch_id - Wallet freeze guard: deposit/withdraw now reject frozen wallets - Overdue invoice job: daily command transitions sent→overdue past due_date - Session generation scheduler: daily command creates upcoming training sessions - Default receipt template created during setup wizard Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Group-to-group segment overlap is blocked (hard error) - Trainer-to-group overlap is allowed (trainers supervise areas) - Checks pending unsaved assignments, not just DB reservations - Proper Arabic error message explaining the constraint Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
ScheduleConflictService checks ALL sources of trainer/group conflicts: - TrainingSchedule (recurring weekly assignments) - TrainingSession (specific date overrides) - TrainingGroup.head_trainer_id (implied trainer commitment) - Assignment model (formal polymorphic assignments) Schedule Builder improvements: - Flexible time picker (any minute interval, not just hourly) - Trainer availability indicators (green dot = free, orange = busy) - Group availability indicators (red warning if scheduled elsewhere) - Implied trainer warnings (group's head trainer conflict = soft warning) - New vs existing assignments visually distinct (green = unsaved) - Trainer name shown on existing reservations - Row/column/all selection helpers - Recurring booking checks group + trainer + space conflicts per date - Cancel series now deactivates the underlying TrainingSchedule - Final validation pass before commit (double-check for race conditions) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Full-featured schedule builder with: - Facility selection, date navigation, weekly view - Hourly time slot grid showing existing reservations - Grid/segment view with drag-drop group assignment - Trainer drag-drop with overlap support - Collision detection via SpaceCollisionService - Single-date save and recurring weekly booking (N weeks, multi-day) - Cancel single reservation or entire recurring series - RTL Arabic-first UI with Alpine.js interactivity Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Financial Overview: - New FinancialOverview Livewire component with P&L, break-even gauge, facility costs breakdown, revenue sources, collection rate - Migration adds monthly_rental_cost to facilities table - Monthly cost field added to facility form - Sidebar entry under المالية section Setup Wizard Enforcement: - Activities are now mandatory (min 1) - Programs are now mandatory with price > 0 - Facilities are now mandatory with monthly cost field - Auto-creates BasePrice records for programs during setup - Facility form includes operating hours and monthly cost Permission System Fix: - PermissionSeeder now called from DatabaseSeeder (has correct permission names matching route middleware: pos.sell, attendance.mark, etc.) - Branch manager gets all relevant module prefixes (inventory, pricing, wallets, activities, audit, notifications) - Receptionist gets pos.sell, pos.list, cash_sessions.manage - Accountant gets reports.view, wallets.view, pricing.list - PermissionService falls back to roles() pivot when primaryRole is null - SetCurrentAcademy middleware eager-loads roles.permissions as fallback Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Big prominent button copies full error report (exception, stack trace, request data, SQL queries, session) as formatted text to clipboard. Visual feedback with green check animation on success. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Features: - SpaceLayoutManager: full CRUD for facility layouts (grid/lanes/zones/custom) with visual segment preview and toggle availability - SpaceAssignmentWizard: 5-step wizard for assigning groups to facility segments Step 1: Search and select training group Step 2: Choose which schedule slot to assign Step 3: Pick the facility (if not already linked) Step 4: Visual grid/lane/zone selector with real-time collision detection Step 5: Success confirmation - Visual grid renders as clickable cells showing available/selected/occupied/disabled states - Real-time collision checking against existing confirmed reservations - Saves space_reservation_template on TrainingSchedule for auto-reservation on session creation - Fix: ReservationService.autoReserveForSession() now uses correct field names (space_reservation_template instead of segments, segment_ids instead of segments key) - Added "التخطيط" action link in facility list table - Added "تعيين المساحات" to sidebar navigation Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- BrandingSettings Livewire component with file uploads (logo, dark logo, favicon, signature, login background, invoice header) - Color picker for primary/secondary/accent/sidebar/status colors with live preview panel and preset palettes - Typography settings (Arabic/English font, base font size) - Invoice/receipt footer text and terms & conditions - Display toggles (logo in sidebar, logo in invoice, signature, compact mode) - CSS variables injected into app layout that drive sidebar, buttons, etc. - Sidebar now uses --brand-sidebar-bg/text/active variables - Logo displays in sidebar when uploaded - SystemSettingsSeeder populates all 6 groups with 50+ settings Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Fix PermissionSeeder: use correct column names (name not slug, permission_role not role_permissions) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Fix sidebar positioning (end-0 → start-0) so it appears on the RIGHT in RTL - Fix main content margin (me-64 → ms-64) to offset sidebar correctly - Fix TrainingProgram queries using non-existent is_active column → status - Fix User queries using is_active → status - Fix invoice type 'invoice' → 'standard' to match CHECK constraint - Fix CollectPaymentWizard using balance_due → due_amount + billable morphs - Fix notification template Blade parse error (unclosed parenthesis) - Align 10+ sidebar permission checks with actual route middleware permissions - Add missing permissions to seeder (pos.sell, inventory.list, reports.view, etc.) - Add comprehensive global error handler with full stack trace, SQL log, request data - Add Arabic error pages (500, 403, 404) with detailed debugging info Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 29 Jun, 2026 4 commits
-
-
Mahmoud Aglan authored
Audited all varchar-limited columns vs code that generates values for them: - BranchForm: validation was max:20 but column is varchar(10) — fixed - ActivityService: Str::slug output now capped at 90 chars (column is 100) - TrainingProgramService: same slug truncation fix - SetupWizard: slug generation for activities/programs also truncated - Logout: removed navigate:true (app→guest layout cross breaks) Affected columns and their limits: branches.code = varchar(10) ✓ fixed training_groups.code = varchar(10) ✓ already validated activities.slug = varchar(100) ✓ now truncated training_programs.slug = varchar(100) ✓ now truncated Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Str::slug on Arabic names can produce codes longer than 10 chars. Added Str::limit(..., 10, '') to truncate. Also removed navigate:true from redirects to avoid Livewire SPA issues between layouts. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Replaced x-data/x-show/x-transition with @if($currentStep === N)/@endif. Livewire re-renders the component on each step change, so only the active step's HTML is sent to the browser. No JS needed, no entangle, no Alpine timing issues. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
1. app.js was importing and starting Alpine manually, but Livewire 3/4 already bundles Alpine. Two instances meant $wire magic was unavailable. Now app.js just registers the focus plugin via Livewire's alpine:init hook. 2. Wizard x-data used @entangle which compiled to the old window.Livewire.find(id).entangle() syntax. Replaced with $wire getters which is the canonical Livewire 3+ approach. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-