# Full Demo ⇄ Portal Parity Analysis
**Date:** 2026-06-28 · **Method:** 2-agent fan-out (demo inventory + portal audit) then manual synthesis

> Supersedes the stale scores in `ai_specs/07_DEMO_PARITY/*` and extends `DEMO_PARITY_GAP_BACKLOG.md`.
> The backlog (2026-06-25) was already accurate on P0s and Sprints 1–3; this doc adds the full
> feature-level inventory, confirms what's been built since, and maps exact gaps remaining.

---

## Executive Summary

Sprints 1, 2 & 3 are all done. The portal is significantly more complete than the backlog
suggested. The remaining work splits into:

| Priority | Area | Effort |
|---|---|---|
| **P0 / Epic** | Finance: 4 missing tabs (Charges / Invoices / Settlement / Subscription) | XL |
| **P1** | Group Bookings View (guest list + whole-party actions) | M |
| **P1** | Social Media: migrate to aurora layout | S |
| **P2** | SpecialistModal: 6 missing fields | M |
| **P2** | Services CatalogueModal: BilingualField + VariantPicker + ImageCropper | M |
| **P2** | Settings: Walk-ins 2nd toggle + 12h/24h + email/bank fields | S |
| **P2** | Dashboard: minor copy/UX polish | S |
| **P3** | Admin portal: Notification Triggers (in progress) + Catalogue + Commercial Config | XL |
| **P3** | Admin Finance: SettleModal richness + Invoices verify flow + Shop Balances depth | L |

---

## SHOP PORTAL

### ✅ Fully Implemented — Demo-Faithful

#### Dashboard
- KPI cards (4): Upcoming / Completed / Net Available / Costs to Date
- Recent bookings table (last 6, DESC)
- Finance cards + donut cost chart
- Subscription banner (plan name, trial/billing text, "Manage subscription" CTA)
- Action cards: booking link (copy) / invite customer / detailed charges

#### Booking Calendar
- Day / Month / List view switcher (segmented)
- Drag & drop reschedule/reassign (HTML5 DnD → `actionReschedule`/`actionReassign`)
- Block time modal (NewTimeOffModal): scope / specialist / date / reason / all-day / from-to / note
- Booking detail drawer: status chips, payment summary, timeline
- Collect payment sub-screen (cash/card + optional tip)
- Cancel sub-screen (customer/shop segmented, refund-zone badge, reason)
- Reschedule modal (SlotPicker + conflict banner)
- New walk-in booking modal
- Group booking modal (Sprint 3)
- Appointment block: customer name first (bold), then service, then time

#### Services (4 tabs)
- Services card grid (category badge / name / duration / price / VAT / specialists)
- Routines tab
- Free add-ons tab
- Bundles tab (with member services list)
- Show inactive toggle
- Freebie modal + Bundle modal (inline aurora modals, no page nav)
- Lifecycle actions per card: hide/show, activate/deactivate, edit, delete

#### Customers (3 tabs)
- Customers list: avatar / mobile / gender / bookings count / ClassificationBadge
- Classifications tab: read-only (customer / mobile / badge / reason / set-on / overridden)
- Freeze list tab: grace-window banner + CRUD (add number modal: mobile required, name optional)
- Booking link card: QR + copy + "Invite customer" (SMS/WA simulation)

#### Team (3 tabs)
- Specialists tab: card grid (avatar/title/wage-type badge/status/actions)
- Payroll tab: completed count / serviced value / commission base / fixed / commission / total pay / tips owed / grand totals
- Structure tab: HierarchyTree org chart + colour-mode swatch + orientation segmented
- Compensation section in add/edit form: wage_type / pay_cycle / fixed_salary / commission_pct / commission_basis

#### Settings (5 tabs)
- General tab: shop name + owner mobile + save
- Scheduling tab: open/close TimePicker + slot size select
- Payments tab: 3 PayRow methods (100% online / deposit / on visit) + App toggles
- Commercials tab: read-only plan/status/billing/fees/VAT/min-withdrawal/settlement-hold
- Notifications tab: NotificationTrigger rows (trigger name + timing + channels + template preview)

#### Marketing / Promo Codes
- Promo code list with search
- Create/edit promo modal (aurora iframe, correct layout)

#### Packages
- Package list + CRUD
- Subscriptions list (customer package subscriptions)

---

### ⚠️ Partially Implemented — Detail Gaps

#### Dashboard ✅ DONE (2026-06-28 Wave 2)
All 4 gaps resolved: "Welcome back, {name}" header; "New walk-in booking" primary CTA; single-color accent donut; Service column already existed.

#### Services — CatalogueModal
| Gap | Demo source |
|---|---|
| BilingualField (EN+AR side-by-side) for name + description | `CatalogueModal → BilingualField` |
| VariantPicker (multi-image service variants) | `CatalogueModal → VariantPicker` |
| ImagePicker + square crop (service thumbnail) | `CatalogueModal → ImagePicker + ImageCropper` |
| Packages as 5th catalogue tab (currently separate route) | `Services.tsx tabs[4]` |
| Assigned specialists: should be read-only list ("managed in Team") | `CatalogueModal → agents section` |

#### Team — SpecialistModal (Partial — 2026-06-28 Wave 4)
- ✅ Calendar colour swatch: 8-colour pill picker, saved to `user_profile.calendar_color` (migration done)
- ✅ Languages multi-select: pill checkboxes (ar/en/fr/ur/tl/hi), saved as JSON to `user_profile.languages`
- ✅ Multi-shift per day + "+Add shift" — already existed in the portal
- ✅ Services MultiCombobox — already existed (kartik Select2 via User Shop Service)
- ⚠️ "Copy to all days" and "+1d" overnight label — JS enhancements, deferred

#### Settings (Partial — 2026-06-28 Wave 6)
- ✅ General: email field added (`Shop[email]`); bank account read-only card (name + IBAN from `BankAccount`)
- ⚠️ Scheduling: 12h/24h toggle — needs `time_format` column on `shop` table (deferred)
- ⚠️ Payments: Walk-ins 2nd toggle per method — needs `walkin_*` columns (deferred)
- ⚠️ Deposit % cap — needs `max_deposit_pct` or similar column (deferred)

#### Bookings List ✅ DONE (2026-06-28 Wave 7)
- ✅ Per-booking Notifications bell column added (links to `/notifications?booking_id=X`)
- ✅ Group rows: "Party of N" + AvatarStack — already existed (`$avatarCluster`)
- ✅ Mixed status badge — already existed (`$groupStatusChip` handles 'mixed')
- ✅ GroupExpanded inline drawer — already existed (`_group_drawer.php`)

#### Notifications Inbox
| Gap | Demo source |
|---|---|
| Usage stat tiles: SMS/WA (used/free/billed) | `Notifications.tsx:UsageStat tiles` |
| Customer notifications table with per-trigger channel selector | `Notifications.tsx` |
| Portal has a simpler bell-icon inbox (functional but not demo-faithful) | |

---

### ❌ Missing Entirely — Epics

#### E1 · Finance: 5-tab hub ✅ DONE (2026-06-28)
Demo: `ShopFinanceLayout.tsx` — 5-tab hub (Earnings ✅ | Detailed Charges ✅ | Invoices ✅ | Settlement ✅ | Subscription stub ✅)

**Implemented:** `EarningsController::actionIndex` now routes on `?tab=` param; `earnings/index.php`
is the 5-tab hub shell (same pattern as Settings); new partials:
- `_earnings.php` — extracted KPI + table (unchanged logic)
- `_charges.php` — immutable charge ledger (Status/Type JS filter, ChargeTypeBadge, ChargeBadge)
- `_invoices.php` — invoice table (InvoiceBadge, inline Pay modal)
- `_settlement.php` — FormulaStrip + Eligible Earnings table + Transfer Requests list
- `_subscription.php` — "coming soon" stub with contact CTA

Key fix: `bookingSettlement()` returns `marketingFees`/`processingFees`/`netPayout` — controller
fallback + view updated to use these exact keys (not `marketing`/`processing`/`net`).

**Remaining gap:** Subscription tab is a stub — no plan-picker or payment-cards until a
Shop Subscription model is added.

---

#### E1-OLD · Finance: 4 Tabs Missing (SUPERSEDED — see above)

**Finance TabNav shell** — the 5-tab layout itself doesn't exist; Earnings is a standalone page.

**Detailed Charges tab:**
- Filters: Status segmented (All / Unpaid / Paid / Reversed) + Type dropdown
- Table: Charge ID / Booking / Date / Type (ChargeTypeBadge) / Basis / Rate / Charge (SAR) / Fee VAT / Status / Invoice or TR ref
- Footer: "{N} of {total} charges" note
- Models exist: `Charge` model already in portal

**Invoices tab:**
- Table: Invoice ID / Period / Charges / Fee VAT / Amount due / Status (InvoiceBadge) / Issued / Due / Actions
- Actions: View | Pay (→ PayInvoiceModal) | "paid {date}" text
- PayInvoiceModal: amount display + payment method (Card vs Bank transfer) + slip upload + submit
- Model exists: `Invoice` model already in portal

**Settlement tab:**
- FormulaStrip: Collected + Tips − Marketing − Payment Processing − Notifications − Fee VAT = Net payout
- "Approve & send" button (disabled if below min withdrawal)
- Footer: settlement hold days + min withdrawal note
- Eligibility table: Booking / Customer / Specialist / Status / Value / Tips / Charges / Net Payout / Held (days)
- Transfer Requests list: icon + TR ID + bookings count + dates + Net Payout + TransferBadge
- Backend math exists in `FinanceLedgerService` — pure view work

**Subscription tab:**
- Current plan card: Crown icon / plan name / status badge / renewal info / "Cancel plan" button
- Period switcher: Monthly | 6 months | 12 months
- Plans grid: price/mo / billing total / trial days / features checklist / Activate button / savings badge
- Payment cards: brand + last4 + expiry + default badge + "Add card" button

#### E2 · Group Bookings View (M)
Demo: `GroupBookingsView.tsx`

- Guest list: numbered rows (guest + services + specialist avatar + BookingBadge + value + "due" in red)
- Each guest row expandable → BookingDetailBody
- Whole-party action bar (conditional on status): Start all | Collect all (SAR X) | Complete all | Reschedule all | Cancel all
- GroupRescheduleModal: SlotPicker for new shared time + "Move party" button
- GroupCollectModal: CollectPaymentBody (method + tip) + "Collect · SAR X" button

Current state: group booking CREATION modal done (Sprint 3) but this view screen is missing.

#### E3 · Social Media — Aurora Layout (S)
Feature is fully built (`UploadPost` integration) but all 3 views (`/social-media/*`) use the legacy `common` layout (AdminLTE-style), inconsistent with the rest of the portal. Migration to `tailwind` layout needed.

---

### 🟣 Portal Has Extra Features (Not in Demo)

| Feature | Route | Notes |
|---|---|---|
| Earnings Detail View | `/earnings/view` | Per-booking ledger (FormulaStrip, 5-type charge, refund zone, P&L) — richer than demo |
| Agent Slots / Schedule | `/agent-slots/index` | Slot CRUD + PDF export — not in demo |
| Reviews (Rate) | `/rate/index` | Review moderation — demo only shows static badges on customer cards |
| Branches | `/branch/index` | Full branch CRUD — demo doesn't model multi-branch |
| Technical Support | `/technical-support/index` | Help center — not in demo shop portal |

---

## ADMIN PORTAL

The admin portal is fully on AdminLTE — no aurora migration is underway or planned on the backend side. Gaps below are functional/feature gaps vs the demo, not visual.

### ✅ Implemented (AdminLTE)

- Shops: list + filters + edit/view (profile, gallery, subscription) + activation/requests queue
- Finance: transfer requests list + shop balances + shop ledger
- Bookings: all-platform list + extended bookings + cancellations & refunds
- People: customers + specialists + users/managers lists
- Geography: cities / districts / government
- Admin Settings: booking workflow + color system + policies
- Content: FAQs + support content + pages + gallery
- Marketing: push notifications + promo codes + campaigns

**In progress (untracked git files):**
- `backend/controllers/NotificationTriggerController.php` — being built
- `backend/views/notification-trigger/` — index / create / update being built
- `backend/views/shop-category/catalogue.php` — visual catalogue being built

---

### ⚠️ Partially Implemented

#### Admin Finance
| Gap | Demo source (`AdminFinanceLayout.tsx`) |
|---|---|
| SettleModal: doc uploads + mismatch alert + FormulaStrip | `TransferRequests.tsx → SettleModal` |
| Admin Invoices: verify (ShieldCheck) + doc upload flow per invoice | `AdminInvoices.tsx` |
| Shop Balances: credit-limit col + negative-days + "Issue invoice now" CTA | `ShopBalances.tsx` |
| Portal transfer-requests exists but without the full SettleModal richness | |

#### Admin People
| Gap | Demo source (`People.tsx`) |
|---|---|
| Classifications tab with admin Override modal (new classification + reason) | `People.tsx → Classifications tab` |
| Wage type badge per specialist in the list | `People.tsx → Specialists tab` |

#### Admin Shops
| Gap | Demo source (`Shops.tsx`) |
|---|---|
| ActivateModal: 6 document uploads + full commercial config + bank details | `Shops.tsx → ActivateModal` |
| Subscription Plans tab: plan CRUD (name / monthly price / trial days / features) | `Shops.tsx → Plans tab` |
| Subscription Dashboard tab: shop / plan / status / next billing / card last4 | `Shops.tsx → Subscription Dashboard tab` |

#### Admin Marketing
| Gap | Demo source (`Marketing.tsx`) |
|---|---|
| Deals tab: DealsManager component (shopId-scoped) | `Marketing.tsx → Deals tab` |
| Ads tab: 3 ad cards (placement / impressions / CTR / live badge) | `Marketing.tsx → Ads tab` |
| Push tab: compose form (title + audience select + send) + recent sends list | `Marketing.tsx → Push tab` |
| Portal: push notifications exist but as a standalone route, not the 3-tab Marketing hub | |

---

### ❌ Missing Entirely

#### Admin Notifications TriggerTable (being built)
Demo: `Notifications.tsx` (admin) — full trigger management system.

- TriggerTable: 2 tables (Customer notifications + Shop notifications)
- Columns: Notification (name + timing + preview) | Channels & template (approve flow) | Shop config toggle | Actions
- TriggerModal (lg): BilingualField name + audience + fires + timed offset + per-channel (enable toggle / template textarea / variable insert buttons / preview / char+segment count) + shop-configurable toggle + active toggle
- Currently untracked files are being built — watch for completion

#### Commercial Config (Admin Finance)
Demo: `CommercialConfig.tsx`

- Card 1 — Fees & Tax: VAT % / Marketing fee % / Payment processing fee % / Fixed fee (SAR) / Min marketing fee / Max deposit %
- Card 2 — Settlement & Billing: Min withdrawal / Carry-forward threshold (= credit limit) / Invoice due days / Settlement hold / Grace window / Max shop cancel days
- Card 3 — Messaging: SMS + WA channels; each: live margin badge (green/red) + Sell / Cost / Refund-on-fail / Free / shop / month fields
- Footer: "Save commercial config" (disabled if no changes)
- Note: "Changing a rate affects new charges only — existing ledger rows keep the rate stamped at creation."

---

## Recommended Sequencing (as of 2026-06-28)

```
NOW (unblocked, pure view work):
  1. Finance 5-tab hub shell + Settlement tab          ← biggest user-visible gap, backend ready
  2. Finance Detailed Charges tab                      ← Charge model exists
  3. Finance Invoices tab + PayInvoiceModal            ← Invoice model exists
  4. Finance Subscription tab                          ← plan model exists

NEXT (some schema work):
  5. SpecialistModal: languages + colour + multi-shift ← UX completeness
  6. Services CatalogueModal: BilingualField + ImagePicker ← bilingual mandate
  7. Settings: Walk-ins 2nd toggle + 12h/24h          ← needs 2 new columns
  8. Group Bookings View screen                        ← group booking creation already done

THEN:
  9. Social Media → aurora layout migration            ← S effort
 10. Admin Commercial Config                           ← admin-side
 11. Admin Finance modal richness (SettleModal etc.)   ← admin-side
```

---

## Cross-Cutting Patterns Still Missing

| Pattern | Demo component | Where needed |
|---|---|---|
| BilingualField (EN+AR side-by-side) | `BilingualField.tsx` | Services modal, notification trigger names, catalogue |
| FormulaStrip (horizontal formula) | `FormulaStrip.tsx` | Finance Settlement tab, admin SettleModal |
| ImagePicker + ImageCropper (square crop) | `ImageCropper.tsx` | Services, specialist photo |
| VariantPicker (multi-image) | `VariantPicker.tsx` | Services |
| DataTable (universal table component) | `Table.tsx` | Used everywhere in demo as one component |
| InvoiceBadge / ChargeBadge / TransferBadge | badge components | Finance tabs |
| AvatarStack (overlapping group avatars) | `Avatar.tsx → AvatarStack` | Bookings group rows |
| ShopTile (color-hued logo square) | `ShopTile` (admin) | Admin screens |
