# UI Architecture — Livewire 3 + Alpine.js + Tailwind CSS

---

## Stack

| Layer | Technology | Role |
|-------|-----------|------|
| Server Components | Livewire 3 | Full-page components, forms, tables, modals |
| Client Interactivity | Alpine.js 3 | Tabs, dropdowns, toggles, real-time UI state |
| Styling | Tailwind CSS 3 | Utility-first, RTL-ready |
| Build | Vite | Asset bundling, HMR in dev |
| Icons | Heroicons (blade-heroicons) | Consistent iconography |
| Charts | Chart.js via Alpine | Dashboard visualizations |
| PDF | DomPDF | Server-side document generation |
| Tables | Custom Livewire component | Sortable, filterable, paginated |

---

## Directory Structure

```
resources/
├── views/
│   ├── layouts/
│   │   ├── app.blade.php              ← Main authenticated layout (sidebar + topbar)
│   │   ├── guest.blade.php            ← Login/register layout
│   │   └── print.blade.php            ← Minimal layout for printable pages
│   │
│   ├── components/
│   │   ├── layouts/
│   │   │   ├── sidebar.blade.php
│   │   │   ├── topbar.blade.php
│   │   │   └── mobile-nav.blade.php
│   │   │
│   │   ├── ui/
│   │   │   ├── button.blade.php
│   │   │   ├── input.blade.php
│   │   │   ├── select.blade.php
│   │   │   ├── textarea.blade.php
│   │   │   ├── checkbox.blade.php
│   │   │   ├── radio.blade.php
│   │   │   ├── toggle.blade.php
│   │   │   ├── badge.blade.php
│   │   │   ├── alert.blade.php
│   │   │   ├── card.blade.php
│   │   │   ├── modal.blade.php
│   │   │   ├── dropdown.blade.php
│   │   │   ├── table.blade.php
│   │   │   ├── pagination.blade.php
│   │   │   ├── tabs.blade.php
│   │   │   ├── stat-card.blade.php
│   │   │   ├── avatar.blade.php
│   │   │   ├── empty-state.blade.php
│   │   │   └── loading-spinner.blade.php
│   │   │
│   │   ├── forms/
│   │   │   ├── field-group.blade.php   ← Label + input + error wrapper
│   │   │   ├── date-picker.blade.php
│   │   │   ├── file-upload.blade.php
│   │   │   ├── rich-text.blade.php
│   │   │   └── search-select.blade.php ← Searchable dropdown (wire:model)
│   │   │
│   │   └── data/
│   │       ├── data-table.blade.php    ← Full table with sort/filter/pagination
│   │       ├── filter-bar.blade.php
│   │       └── bulk-actions.blade.php
│   │
│   ├── livewire/
│   │   ├── auth/
│   │   │   ├── login.blade.php
│   │   │   └── forgot-password.blade.php
│   │   │
│   │   ├── dashboard/
│   │   │   ├── admin-dashboard.blade.php
│   │   │   ├── trainer-dashboard.blade.php
│   │   │   └── parent-dashboard.blade.php
│   │   │
│   │   ├── participants/
│   │   │   ├── participant-list.blade.php
│   │   │   ├── participant-create.blade.php
│   │   │   ├── participant-show.blade.php
│   │   │   └── participant-edit.blade.php
│   │   │
│   │   ├── programs/
│   │   │   ├── program-list.blade.php
│   │   │   ├── program-create.blade.php
│   │   │   ├── program-show.blade.php
│   │   │   └── group-manage.blade.php
│   │   │
│   │   ├── scheduling/
│   │   │   ├── calendar-view.blade.php
│   │   │   ├── session-list.blade.php
│   │   │   └── space-booking.blade.php
│   │   │
│   │   ├── attendance/
│   │   │   ├── take-attendance.blade.php
│   │   │   ├── attendance-report.blade.php
│   │   │   └── excuse-manage.blade.php
│   │   │
│   │   ├── financial/
│   │   │   ├── invoice-list.blade.php
│   │   │   ├── invoice-create.blade.php
│   │   │   ├── invoice-show.blade.php
│   │   │   ├── payment-record.blade.php
│   │   │   ├── wallet-manage.blade.php
│   │   │   ├── cash-session.blade.php
│   │   │   └── daily-closing.blade.php
│   │   │
│   │   ├── inventory/
│   │   │   ├── product-list.blade.php
│   │   │   ├── product-manage.blade.php
│   │   │   ├── stock-count.blade.php
│   │   │   └── purchase-order.blade.php
│   │   │
│   │   ├── pos/
│   │   │   └── pos-terminal.blade.php  ← Full-screen POS interface
│   │   │
│   │   ├── staff/
│   │   │   ├── employee-list.blade.php
│   │   │   ├── trainer-list.blade.php
│   │   │   └── assignment-manage.blade.php
│   │   │
│   │   ├── facilities/
│   │   │   ├── facility-list.blade.php
│   │   │   ├── facility-manage.blade.php
│   │   │   └── space-layout-editor.blade.php
│   │   │
│   │   ├── settings/
│   │   │   ├── academy-settings.blade.php
│   │   │   ├── roles-permissions.blade.php
│   │   │   ├── pricing-rules.blade.php
│   │   │   ├── template-editor.blade.php
│   │   │   └── notification-settings.blade.php
│   │   │
│   │   └── super-admin/
│   │       ├── academy-list.blade.php
│   │       ├── academy-manage.blade.php
│   │       ├── platform-settings.blade.php
│   │       └── system-health.blade.php
│   │
│   └── pdf/
│       ├── invoice.blade.php
│       ├── receipt.blade.php
│       ├── certificate.blade.php
│       └── report.blade.php
│
├── css/
│   └── app.css                         ← Tailwind directives + custom utilities
│
└── js/
    └── app.js                          ← Alpine plugins + Chart.js setup
```

---

## RTL (Arabic-First) Strategy

### Tailwind RTL Configuration

```css
/* app.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
    html {
        direction: rtl;
        font-family: 'Cairo', 'Noto Sans Arabic', sans-serif;
    }
    
    [dir="ltr"] {
        font-family: 'Inter', sans-serif;
    }
}
```

### Logical Properties Over Physical

| Instead of | Use |
|-----------|-----|
| `ml-4` | `ms-4` (margin-start) |
| `mr-4` | `me-4` (margin-end) |
| `pl-4` | `ps-4` (padding-start) |
| `pr-4` | `pe-4` (padding-end) |
| `text-left` | `text-start` |
| `text-right` | `text-end` |
| `left-0` | `start-0` |
| `right-0` | `end-0` |
| `border-l` | `border-s` |
| `border-r` | `border-e` |
| `rounded-l` | `rounded-s` |
| `rounded-r` | `rounded-e` |

### Language Switcher

- Default: Arabic (ar) with RTL
- Toggle: adds `dir="ltr"` to `<html>` + switches font + stores preference in session
- All user-facing strings wrapped in `__()` for translation
- Database stores both `name` and `name_ar` — display logic: `app()->getLocale() === 'ar' ? $model->name_ar : $model->name`

---

## Layout System

### Main Authenticated Layout (`app.blade.php`)

```
┌─────────────────────────────────────────────────────────┐
│ Topbar: Academy name | Search | Notifications | Profile │
├──────────┬──────────────────────────────────────────────┤
│          │                                              │
│ Sidebar  │              Main Content                    │
│ (240px)  │              (fluid)                         │
│          │                                              │
│ - Logo   │  ┌─────────────────────────────────────────┐ │
│ - Nav    │  │  Page Header (title + actions)          │ │
│ - Groups │  ├─────────────────────────────────────────┤ │
│          │  │  Page Content                           │ │
│          │  │  (Livewire component renders here)      │ │
│          │  │                                         │ │
│          │  └─────────────────────────────────────────┘ │
│          │                                              │
├──────────┴──────────────────────────────────────────────┤
│ Footer (optional): Version | Support                    │
└─────────────────────────────────────────────────────────┘
```

### Sidebar Navigation Groups

```
📊 لوحة التحكم (Dashboard)
👥 المشتركين (Participants)
🏋️ البرامج (Programs)
📅 الجدول (Schedule)
✅ الحضور (Attendance)
💰 المالية (Financial)
📦 المخزون (Inventory)
🏢 المنشآت (Facilities)
👔 الموظفين (Staff)
⚙️ الإعدادات (Settings)
🛡️ إدارة النظام (Super Admin) ← only for super_admin role
```

### Responsive Behavior

| Breakpoint | Sidebar | Topbar | Content |
|-----------|---------|--------|---------|
| Desktop (≥1024px) | Fixed, always visible | Full | Fluid |
| Tablet (768-1023px) | Collapsible (icon-only by default) | Full | Fluid |
| Mobile (<768px) | Hidden (slide-in overlay) | Hamburger + logo only | Full-width |

---

## Color System

### Brand Colors (El Captain)

```css
:root {
    /* Primary — deep navy/blue (authority, trust, sports) */
    --color-primary-50: #eff6ff;
    --color-primary-100: #dbeafe;
    --color-primary-200: #bfdbfe;
    --color-primary-300: #93c5fd;
    --color-primary-400: #60a5fa;
    --color-primary-500: #3b82f6;
    --color-primary-600: #2563eb;
    --color-primary-700: #1d4ed8;
    --color-primary-800: #1e40af;
    --color-primary-900: #1e3a8a;
    
    /* Accent — gold/amber (achievement, premium) */
    --color-accent-400: #fbbf24;
    --color-accent-500: #f59e0b;
    --color-accent-600: #d97706;
    
    /* Semantic */
    --color-success: #10b981;
    --color-warning: #f59e0b;
    --color-danger: #ef4444;
    --color-info: #3b82f6;
}
```

### Dark/Light Mode

- Default: Light mode
- Dark mode: system preference detection + manual toggle
- Implementation: Tailwind `dark:` variants, stored in localStorage

---

## Component Patterns

### Data Table (Livewire)

Every list view follows this pattern:

```php
// Livewire Component: ParticipantList
class ParticipantList extends Component
{
    use WithPagination;

    public string $search = '';
    public string $status = '';
    public string $sortBy = 'name_ar';
    public string $sortDir = 'asc';
    public int $perPage = 25;
    public array $selected = [];
    public bool $selectAll = false;

    protected $queryString = [
        'search' => ['except' => ''],
        'status' => ['except' => ''],
        'sortBy' => ['except' => 'name_ar'],
        'sortDir' => ['except' => 'asc'],
    ];

    public function render()
    {
        $participants = Participant::query()
            ->when($this->search, fn ($q) => $q->search($this->search))
            ->when($this->status, fn ($q) => $q->where('status', $this->status))
            ->orderBy($this->sortBy, $this->sortDir)
            ->paginate($this->perPage);

        return view('livewire.participants.participant-list', compact('participants'));
    }
}
```

### Form Pattern (Livewire)

```php
class ParticipantCreate extends Component
{
    public string $name = '';
    public string $name_ar = '';
    public string $phone = '';
    public string $national_id = '';
    // ... all form fields as public properties

    protected function rules(): array
    {
        return [
            'name' => 'required|string|max:255',
            'name_ar' => 'required|string|max:255',
            'phone' => 'required|string|max:20',
            'national_id' => 'nullable|string|size:14',
        ];
    }

    public function save()
    {
        $this->validate();
        
        // Dispatch to service
        $participant = app(ParticipantService::class)->create($this->all());
        
        session()->flash('success', __('تم إضافة المشترك بنجاح'));
        return redirect()->route('participants.show', $participant);
    }
}
```

### Modal Pattern (Alpine + Livewire)

```html
<!-- Parent page has ONE x-data scope -->
<div x-data="{ showDeleteModal: false, deleteTarget: null }">
    
    <!-- Trigger -->
    <button @click="showDeleteModal = true; deleteTarget = {{ $participant->id }}">
        حذف
    </button>
    
    <!-- Modal component receives state from parent -->
    <x-ui.modal x-show="showDeleteModal" @close="showDeleteModal = false">
        <p>هل أنت متأكد من حذف هذا المشترك؟</p>
        <button wire:click="delete(deleteTarget)" @click="showDeleteModal = false">
            تأكيد
        </button>
    </x-ui.modal>
</div>
```

### Tab Pattern (Alpine)

```html
<div x-data="{ activeTab: 'info' }">
    <div class="border-b border-gray-200" role="tablist">
        <button role="tab" :aria-selected="activeTab === 'info'"
            :class="activeTab === 'info' ? 'border-primary-500 text-primary-600' : 'border-transparent'"
            @click="activeTab = 'info'">
            المعلومات الأساسية
        </button>
        <button role="tab" :aria-selected="activeTab === 'financial'"
            :class="activeTab === 'financial' ? 'border-primary-500 text-primary-600' : 'border-transparent'"
            @click="activeTab = 'financial'">
            المالية
        </button>
        <button role="tab" :aria-selected="activeTab === 'attendance'"
            :class="activeTab === 'attendance' ? 'border-primary-500 text-primary-600' : 'border-transparent'"
            @click="activeTab = 'attendance'">
            الحضور
        </button>
    </div>

    <div x-show="activeTab === 'info'" role="tabpanel">
        @livewire('participants.info-tab', ['participant' => $participant])
    </div>
    <div x-show="activeTab === 'financial'" role="tabpanel">
        @livewire('participants.financial-tab', ['participant' => $participant])
    </div>
    <div x-show="activeTab === 'attendance'" role="tabpanel">
        @livewire('participants.attendance-tab', ['participant' => $participant])
    </div>
</div>
```

---

## Key UI Screens

### 1. POS Terminal (Full-Screen)

```
┌─────────────────────────────────────────────────────────────┐
│  🔍 بحث عن مشترك...          │  الكاشير: محمد  │  🔴 إغلاق │
├────────────────────────────────┼────────────────────────────┤
│                                │                            │
│  المنتجات / الخدمات           │  سلة المشتريات             │
│                                │                            │
│  [اشتراكات] [منتجات] [أطقم]  │  ┌────────────────────┐    │
│                                │  │ كرة قدم × 1   150ج │    │
│  ┌──────┐ ┌──────┐ ┌──────┐  │  │ اشتراك شهري  800ج │    │
│  │ كرة  │ │ حذاء │ │ شورت │  │  │ خصم عائلي   -80ج │    │
│  │ 150ج │ │ 450ج │ │ 200ج │  │  └────────────────────┘    │
│  └──────┘ └──────┘ └──────┘  │                            │
│  ┌──────┐ ┌──────┐ ┌──────┐  │  المجموع:        870 ج.م   │
│  │ طقم  │ │ شنطة │ │ واقي │  │  ────────────────────────  │
│  │ 700ج │ │ 300ج │ │  80ج │  │                            │
│  └──────┘ └──────┘ └──────┘  │  [نقدي] [بطاقة] [محفظة]   │
│                                │                            │
│                                │  [ ✅ إتمام البيع ]        │
├────────────────────────────────┴────────────────────────────┤
│  المشترك: أحمد محمد │ الرصيد: 200ج │ برنامج: كرة قدم (نشط) │
└─────────────────────────────────────────────────────────────┘
```

### 2. Attendance Taking (Trainer View)

```
┌─────────────────────────────────────────────────────────────┐
│  ← رجوع  │  حضور: مجموعة كرة القدم - الأحد 29/6  │  5:00م  │
├─────────────────────────────────────────────────────────────┤
│  [✅ تحضير الكل] [❌ غياب الكل]  │  12/15 حاضر            │
├─────────────────────────────────────────────────────────────┤
│  الاسم                │ الحالة         │ ملاحظات            │
│  ─────────────────────────────────────────────────────────  │
│  أحمد محمد علي       │ [✅ حاضر    ] │                    │
│  محمد إبراهيم سيد    │ [✅ حاضر    ] │                    │
│  يوسف أحمد حسن      │ [⏰ متأخر   ] │ وصل 5:20م          │
│  عمر خالد محمود      │ [❌ غائب    ] │                    │
│  حسين علي أحمد      │ [📋 معذور   ] │ مرضي - مرفق شهادة  │
│  ─────────────────────────────────────────────────────────  │
│                                                             │
├─────────────────────────────────────────────────────────────┤
│  [ 💾 حفظ الحضور ]                                         │
└─────────────────────────────────────────────────────────────┘
```

### 3. Space Booking (Visual Grid)

```
┌─────────────────────────────────────────────────────────────┐
│  ← رجوع  │  حجز ملعب: الملعب الرئيسي  │  الأحد 29/6 5-7م  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  التخطيط: شبكة 3×2                                         │
│                                                             │
│  ┌─────────────┬─────────────┬─────────────┐               │
│  │   🟢 R1C1  │   🔴 R1C2  │   🟢 R1C3  │               │
│  │  (متاح)    │  (محجوز)    │  (متاح)    │               │
│  │             │  مجموعة أ   │             │               │
│  ├─────────────┼─────────────┼─────────────┤               │
│  │   🟢 R2C1  │   🟢 R2C2  │   🟡 R2C3  │               │
│  │  (متاح)    │  (متاح)    │  (صيانة)   │               │
│  │             │             │             │               │
│  └─────────────┴─────────────┴─────────────┘               │
│                                                             │
│  المحدد: R1C1, R2C1, R2C2 (3 أقسام)                       │
│  السعة الإجمالية: 45 لاعب                                  │
│                                                             │
│  [ ✅ تأكيد الحجز ]  [ ↩️ إلغاء ]                          │
└─────────────────────────────────────────────────────────────┘
```

### 4. Participant Profile (Tabbed View)

```
┌─────────────────────────────────────────────────────────────┐
│  ← قائمة المشتركين                                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  [👤]  أحمد محمد علي                                       │
│        12 سنة │ ذكر │ نشط                                  │
│        رقم قومي: 31201154XXXXX                              │
│                                                             │
│  ┌──────────────────────────────────────────────────────┐   │
│  │ [المعلومات] [المالية] [الحضور] [البرامج] [التقييمات]│   │
│  └──────────────────────────────────────────────────────┘   │
│                                                             │
│  ═══ المالية ════════════════════════════════════════════   │
│                                                             │
│  الرصيد المستحق: 1,200 ج.م                                │
│  المحفظة: 350 ج.م                                          │
│                                                             │
│  آخر الفواتير:                                             │
│  ┌──────────────────────────────────────────────────────┐   │
│  │ #INV-2026-0142 │ 800 ج.م │ مدفوعة جزئياً │ 15/6  │   │
│  │ #INV-2026-0098 │ 400 ج.م │ مدفوعة        │ 01/6  │   │
│  └──────────────────────────────────────────────────────┘   │
│                                                             │
│  [ + تسجيل دفعة ]  [ + إنشاء فاتورة ]                     │
└─────────────────────────────────────────────────────────────┘
```

---

## SuperAdmin Panel

Separate route group: `/super-admin/*`
Middleware: `EnsureSuperAdmin` (checks user.role === 'super_admin', bypasses academy scope)

### SuperAdmin Screens

| Screen | Purpose |
|--------|---------|
| Academy List | All academies with status, plan, created date |
| Academy Create/Edit | Name, slug, contact, plan, features toggle |
| Academy Impersonate | "Login as" any academy admin |
| Platform Settings | Global config (default language, email from, maintenance mode) |
| Template Management | Manage default invoice/receipt/certificate templates |
| System Health | Queue jobs, failed jobs, database size, container stats |
| Activity Log | Cross-tenant audit trail (login, changes, errors) |
| User Management | All users across academies (for support) |

### Multi-Tenancy in UI

- Academy admin sees ONLY their data (global scope enforced)
- SuperAdmin can switch context: "Viewing as: [Academy Dropdown]"
- When impersonating: yellow banner "أنت تعمل كـ [Academy Name] — [العودة لإدارة النظام]"
- Some settings are "platform-level" (only SuperAdmin), others are "academy-level" (each academy manages their own)

---

## Performance Patterns

### Livewire Optimization

1. **Lazy Loading**: Heavy components use `wire:init` to load data after page paint
2. **Polling**: Dashboard widgets poll every 30s (`wire:poll.30s`)
3. **Debounce**: Search inputs use `wire:model.live.debounce.300ms`
4. **Pagination**: Server-side pagination for all lists (never load all records)
5. **Computed Properties**: Use `#[Computed]` attribute for cacheable derived data
6. **Wire:navigate**: SPA-like navigation without full page reloads (Livewire 3 feature)

### Asset Loading

1. Vite code splitting: separate chunks for POS, charts, admin
2. Font loading: `font-display: swap` with preload for Arabic font
3. Image optimization: WebP with fallback, lazy loading for avatars
4. Critical CSS: inline above-fold styles

---

## Accessibility

- All interactive elements have proper ARIA roles and labels
- Keyboard navigation: Tab order follows visual RTL flow
- Color contrast: WCAG AA minimum (4.5:1 for text)
- Focus indicators: visible focus ring on all interactive elements
- Screen reader: Arabic aria-labels on all icon-only buttons
- Form errors: announced via `aria-live="polite"` regions

---

## Error Handling (UI)

| Scenario | Behavior |
|----------|----------|
| Validation error | Inline red text below field + top-of-form alert |
| Server error (500) | Toast notification with "حدث خطأ — حاول مرة أخرى" |
| Network error | Livewire reconnect banner (built-in) |
| 404 page | Custom Arabic 404 with nav back to dashboard |
| 403 (unauthorized) | Flash message + redirect to dashboard |
| Session expired | Livewire auto-redirects to login |
| Optimistic UI | Disable submit button during wire:loading |

---

## Notifications UI

### Toast Notifications (Livewire Events)

```
┌──────────────────────────────────┐
│ ✅ تم حفظ البيانات بنجاح        │  ← slides in from top-end
│                              ✕  │
└──────────────────────────────────┘
```

- Success: green left border
- Error: red left border  
- Warning: yellow left border
- Info: blue left border
- Auto-dismiss after 5s (configurable)
- Stack up to 3 visible

### Real-Time Notifications (Bell Icon)

- Dropdown panel on bell click
- Unread count badge
- Grouped by type (financial, attendance, system)
- Mark as read / mark all read
- Link to relevant page

---

## Print Styles

For printable pages (invoices, reports, certificates):
- Separate `print.blade.php` layout (no sidebar, no nav)
- `@media print` styles hide interactive elements
- A4 page sizing with proper margins
- Arabic font embedded for PDF generation
- Print button triggers `window.print()` or generates PDF via DomPDF
