# PPSA Admin UI Overhaul Plan

**Goal:** Transform the Filament admin from a generic table+form pattern into a purpose-built ops console — each section matches the shape of the data it manages. Visual system: brand green (#16a34a), white/light-grey backgrounds, Space Grotesk headings, Inter body. No dark backgrounds except counter-sales banner.

**Approach:** One section at a time, starting with Orders. Each section is self-contained — confirm before moving to the next.

---

## Design Principles

| Data type | UI pattern |
|---|---|
| Workflow with states | Kanban board or stepper |
| Hierarchy (Make→Model→Year) | Tree / master-detail panel |
| Calculation / formula | Live preview panel |
| Log / audit trail | Timeline / activity feed |
| Matrix (permissions × roles) | Toggle-able grid |
| Monitoring (sync jobs) | Real-time status cards with polling |
| Queue management | Visual queue cards matching storefront |

---

## Section 1 — Orders ✦ START HERE

### Current state
- Flat `ListOrders` table with status filter tabs
- `ViewOrder` Infolist with tabs (Details, Items, Timeline, Messages, Credits, Returns)
- Status timeline and messages already exist as data, but rendered as Filament infolist fields

### Proposed UI

**1a. List page — Kanban view (alternate to table)**

Add a `KanbanView` toggle on `ListOrders`. Two modes:
- **Table mode** (default, existing) — keep as-is for bulk operations and search
- **Kanban mode** — custom Livewire component embedded via `->header()` slot

Kanban columns (left → right):
```
Pending | Paid | Processing | Shipped | Delivered | Cancelled · Closed
```

Each card shows:
- Order # + customer name (bold)
- Total (R amount, right-aligned)
- Shipping method badge
- Age pill (e.g. "3h ago", turns amber >24h, red >48h)
- Quick action: click card → ViewOrder; drag-to-column → status update with confirmation

Column headers show count + total revenue for that status.

Cancelled/Closed share one collapsed column to keep the board uncluttered.

**Implementation:** Custom Livewire component `App\Livewire\Admin\OrderKanban`. Mounted in `ListOrders::getHeaderWidgets()`. Uses `wire:poll.10s` to refresh counts. Drag-to-drop via Alpine.js + SortableJS (CDN, no npm).

---

**1b. ViewOrder page — ops console layout**

Replace the current Infolist tab layout with a two-column console view:

```
┌─────────────────────────────────────────┬────────────────────────────┐
│  LEFT (65%)                             │  RIGHT (35%)               │
│                                         │                            │
│  Order header bar                       │  Status stepper            │
│  (customer · date · total · payment)    │  (6 steps, current green)  │
│                                         │                            │
│  ─── Items table ───                    │  ─── Quick actions ────    │
│  Part # | Description | Qty | Price     │  [Update Status ▾]         │
│  Subtotal / Shipping / VAT / Total      │  [Send Message ▾]          │
│                                         │  [Generate Invoice]        │
│  ─── Timeline feed ───                  │  [Create Credit Note]      │
│  • Created → Paid → Processing …        │  [Request Return]          │
│    (timestamps, actor, note on each)    │                            │
│                                         │  ─── Order meta ───        │
│  ─── Messaging thread ───               │  Shipping address          │
│  Chronological bubbles:                 │  Tracking / waybill        │
│  Staff (right, green) / Customer (left) │  Payment ref               │
│  [Message input + channel selector]     │  Invoice badge             │
│  [Template picker dropdown]             │                            │
└─────────────────────────────────────────┴────────────────────────────┘
```

The timeline feed and messaging thread are rendered via a Blade partial loaded into the Livewire page — **not** Filament Infolist fields. This allows proper chat-bubble styling.

Status stepper on the right uses a vertical `<ol>` with green filled circles for completed states, outlined for future, pulsing ring for current.

**Files to create/modify:**
- `app/Filament/Admin/Resources/OrderResource/Pages/ViewOrder.php` — restructure into custom view
- `resources/views/filament/orders/view-order.blade.php` — two-column layout
- `resources/views/filament/orders/partials/timeline.blade.php`
- `resources/views/filament/orders/partials/thread.blade.php`
- `resources/views/filament/orders/partials/status-stepper.blade.php`
- `app/Livewire/Admin/OrderKanban.php`
- `resources/views/livewire/admin/order-kanban.blade.php`

### Checklist
- [ ] Kanban Livewire component with 6 columns
- [ ] Card component (order #, name, total, age pill, method badge)
- [ ] Drag-to-column status update (Alpine + SortableJS)
- [ ] `wire:poll.10s` live count refresh
- [ ] Toggle button on ListOrders switching Table ↔ Kanban
- [ ] ViewOrder two-column layout Blade view
- [ ] Status stepper (vertical, 6 states)
- [ ] Timeline feed (event bubbles with actor + timestamp)
- [ ] Messaging thread (chat bubbles, staff vs customer)
- [ ] Message compose bar (text input + channel selector + template picker)
- [ ] Quick actions panel (right column)
- [ ] Order meta panel (address, tracking, payment ref, invoice badge)

---

## Section 2 — Shopping Carts

### Current state
- Flat table with status column (text label)
- Cart preview via slideOver

### Proposed UI

**Urgency-coded card grid** replacing the default table rows.

Four swim-lanes or filter tabs with distinct visual treatment:

| Status | Visual treatment |
|---|---|
| **Active** (last activity <30 min) | White card, green left border |
| **Recent** (30 min–2 h) | White card, amber left border |
| **Idle** (2–24 h) | Light grey card, grey border |
| **Abandoned** (>24 h) | Pale red card, red left border, "ABANDONED" badge |

Each card: customer name (or "Guest"), item count, cart total, time since last activity, top product thumbnail, [Recover Link] + [View] actions.

Summary bar at top: count + total value per lane.

**Files:**
- `app/Livewire/Admin/CartBoard.php`
- `resources/views/livewire/admin/cart-board.blade.php`

### Checklist
- [ ] CartBoard Livewire component with 4 urgency lanes
- [ ] Urgency classification logic (based on `updated_at`)
- [ ] Card design with left-border color coding
- [ ] Summary bar (count + value per lane)
- [ ] [Recover Link] and [View] actions on each card
- [ ] Auto-refresh every 60s (`wire:poll.60s`)

---

## Section 3 — Turn14 Dashboard

### Current state
- Static stats page with last sync times and record counts

### Proposed UI

**Live sync monitor** — each sync job type is a card with real-time status.

```
┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐
│  Fitment Sync   │  │  Pricing Sync   │  │  Inventory Sync │
│  ● Running      │  │  ✓ Success      │  │  ◌ Queued       │
│  Started 2m ago │  │  3h ago · 14.2k │  │  —              │
│  [View Log]     │  │  records        │  │  [Run Now]      │
└─────────────────┘  └─────────────────┘  └─────────────────┘
```

Status indicators: pulsing green dot (running), solid green check (success), red X (failed), grey circle (idle/queued).

Each card polls every 5s while status is `running`. Cards with errors expand to show the error message inline.

Below the cards: a mini activity feed of the last 10 sync log entries (all job types combined), replacing the current table widget.

**Files:**
- `app/Filament/Admin/Pages/Turn14Dashboard.php` — add `wire:poll`
- `resources/views/filament/pages/turn14-dashboard.blade.php` — card grid + feed

### Checklist
- [ ] Sync job status cards (one per job type)
- [ ] Real-time polling (5s while running, 30s otherwise)
- [ ] Status dot animations (pulsing for running)
- [ ] Error expansion inline on failed cards
- [ ] [Run Now] action per card
- [ ] Mini activity feed (last 10 entries, all types)
- [ ] Stats strip (total products, active brands, last full sync)

---

## Section 4 — Turn14 Settings (Pricing Formula)

### Current state
- Form fields for exchange rate, markup, duty, freight, etc.
- No preview of what the numbers mean

### Proposed UI

Split the page into two panels side-by-side:

**Left — Formula inputs** (existing fields, unchanged)

**Right — Live price preview panel**

```
Example Product: "K&N Air Filter — USD $89.99"

  USD Cost:           $89.99
  × Exchange Rate:    × 17.00  =  R 1,529.83
  + Customs Duty:     + 10%    =  R 1,682.81
  + Freight (est):    + R 48   =  R 1,730.81
  − Freight Disc:     − 50%    =  R 1,706.81
  + Disbursement:     + 4%     =  R 1,775.08
  × Markup:           × 1.70   =  R 3,017.64
  (round to R5)                =  R 3,020.00
  + VAT 15%:                   =  R 3,473.00
  ─────────────────────────────────────────
  Retail Price (incl. VAT):     R 3,473.00
```

Every row updates live as form fields change. The example USD cost is user-editable.

**Files:**
- `app/Filament/Admin/Pages/Turn14Settings.php` — wire up reactive properties
- `resources/views/filament/pages/turn14-settings.blade.php` — two-column layout with preview

### Checklist
- [ ] Two-column layout (inputs left, preview right)
- [ ] Live preview panel with step-by-step calculation
- [ ] Editable USD example cost input in preview
- [ ] Each formula step shown with operand + running total
- [ ] Final price highlighted in brand green
- [ ] Preview updates on every keystroke (Livewire `wire:model.live`)

---

## Section 5 — Vehicle Manager / Engine Manager

### Current state
- `VehicleManager` page: already has 3-level navigation (Make → Model → Year) but rendered as simple lists side by side
- `EngineManager` page: separate flat page

### Proposed UI

**True master-detail tree panel** — three persistent columns always visible:

```
┌──────────────┬──────────────┬──────────────────────────────┐
│  Makes       │  Models      │  Years / Detail              │
│  ─────────── │  ─────────── │  ───────────────────         │
│  ▸ BMW       │  3 Series    │  2018  ✓  ✓  ✓              │
│  ▸ Ford    ◀ │  5 Series  ◀ │  2019  ✓  ✓  –              │
│  ▸ Toyota    │  M3          │  2020  –  –  –              │
│              │  M5          │                              │
│  [+ Add]     │  [+ Add]     │  [+ Add Year]               │
└──────────────┴──────────────┴──────────────────────────────┘
```

Active selection highlighted in green. Clicking a make loads its models in column 2. Clicking a model loads years in column 3. Makes and models show their image thumbnail inline.

Engine Manager gets the same two-column treatment (Make → Engine variant), embedded in the same page via tabs: **Vehicles** | **Engines**.

**Files:**
- `app/Filament/Admin/Pages/VehicleManager.php` — refactor layout state
- `resources/views/filament/pages/vehicle-manager.blade.php` — 3-panel grid
- Merge EngineManager into VehicleManager as a tab

### Checklist
- [ ] 3-panel grid layout (makes | models | years)
- [ ] Make column with thumbnail + name + edit/delete inline
- [ ] Model column loads on make click
- [ ] Year column loads on model click
- [ ] Add/edit inline within each column (modal or inline form)
- [ ] Engine tab: 2-panel (make | engine variants)
- [ ] Merge EngineManager into VehicleManager under "Engines" tab

---

## Section 6 — Workshop Queue

### Current state
- `WorkshopBookingResource` — standard Filament table

### Proposed UI

**Visual queue board** matching the storefront's live queue display.

Cards arranged in a vertical queue, ordered by booking date. Each card:
- Vehicle photo (left, 80×80 thumbnail)
- Customer name + vehicle description
- Service description
- Status badge (Pending / Confirmed / In Progress / Completed / Cancelled)
- Booking date + time
- Inline status update (single click → next status, or dropdown for any status)

Staff and customers see the same queue order — the admin card matches the storefront card layout (same info hierarchy, same status badge colours).

Filter bar at top: Today | This Week | All | by Status.

**Files:**
- `app/Livewire/Admin/WorkshopQueue.php`
- `resources/views/livewire/admin/workshop-queue.blade.php`
- Replace `ListWorkshopBookings` table with this component

### Checklist
- [ ] Card layout matching storefront queue card
- [ ] Vehicle photo thumbnail
- [ ] Status badge (colour-coded, matching storefront)
- [ ] One-click status advance button
- [ ] Date/time filter bar
- [ ] Empty state per filter

---

## Section 7 — Roles & Permissions Matrix

### Current state
- `UserResource` — edit form per user with role assignment
- No visual overview of what each role can do

### Proposed UI

**Permission matrix page** — a dedicated Settings page (not a resource).

Rows = permission areas (orders.view, orders.edit, products.manage, etc.)
Columns = roles (admin, manager, staff, viewer)

Each cell = toggle (green checkbox if granted, grey if not). Changes save immediately via Livewire `wire:click`.

```
                    admin   manager   staff   viewer
─────────────────────────────────────────────────────
orders.view          ✓        ✓        ✓       ✓
orders.edit          ✓        ✓        ✓       –
orders.close         ✓        ✓        –       –
orders.delete        ✓        –        –       –
products.manage      ✓        ✓        –       –
settings.manage      ✓        –        –       –
users.manage         ✓        –        –       –
…
```

Role column headers are editable (rename role). "Add Role" button adds a new column.

**Files:**
- `app/Filament/Admin/Pages/PermissionsMatrix.php` (new Livewire page)
- `resources/views/filament/pages/permissions-matrix.blade.php`

### Checklist
- [ ] Matrix table (permission rows × role columns)
- [ ] Toggle cells (save on click)
- [ ] Role name editing in column header
- [ ] Add role column
- [ ] Section grouping for permission rows (Orders, Products, Settings, etc.)
- [ ] "Reset to defaults" action per role

---

## Section 8 — Activity Log & Sync Log

### Current state
- Both are flat Filament tables

### Proposed UI

**Timeline feed** — single vertical stream, newest at top.

Each entry is a feed card:

```
  ●  [Avatar initials]  Jane Admin  ·  2 min ago
     Updated order #12847 status: Processing → Shipped
     ┌─ before ──────────────────┐  ┌─ after ──────────────────┐
     │  status: "processing"     │  │  status: "shipped"       │
     │  tracking: —              │  │  tracking: "TCG123456"   │
     └───────────────────────────┘  └──────────────────────────┘
```

Sync Log entries show job type icon, duration, record counts, and expandable error detail.

Both logs share the same timeline component but can be filtered separately. Date range picker + actor filter + action type filter at the top.

**Files:**
- `app/Livewire/Admin/ActivityFeed.php`
- `resources/views/livewire/admin/activity-feed.blade.php`
- Mount in `AdminActivityLogResource` and `SyncLogResource` list pages

### Checklist
- [ ] Timeline feed component (newest first)
- [ ] Avatar initials badge per actor
- [ ] Before/after diff panel for change events
- [ ] Expandable error detail for sync failures
- [ ] Date range filter
- [ ] Actor filter (dropdown)
- [ ] Action type filter
- [ ] Infinite scroll / load more (replace pagination)

---

## Section 9 — Notification Log

### Current state
- Flat table (keep as table — correct pattern for a log)

### Proposed UI

**Enhanced table** — keep the table but add:

- Channel icons (envelope / phone / whatsapp / bell) in the Channel column, not just text
- Status column: coloured badge pills
  - Sent → green
  - Queued → amber
  - Failed → red with expandable error tooltip
  - Bounced → orange
- Recipient column: show avatar initials + name + email on hover
- Subject column: truncated with tooltip on hover
- Quick filter chips above table: All | Email | SMS | WhatsApp | Push | Failed

**Files:**
- `app/Filament/Admin/Resources/NotificationLogResource.php` — enhance table columns

### Checklist
- [ ] Channel icon column (SVG icons per channel)
- [ ] Status badge with colour coding
- [ ] Failed row: inline error tooltip / expandable row detail
- [ ] Quick filter chips (channel + status)
- [ ] Recipient display with initials badge

---

## Section 10 — Dashboard Widgets

### Current state (per agent survey — all 5 already implemented)
- `OrderStatsWidget` — stat cards
- `StockAlertStatsWidget` — stat cards
- `RevenueChartWidget` — 30-day Chart.js line
- `RecentOrdersWidget` — table
- `TopProductsWidget` — table

### Proposed enhancements

These are already the benchmark, but apply the following polish:
- Revenue chart: add a secondary axis for order count (dual-axis) if not already dual-axis
- RecentOrders: add the age pill and urgency colour coding (same as Kanban cards)
- TopProducts: add a small sparkline bar (7-day trend) per product row
- Stat cards: add delta vs previous period (e.g. "+12% vs last week") as a subtle sub-label

**Files:**
- `app/Filament/Admin/Widgets/RevenueChartWidget.php`
- `app/Filament/Admin/Widgets/RecentOrdersWidget.php`
- `app/Filament/Admin/Widgets/TopProductsWidget.php`
- `app/Filament/Admin/Widgets/OrderStatsWidget.php`

### Checklist
- [ ] Revenue chart: confirm dual-axis (revenue + order count); add if missing
- [ ] Stat cards: delta vs previous period
- [ ] RecentOrders: age pill + urgency colour
- [ ] TopProducts: 7-day sparkline bar

---

## Implementation Order

| # | Section | Complexity | Est. files |
|---|---|---|---|
| 1 | **Orders** (Kanban + detail) | High | ~8 |
| 2 | Shopping Carts (urgency board) | Medium | ~3 |
| 3 | Turn14 Dashboard (live monitor) | Medium | ~2 |
| 4 | Turn14 Settings (price preview) | Medium | ~2 |
| 5 | Vehicle + Engine Manager (tree) | Medium | ~3 |
| 6 | Workshop Queue (card board) | Medium | ~3 |
| 7 | Roles & Permissions Matrix | High | ~2 |
| 8 | Activity + Sync Log (timeline) | Medium | ~3 |
| 9 | Notification Log (table polish) | Low | ~1 |
| 10 | Dashboard widgets (polish) | Low | ~4 |

**Start with Section 1 (Orders) and confirm before proceeding.**
