# Report 1 — Functionality & UX Review: Operations Suite

**Date:** 2026-07-28 · **Scope:** every nav entry of the Operations suite — Dashboard · Leads · AI Copilot · Sales · Funnels · Traffics · Portal · Messages · Zoom · Phone Call · Showroom F2F · Setting · **Author:** AI review (Claude), from a full read of the codebase, module handbooks, and live data volumes.

> Companion report: [AI Copilot Development](./2026-07-28-ai-copilot-development.md). Read this one first — several AI recommendations depend on fixing the data-capture gaps identified here.

---

## Executive summary — the ten changes worth making first

The platform's architecture is strong: one identity spine (`LeadLinker`, lead == portal user), one shared analyzer for all three recording types, one inbox for all messaging channels, one DataTable/filter foundation for every list. The gaps are almost never *missing modules* — they are **broken feedback loops between modules that already exist**, and **data capture discipline**.

| # | Priority | Area | Why |
|---|----------|------|-----|
| 1 | **Work the 9,651-lead gap** | Leads → Sales | 9,846 leads exist; only 195 have ever had an engagement. The pool is 98% untouched. Everything else is secondary to this. |
| 2 | **Fix booking data capture** | Sales | 0/182 bookings carry SPA price, bank, SPA/LO dates; 0/195 engagements have a closer. The columns, filters, and sorts all exist and all render "—". |
| 3 | **Speed-to-lead SLA queue** | Leads | No "new leads awaiting first touch" view with timers. Industry-standard: contact within 5 minutes multiplies conversion. |
| 4 | **Close the loop: attendance → pipeline** | Funnels → Sales | 1,004 event registrations, but attendance never creates/updates an engagement. A webinar attendee is the warmest lead in the building. |
| 5 | **Surface recording insights where work happens** | Phone/F2F/Zoom → Leads/Messages | `ConversationAnalyzer` already extracts interest level, buying stage, objections, next steps — but only into a per-recording drawer. It should feed the lead page, the inbox, and coaching. |
| 6 | **Portal activation** | Portal | 10,063 users; 1 wealth plan, 2 analyses, 3 AI conversations. The portal features work; almost nobody is brought to them. The new Activity tab now makes this visible. |
| 7 | **Traffics → revenue attribution** | Traffics | CPL exists; cost-per-*booking* doesn't. The data to join spend → lead → engagement → booking is all present. |
| 8 | **Agent coaching dashboard** | Dashboard | `sales_performance.score` (0–10) exists on every analyzed recording. Nobody aggregates it per agent over time. |
| 9 | **Pipeline status hygiene** | Sales | 98 Converted + 79 Lost, zero rows in Booked or any working status. Either the team skips stages (enforce) or statuses are backfilled at import (accept + label). |
| 10 | **Deploy DB backup** | Ops | Every deploy writes a 20-byte empty backup. Fix `mysqldump` host flag before the next migration-carrying deploy. |

---

## Per-area review

### 1. Dashboard (`/manage/sales/dashboard` — Insights · Sales · Pipeline · Calendar)

**Today:** Revenue roll-up across three streams (bookings + memberships + product purchases), Insights page, the cross-project engagement kanban (property line only, correctly labelled since the six-line pill strip landed), and the calendar.

**Recommendations**
- **Add a funnel strip to the top of Dashboard:** Leads → Registrations → Attended → Engagements → Booked → Converted, each with week-over-week deltas. Every number already exists in one query each; today the reader must visit five pages to assemble the story.
- **Agent leaderboard:** bookings, revenue, calls made (`call_recordings` per admin), average `sales_performance.score`, average response time. All derivable now.
- **Pipeline board:** the six-line pill strip is honest about only Property Booking existing. When a second line gets a board, resist a second kanban component — parameterize the existing one.
- **Calendar:** currently peer to Sales/Insights inside the hub. Consider surfacing "today's appointments" as a Dashboard card — the calendar is a destination, but today's schedule is a glance.

### 2. Leads (`/manage/leads`)

**Today:** The richest list page (search, filters, export, per-lead portal aggregates, distribution, enrichment with GeoIP/device/phone/WhatsApp-presence/Gravatar/Google-Places signals via `EnrichLeadJob`), backed by the `LeadLinker` identity spine.

**Recommendations**
- **Next-action worklist mode.** The index answers "who exists"; nothing answers "who do I work now". Add a default segment: unworked new leads (no engagement, no outbound message, age < 7d) with an SLA timer column. This is the single highest-leverage UX change in the suite (see Exec #1, #3).
- **Saved segments.** Filter combinations are URL state only. Let admins pin named segments ("Hot: attended last webinar, no engagement").
- **Enrichment as filters.** 1,213 leads enriched, but signals (valid phone / on WhatsApp / device / geo) are display-only on the Identity tab. "Phone NOT on WhatsApp" is a fake-lead filter the drawer should offer.
- **Bulk actions.** No multi-select. Bulk assign, bulk add-to-pipeline, bulk tag would remove the biggest remaining grind.
- **`activity_logs` is underused (31 rows).** The `ActivityLogger` service exists and never throws — instrument the write paths (status change, assign, booking) so the lead timeline actually fills.

### 3. AI Copilot (`/manage/ai-copilot`)

Placeholder (by design). The entire second report is its build plan. One UX note for when it lands: it sits in the unsectioned top zone because it acts on *whatever is in front of you* — its v1 should therefore be reachable from context (lead page, inbox thread) and not only as a page.

### 4. Sales (`/manage/memberships`, `/manage/sales-projects`, …)

**Today:** Six product lines, each carrying the Pipeline → Sales → Referral & Repeat stage rail; Property Booking fully built (Property Match → Bookings with search/filter/sort + in-place edit → ripeness-ranked referral worklist); Memberships (5 tiers, 452 subscriptions); Rental at stage 1; three lines placeholdered.

**Recommendations**
- **Data hygiene nudges (Exec #2).** A booking row with no SPA price should say so actionably: an amber "3 fields missing" chip that opens the edit modal, and a "missing SPA price" filter. Commission-basis config is meaningless while every `spa_price` is null.
- **Stage-conversion metrics on the rail.** The chevrons carry counts; add the rates between them (match → booking %, customer → referral %). A funnel that shows counts but not conversion invites vanity reading.
- **Pipeline statuses are unused (Exec #9).** All 177 outcomes are terminal (Converted/Lost); the working statuses (New → Contacting → Appointment Set → With Closer) hold zero rows, and `closer_admin_id` is never set. Decide: enforce stage progression in the UI (require passing through Booked; require a closer on booking), or accept that historical imports jump to terminal and label them as imported.
- **Property Match & Rental Estimate have 0 submissions.** Both public funnels are live and polished. This is a marketing problem, not a code problem — but each stage-1 page should show its landing-page link prominently (done) plus a QR code for offline events (cheap add).
- **Referral stage:** `referral_asked_at` is null for all 90 customers — the worklist is fresh. Watch whether "Mark asked" gets used; if not, integrate the ask into the WhatsApp inbox (one-tap "send referral ask" template) rather than expecting a separate ritual.

### 5. Funnels (`/manage/events/funnels` — Funnel · Meta Ads · AI Video)

**Today:** Mature: funnels → slots → sessions → Zoom webinars, attendance tracking with walk-in capture and lead minting, per-session Meta ad snapshot (session-level CPL), WhatsApp welcome/reminder automation with provider-aware templates and magic links, QR tickets.

**Recommendations**
- **Attendance → pipeline (Exec #4).** `EventRegistration` knows who attended and for how many minutes. Nothing downstream reacts. Minimum: an "attended, not in any pipeline" segment on Leads; better: a post-session prompt — "18 attended · 12 not in a pipeline → add to [project]".
- **No-show remarketing.** No-show lists exist per session (with export). Wire a one-click "enrol no-shows into the next session + send the invite flow" action — the WhatsApp flow machinery already supports campaign triggers.
- **Session detail is the hub's strongest page; the funnel list is its weakest.** The list shows names; it should show each funnel's live stats (next session, registrations this week, CPL trend sparkline).

### 6. Traffics (`/manage/marketing/campaigns`)

**Today:** One page — every Meta campaign across connected accounts with spend and CPL, date-range picker. Mapping/Setting stayed under Funnels → Meta Ads (correct split; verified no highlight overlap).

**Recommendations**
- **Cost per booking, not just per lead (Exec #7).** Join exists: campaign → `lead_funnels` attribution → lead → engagement → booking revenue. Even with sparse booking data this reframes ad decisions from "cheap leads" to "leads that transact".
- **Trend, not snapshot.** Spend/CPL as a time series (the `dataviz` charting already used elsewhere in Insights can be reused), with campaign start/stop annotations.
- **Drill-through:** clicking a campaign should open Leads filtered to that campaign's attribution — the filter key already exists on `lead_funnels`.

### 7. Portal (`/manage/portal-engagement` — Activity · Wealth Planning · Analyze Property · Concierge · AI Conversations · Courses)

**Today:** Read-only discovery layer over the customer portal, now fronted by the Activity timeline (five behaviors, one feed, tiles-as-filters).

**Recommendations**
- **The numbers are the finding (Exec #6):** 10,063 portal accounts; 1 wealth plan, 2 analyses, 1 concierge request, 3 AI conversations, 8 lesson views. Either members don't know the portal exists or onboarding never routes them there. Fix outside this module: a WhatsApp flow step ("Your account is ready — analyze your first property: {{login_link}}"), webinar follow-ups linking to a portal feature, LMS course completion prompts.
- **Make Activity actionable.** Rows are read-only. Each should offer "message on WhatsApp" — a member who just ran an analysis is a live signal an agent should act on within the hour, and the inbox deep-link (`/manage/messages?search=<phone>`) already exists.
- **Alert on high-intent signals.** The `Notifier` service (Telegram) exists precisely for this: "lead X created a wealth plan" as a registered event admins can subscribe to.

### 8. Messages (`/manage/messages` — Inbox · Broadcasts · AI Automation · Settings)

**Today:** The most mature module: unified WhatsApp (Cloud + Bridge) + Messenger inbox (19,070 messages, 1,048 conversations), broadcasts, 20 flows (drip + menu-bot types with parallel slots, template validation at four points), 5 AI profiles (draft/auto modes, debounce, active hours, layered knowledge docs), CTA links, tags.

**Recommendations**
- **Thread summary on open.** Long threads force scroll-reading. A cached AI summary + extracted state ("viewing Tuesday, budget ~600k, objection: loan margin") at the top of the pane — `AiClient` and the profile knowledge are already wired.
- **Unanswered-queue view.** The inbox sorts by activity; nothing isolates "customer spoke last, > N hours ago". That is *the* daily supervisor view for response SLAs.
- **Chat-level sentiment/intent.** `ConversationAnalyzer` runs only on recordings. A lightweight message-thread classifier (interest level, buying stage) would let the inbox filter by "hot conversations" — and become a lead-scoring feature (Report 2).
- **Messenger is marginal (18 messages).** Don't invest further until volume justifies it; the unified inbox already absorbs it correctly.

### 9. Zoom (`/manage/zoom` — Recordings · Polls · Settings)

**Today:** S2S OAuth account integration; webinars with registration/attendance; 1:1 meetings; 1,694 cloud recordings with transcript fetch + the shared analyzer; polls.

**Recommendations**
- **1,694 recordings is your largest conversation corpus** — larger than calls (214) and F2F (4) combined. Confirm the analysis backlog is actually processed (the pipeline analyzes 1:1s, not webinars); an "unanalyzed" count on the Recordings page would keep it honest.
- **Webinar recordings are deliberately never analyzed** — right call for cost. But a *single* per-webinar summary (topics, questions asked in chat — webinar chat capture exists) is one AI call per session and directly feeds the follow-up flow.

### 10. Phone Call & 11. Showroom F2F (`/manage/calls`, `/manage/f2f`)

**Today:** Two device-ingest pipelines (dowayai poller, yhy badge webhook) feeding one standardized recording surface: shared columns (Lead/Agent/Duration/Date/Stage), shared `RecordingDetail` tabs, shared transcription (Gemini→Deepgram) + analyzer, suggested-match review, tombstone-delete semantics that survived real incident debugging.

**Recommendations**
- **These modules are engineering-complete; their output is under-consumed (Exec #5).** The analysis (interest, stage, objections, next steps, score) should propagate: to the lead's show page ("last conversation: high interest, decision stage"), to a follow-up suggestion ("analyzer said follow up Friday — create appointment?"), and to coaching (Exec #8).
- **`agent_call_events` is empty** — click-to-call logging never fires, which starves the suggested-match feature for phone-less dowayai recordings. Either instrument the inbox call button properly or expect Unmatched to accumulate.
- **F2F has 4 recordings.** The pipeline is proven; the badges aren't worn. Hardware adoption, not software.

### 12. Setting (`/manage/people/admins` hub — Admins · Roles · Products · Devices · AI Requests · Notifications · System Health)

**Today:** Correctly consolidated into one pinned-footer hub (post-refactor); Products folded in with its three sub-tabs; device registry doubles as ingest-account management with retroactive attribution backfill.

**Recommendations**
- **AI Requests page will matter much more after Report 2** — 764 rows today, thousands later. Pre-emptively add per-feature/per-day cost aggregation (the columns exist) so AI spend is readable before the copilot multiplies it.
- **Notifications (the `Notifier` Telegram service) is the delivery rail for half the recommendations above** — new-lead SLA breaches, high-intent portal signals, deploy failures. Register those events as they're built.

---

## Cross-cutting UX themes

1. **Lists are excellent; "what should I do next" is absent.** The §14 DataTable foundation made every list consistent — the next maturity level is opinionated queues (SLA, unanswered, missing-data) that turn lists into work.
2. **Counts everywhere, conversions almost nowhere.** Stage rails, chips and tiles all show totals. Ratios between stages are what change behavior.
3. **Signals don't travel.** Enrichment stays on Identity; analysis stays in the recording drawer; attendance stays in Events. The lead page and the inbox are where decisions happen — pipe signals there.
4. **Empty states should teach.** Several pages are empty because upstream behavior hasn't happened (Property Match, F2F, portal pivots). Each empty state should say what fills it and link to the lever (landing page, device registry, flow builder).
5. **Ops debt:** deploy DB backup writes empty files (fix the `mysqldump` host flag); `routes/web.php` declares the `rental-estimates` group twice (harmless, delete one); Diver's `QueryRequest` throws a PHP 8.4 deprecation on every request (one-line nullable-param fix in `diver/Http/Requests/QueryRequest.php:49`).
