- 09 Jul, 2026 13 commits
-
-
Mahmoud Aglan authored
Cast config values to string with null-coalescing fallback, and add empty-string defaults to env() calls so instances without WhatsApp configured still boot without TypeError. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The demo_academy DB doesn't have organizations/users tables with those exact names. Use plain indexed columns instead. 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
- WhatsAppService: send text, template, image, document messages - Bulk send to groups/status/custom selections - Message log with status tracking (sent/delivered/read/failed) - Three Livewire pages: Send Message, Send Template, Message Log - Migration for whatsapp_messages table - Added 'whatsapp' channel to NotificationChannel enum - Wired into NotificationService for automated notifications - Sidebar section "واتساب" with 3 items - Config via WHATSAPP_PHONE_NUMBER_ID + WHATSAPP_ACCESS_TOKEN env vars Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Auto-seed default sections on first visit when none exist - Every section now shows skeleton placeholders when empty (branches, partners, pricing, trainers, stats, schedule) - Converted remaining dark sections to light theme (branches, trainers, pricing, contact, schedule) for consistency - Stats band keeps dark bg for visual contrast - Fresh deploy = beautiful skeleton website ready for client to imagine Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Fixes Route [inventory.purchase-orders.create] not defined error by adding the missing routes and creating PurchaseOrderForm + PurchaseOrderShow Livewire components with full Arabic UI. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Default background: white, text: dark gray, accent: blue - Hero/navbar/footer stay dark (branded primary color) - All sections show skeleton placeholder cards when no data exists - Removed all hard-coded oklch dark values from section views - Cards, testimonials, FAQ items now use white bg + subtle borders - Empty states show shimmer animation + "لم تُضف ... بعد" message Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Use null-coalescing for age_from/age_to/duration_months (columns don't exist yet) - Handle __PHP_Incomplete_Class from stale cache by re-fetching on type mismatch - Add cache:clear to deploy entrypoint to prevent stale cache after rebuilds Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Livewire's ExtendedCompilerEngine misparses @if inside <script> tags. Replaced inline Blade conditionals with @php block + json_encode. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Route / now serves academy public website (no auth required) - Dashboard moved to /dashboard - Login/Dashboard button added to website navbar (desktop + mobile) - Added "الموقع الإلكتروني" section to sidebar with all 9 CMS pages - Added missing inventory items (POs, Kits, Stock Counts) to sidebar - Configured explicit middleware redirects for guest/auth flows Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Add branch_id accessor to User model (resolves from role_user pivot) - Create AppliesRoleScope trait for one-liner scope enforcement - Enhance PermissionService: include head_trainer_id in group lookup, add training_programs and invoices table support for own_groups scope - Apply AppliesRoleScope to 16 list components: ParticipantList, GroupList, EnrollmentList, AttendanceList, InvoiceList, ProgramList, EvaluationList, CashSessionList, WalletList, AssignmentList, PersonList, FacilityList, ProductList, PurchaseOrderList, KitList, StockCountList Now trainers only see their assigned groups/participants, branch managers only see their branch data, parents only see their children, and receptionists are branch-scoped. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Detect on mount if user already has Trainer/Employee/Guardian records - Show green notice when record exists, amber warning when role implies record but none exists (orphan state) - Allow entity creation on save even without role change when entities are missing (repair orphaned users from before the redesign) - Disable create toggles when record already exists to prevent duplicates Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- CreateTrainerWizard: 9-step flow with activities, user account creation, and initial group assignment (was 6 disconnected steps) - CreateProgramWizard: 7-step flow with head trainer, schedule template, initial group, BasePrice record, facility (was 4 steps, no group/trainer) - NewRegistrationWizard: add parent account creation step so guardians can log in to the Parent Portal immediately - UserForm: role-aware prompts — assigning trainer role creates Trainer+Employee records, parent role links Guardian, staff creates Employee - EnrollmentForm: 3-panel guided experience with group cards, capacity bars, live price preview from PricingService, and schedule conflict detection - TrainerCredentialsGenerated event for async email delivery Closes the "isolated CRUD screens" problem — every entity creation now handles the full business workflow in a single transaction. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 07 Jul, 2026 3 commits
-
-
Mahmoud Aglan authored
- PurchaseOrderList: status filter, receive/cancel actions - KitList + KitForm: CRUD with dynamic components, assemble/disassemble - StockCountList + StockCountForm: warehouse picker, variance display - Register routes for all new inventory components - config/mail.php: add SSL stream options for self-signed cert bypass - Update gap-analysis.md to mark completed items Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Multi-tenant public website system: each academy gets a data-driven advertising site at /site/{slug} with 16 customizable sections, theme editor, gallery, testimonials, FAQ, news, partners, and contact form management. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
4 tiers in EGP: نسبة فقط (Free/12%), المبتدئ (1000/7.5%), المؤسسي (3500/5%), الاحترافي (10000/3.5%). Interactive slider shows total cost based on monthly collections volume, highlights the best-value plan dynamically. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 06 Jul, 2026 1 commit
-
-
Mahmoud Aglan authored
1. User form: add hint that email is used as login username 2. Dashboard low stock widget: only show products below min_stock_level (was showing all) 3. Dashboard attendance widget: link to filtered view showing only sessions without attendance 4. Trainer form: require at least one activity selected (validation + UI) 5. Cross-reference: show activities on trainer list, show trainers on activity cards Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 05 Jul, 2026 23 commits
-
-
Mahmoud Aglan authored
Laravel 13 base Controller has no AuthorizesRequests trait. Use Gate::authorize() facade instead. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Without branch filtering, the collection rate showed global stats even when viewing a specific branch. Now filters invoices by branch via their associated payments. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The revenue query filtered by invoice_items.branch_id which doesn't exist, causing 0 results when a branch is selected. Use payments.branch_id directly since payments already track their branch. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The template variable display used nested {{ '{{' }} syntax which confused Blade's compiler, causing an "Unclosed '(' does not match '}'" error. Use string concatenation with {!! !!} to output literal braces. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
11 Livewire screens: Home dashboard, Schedule (weekly), Attendance (monthly), Finances (invoice list + detail), Profile, Child Detail (with tabs), Evaluation Detail, Excuse Form, Notifications, and Programs browser. Custom parent layout with fixed bottom nav bar (5 tabs). Redirect parent role login to new portal. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Dashboard: - Primary action (new registration) is now a full-width hero card - Secondary actions are a compact 2x2 icon grid Registration wizard: - Mobile step indicator: compact progress bar + step name instead of cramped 5-circle stepper - Sticky bottom nav bar on mobile (fixed position, safe-area aware) so Back/Next are always reachable without scrolling - Activity selection uses horizontal scrollable pills on mobile - Desktop layout remains unchanged (sm: breakpoint gates all changes) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
New instances and the service fallback now default to the academy paying the platform fee rather than adding it to the client's invoice. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
GroupStatus is a backed enum — need ->value to get the string for __(). Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The SystemSettingsForm only displayed settings already in the DB, so platform_fee_customer_pays was invisible. Switched the route to use the schema-driven Admin\SystemSettings component which always renders all defined settings with their defaults. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Quick actions now includes: new registration, enroll existing, collect payment, attendance. Below it a full "Creation Wizards" grid with buttons for every wizard (program, group, transfer, invoice, facility, employee, trainer, pricing rule, product, stock adjustment, cash session, setup). Each button is permission-gated and uses wire:navigate. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- CreateProductWizard: fix permission mismatch (products.create→inventory.create), add SKU uniqueness validation, redirect to list after success instead of dead-end - ProductForm: set branch_id on new products - ProductList: fix dynamic Tailwind classes (use full class strings for JIT) - GroupList: fix dynamic Tailwind status badge classes - POSTerminal: remove dead addProgram() method and unused imports - CSS: add safelist comment for dynamic color classes used via Blade interpolation Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- POS Terminal now shows products tab with addProduct() method (programs are enrolled via receptionist desk, not POS) - Product list and POS show branch products + academy-wide (null branch) - CreateProductWizard and ProductForm now set branch_id on create - Product model gets ManglesUniqueOnDelete for SKU collision prevention - Clicking a product in POS adds it to cart (or increments qty if exists) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Add ManglesUniqueOnDelete trait that appends a timestamp suffix to unique fields (code, slug, sku, employee_number) when a record is soft-deleted, freeing the value for new records. Also make group code generation collision-resistant by checking withTrashed(). Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Programs: activate (draft/closed→active), close (active→closed) Groups: activate (forming/on_hold→active), pause (active→on_hold) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- GroupSchedulePrintController used $this->authorize() but Laravel 13's base Controller has no AuthorizesRequests trait — switched to Gate::authorize() - Added deleteGroup() to GroupList with full cascade: sessions (attendance auto-cascades), schedules, enrollments, waitlists, then the group itself - Delete button with wire:confirm for Arabic confirmation prompt, gated behind groups.delete permission Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
1. ProgramForm now passes status to service — programs default 'active' (the property was set but never included in the data array, so the DB default 'draft' won) 2. Receptionist wizard now finds groups with branch_id=NULL (academy-wide programs) alongside branch-specific ones. Previously only exact branch match was checked, hiding programs created without a branch. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Programs with branch_id=NULL are academy-wide — they should be visible regardless of which branch is selected. The filter now uses WHERE branch_id = X OR branch_id IS NULL. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
training_groups.code is NOT NULL — the auto-created default group was missing it, causing a constraint violation. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The seeder was trying to set branch_id on the user, but that column doesn't exist on the users table (it's on participants/payments). Removed the branch assignment and unused Branch import. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The academy identity is now established by the seeder (from ACADEMY_NAME_EN, ACADEMY_NAME_AR env vars). The wizard no longer has an "Academy Profile" step. It starts directly at Branches (step 1) and only configures operational data: branches, activities, programs, facilities, groups, staff, settings. This enforces one-academy-per-instance: the academy exists before the wizard runs, and no user action can create or duplicate it. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
DatabaseSeeder now uses Academy::first() — never creates duplicates. If the wizard already created an academy, the seeder respects it and just ensures the env-var admin user is super_admin on that academy. FinancialAccountsSeeder no longer has a hardcoded 'el-captain' fallback; it skips gracefully if no academy exists yet. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- UsesBranchScope falls back to withoutGlobalScopes if no branch found in current academy - Shows proper error message instead of TypeError when no branch exists - DatabaseSeeder assigns branch_id to admin user on every seed run Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- RolesAndPermissionsSeeder: seed roles for ALL academies (not just hardcoded 'el-captain' slug) - PermissionSeeder: assign permissions to all role instances per slug (across academies) - DatabaseSeeder: look for owner role in user's academy first, always set is_super_admin Root cause: wizard-created academy had different slug than seeder expected, so roles/permissions were never created for it, leaving the admin user with no permissions (403 on dashboard). Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-