Files
pn-new-crm/docs/superpowers/audits/2026-05-21-remaining-plan.md
Matt a555798cfe docs(uat): structured plan for remaining master-doc items
Captures all 66 still-open items from `alpha-uat-master.md` (Buckets
1-4 plus the deferred bugs and DEFERRED-tagged features) into a
single sequential plan. Items grouped so logically-related work
lands as one PR rather than scattered commits.

Groups (suggested execution order):
  A — Tiny copy / UI fixes (12 items, ~1 h)
  B — Interest detail polish (7 items, ~2 h)
  C — Berth list features (4 items incl. bulk-edit, ~2.5 h)
  D — BulkAddBerthsWizard polish (2 items, ~1.5 h)
  E — Supplemental-info-request (1 item, ~1 h)
  F — DocumentsHub + signing flow polish (3 items, ~3 h)
  G — Admin sections consolidation (2 items, ~6 h)
  H — Email + branding (2 items, ~2 h)
  I — Residential parity (4 items, ~10 h)
  J — Activity feed + EntityActivityFeed (2 items, ~2 h)
  K — OnboardingChecklist + nudges (1 item, ~6-8 h)
  L — UploadForSigningDialog rework (1 item, ~12-16 h)
  M — Universal preview + form-templates (2 items, ~12-16 h)
  N — Dashboard upgrades (3 items, ~10-14 h)
  O — Umami phases 3 / 4 / 5 (9 items, ~14-18 h)
  P — Nested document subfolders phases 2/3 (1 item, ~5-6 h)
  Q — Platform-wide refactors (5 items, ~14-18 h)
  R — Documenso-first templates (1 item, ~6-8 h)
  S — AI extraction (deferred, ~10-14 h)
  T — Deferred bugs (2 items)
  U — EOI bundle UX rework (1 item, ~10-14 h)

Per-item: scope summary, file pointers, effort estimate, blocks-on /
pairs-with annotations. Execution discipline section at the bottom
describes the per-item workflow (quote source bullet → verify not
already shipped → implement + test → annotate master doc → tick
off plan).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 21:18:52 +02:00

21 KiB
Raw Blame History

Remaining UAT Master Doc — Work Plan

Source: alpha-uat-master.md (Bucket 1-4) as of commit d879188. Survey done 2026-05-21 after the PDF report exporter ship.

Status: scaffold for sequential execution. Each item has a scope summary, file pointers (copied from the source entry where helpful), effort estimate, and explicit ordering notes (blocks-on / pairs-with). Items are grouped so logically-related work lands as one PR rather than scattered.

How to use this doc

  • Items are in suggested execution order (top → bottom). Order optimises for (a) unblocking other items, (b) low-cost-high-impact wins first, (c) defer-until-design large features to the end.
  • Each item is one of:
    • Q — quick fix (< 30 min)
    • M — medium (30 min 2 h)
    • L — large (2 h+)
    • DEFERRED — captured but blocked / waiting on external decision
  • We work top to bottom. When an item lands, annotate it in alpha-uat-master.md with the SHIPPED-in-commit line AND tick it off here.

Group A — Tiny copy / UI fixes (batch as one PR, ~1 h total)

These are all <15 min each. Bundle so the commit history doesn't sprawl.

  1. [Q] Admin Documenso settings: surface env-fallback state pillssrc/app/(dashboard)/[portSlug]/admin/documenso/page.tsx. Pattern from 203f543 (env-fallback tooltip on password fields) needs to be applied to all Documenso settings fields. Show Using env fallback / Per-port override active pill next to each field. ~30 min.
  2. [Q] WatchersCard empty-state padding — small CSS fix, add pb-2 or pb-3 to the empty state. ~5 min.
  3. [Q] EOI empty state: add "Mark as signed without file" button (parity with Reservation + Contract tabs)src/components/interests/interest-eoi-tab.tsx — copy the existing button from the reservation/contract tabs that fires markStageSigned without requiring a PDF upload. ~10 min.
  4. [Q] /invoices/upload-receipts guide: copy rewrite — terse, professional, in the luxury-CRM voice. ~10 min.
  5. [Q] Pageviews chart: X-axis date ticks too cramped — drop the time componentsrc/components/website-analytics/. Format ticks MMM d instead of MMM d HH:mm. ~5 min.
  6. [Q] Pageviews chart: inline note explaining Pageviews vs Sessions — small <p> under the chart title. ~5 min.
  7. [Q] Inbox: swap section order — Reminders above Alertssrc/components/inbox/. Single JSX reorder. ~3 min.
  8. [Q] BulkAddBerthsWizard: currency field should use <CurrencySelect>src/components/admin/bulk-add-berths-wizard.tsx. Swap raw input for the existing component. ~5 min.
  9. [Q] CommandList scroll-cap bugsrc/components/ui/command.tsx. CommandList inside Popover scrolls short of the bottom. Add max-h-[var(--radix-popover-content-available-height)] to the inner scroll container. Affects every cmdk dropdown. ~10 min.
  10. [Q] DropdownMenu content stretches to fill viewport — cap itsrc/components/ui/dropdown-menu.tsx. Add max-h-[80vh] to the content variant. ~5 min.
  11. [Q] Residential InterestsTab: whole row should navigate to the interest, not just the "View" link — wrap row in <Link> or add onClick to the row. ~10 min.
  12. [Q] StageStepper: surface stage names visibly on reached slicessrc/components/interests/stage-stepper.tsx. Currently shows just an icon; add aria-label + visible text below the icon on reached slices. ~15 min.

Commit shape: one PR titled chore(uat-batch): group-A copy + UI quick fixes (12 items).


Group B — Interest detail polish (~2 h total)

Surfaces all touch interest-tabs.tsx / interest-overview / linked-berths. Grouping keeps the diff focused on one entity.

  1. [M] Inbox → Reminders: move filter row inline with the "New Reminder" button (embedded mode)src/components/reminders/reminders-list.tsx. Add an embedded?: boolean prop that consolidates the filter row + the New button into one row when set. ~45 min.
  2. [M] Interest Overview Email + Phone rows: combobox picker across client's contacts + quick-add new contactsrc/components/interests/interest-tabs.tsx + src/components/clients/client-contacts-picker.tsx (new). The Email + Phone rows on the Overview currently show only the primary; reps want to pick any of the client's contacts and add new ones inline. ~1 h.
  3. [M] Inline phone editor on the Contact row — adjacent to #14; add InlineEditableField variant="phone" (or similar) using the country-code + national-number split. ~30 min.
  4. [M] Client Overview should summarize current interest's requirements — one-line "current interest needs L × W × D, source X" on the Client detail Overview tab. ~30 min.
  5. [M] Notes Latest-note teaser missing round / stage context pillsrc/components/interests/interest-tabs.tsx around the latest-note teaser. Pull the stage at the time of the note (from audit_logs) and render as a chip next to the timestamp. ~45 min.
  6. [M] InterestBerthStatusBanner: name + link the competing dealsrc/components/interests/interest-berth-status-banner.tsx. Today says "this berth is also linked to another interest"; should name the client + link to the interest. ~30 min.
  7. [M] Qualification auto-confirm "intent confirmed" once stage ≥ EOI (extend computeAutoSatisfied)src/lib/services/qualification.service.ts. Add the auto-confirm rule. Most of the work shipped earlier; this is the final tightening. ~30 min.

Commit shape: one PR titled feat(uat-batch): Interest detail polish (Group B — 7 items).


Group C — Berth list features (~2.5 h)

  1. [M] Berth list: hide "Rates (USD)" + "Pricing valid" columns by default (or remove)src/components/berths/berth-columns.tsx + BERTH_DEFAULT_HIDDEN. Short-term rental fields irrelevant to purchase/long-term ports. Update default visibility; do not remove columns (other ports may still use them). ~10 min.
  2. [M] Dimensions columns: add ft↔m toggle in the column header (persisted to user prefs); skip per-row entry-unit indicatorsrc/components/berths/berth-columns.tsx, src/components/yachts/yacht-columns.tsx, src/components/clients/client-yachts-tab.tsx, src/components/companies/company-owned-yachts-tab.tsx, plus new src/lib/utils/dimensions.ts for the conversion + format helper, and src/lib/db/schema/users.ts user_profiles.preferences for the persisted preference key. ~1 h.
  3. [M] ft ↔ m unit switching on Berth Requirementssrc/components/interests/interest-tabs.tsx — the three inline-editable dim rows hard-code (ft) in the label. The interest already carries desiredLengthUnit; honour it. ~30 min.
  4. [L] Berth list: bulk-edit affordance (parity with bulk-add)src/components/berths/, src/lib/services/berths.service.ts, new endpoint POST /api/v1/berths/bulk. Backend mirrors /interests/bulk shape; UI gets a DataTable bulkActions toolbar. ~5-7 h. Pairs with: Bucket 3 #2 Bulk-price editing UI — the inline-price-edit + bulk-price-sheet should land alongside this. Combined effort ~7-10 h.

Commit shape: two PRs — feat(berths): dimensions column toggle + hide rental columns (B-20/21/22), feat(berths): bulk-edit + bulk-price UI (B-23 + Bucket 3 #2).


Group D — BulkAddBerthsWizard polish (~1.5 h)

  1. [M] BulkAddBerthsWizard + single-berth editor: toggleable input units (ft/m) for dimension fieldssrc/components/admin/bulk-add-berths-wizard.tsx + src/components/berths/berth-form.tsx. Tiny segmented toggle above the dimension inputs (ft / m). Convert on submit so the canonical column stays consistent. ~45 min.
  2. [M] BulkAddBerthsWizard: allow defining new dock/pontoon letters in-flow (or surface the admin path)src/components/admin/bulk-add-berths-wizard.tsx. Currently fixed to A/B/C/D/E. Add "+ New letter" affordance or a clear "manage letters in /admin/vocabularies" link. ~30 min.

Commit shape: one PR titled feat(berth-admin): wizard polish (Group D).


Group E — Supplemental-info-request (~1 h)

  1. [M] Supplemental-info-request: distinct Regenerate vs Resend actions + issue historysrc/components/interests/supplemental-info-request-button.tsx. Today's UI has a single Generate + Send button; add: Regenerate (new token, invalidates old), Resend (re-email existing token), and a small history list of past issuances + their status. Builds on what a4e30ea already shipped (generate vs send split). ~1 h.

Note: Supplemental-info-request separate generate link and send email + link reusable already SHIPPED (a4e30ea, b74fc56).


Group F — DocumentsHub + signing flow polish (~3 h)

  1. [M] DocumentsHub: hide breadcrumb on root "All documents" view, move PageHeader upsrc/components/documents/hub-root-view.tsx + the surrounding shell. Conditional render. ~30 min.
  2. [M] Past-milestones strip → expandable history with inline doc previewsrc/components/interests/interest-tabs.tsx around line 863 (past-milestones strip). Convert to accordion; each past milestone expands to show its associated docs + sub-status timeline + inline PDF preview using the existing pdf-viewer primitive. ~3-4 h.
  3. [M] Watchers configurable at document creation timesrc/components/documents/eoi-generate-dialog.tsx, src/components/documents/upload-for-signing-dialog.tsx, src/components/interests/external-eoi-upload-dialog.tsx, src/components/documents/create-document-wizard.tsx:157 + service-side defaults. ~1.5 h.

Group G — Admin sections consolidation (~6 h)

  1. [L] Merge /admin/invitations into /admin/userssrc/app/(dashboard)/[portSlug]/admin/users/page.tsx, src/app/(dashboard)/[portSlug]/admin/invitations/page.tsx (to be removed), src/components/admin/users/, src/components/admin/admin-sections-browser.tsx:90-95. Add a state filter All | Active | Invited (pending) | Disabled | Archived. Default to Active. ~3-4 h.
  2. [L] Consolidate every AI-feature admin control onto /admin/aisrc/app/(dashboard)/[portSlug]/admin/ai/page.tsx + per-feature embedded forms. Berth PDF parser AI fallback, AI/OCR pipeline, plus deferred sections (recommender embeddings, contact-log extraction, inquiry parsing). Berth PDF parser AI fallback is the only currently-LLM-using feature without a section — surface its provider override, confidence threshold, per-call budget cap. ~2 h for the present one + UI hooks for the deferred sections.

Group H — Email + branding (~2 h)

  1. [M] Email settings page: add explainer copy clarifying why sales send-from and noreply have separate credentialssrc/app/(dashboard)/[portSlug]/admin/email/page.tsx — small description block. ~15 min.
  2. [L] Supplemental-info-request email: branded HTML stylingsrc/lib/email/templates/ — rebuild the template to match the table-based, max-width 600, logo + blurred overhead background look. ~1-2 h.

Group I — Residential parity (~10 h, single coordinated PR)

  1. [M] Residential client detail header: match the main ClientDetailHeader layoutsrc/components/residential/residential-client-detail-header.tsx + src/components/clients/client-detail-header.tsx. Restructure. ~1 h.
  2. [L] Residential interests list: visual + functional parity with the main InterestListsrc/components/residential/residential-interests-list.tsx vs src/components/interests/interest-list.tsx. Card / table / kanban view modes, full FilterBar, ColumnPicker, bulk actions, realtime invalidation, kebab actions. ~6-8 h.
  3. [L] Residential inquiry → auto-forward to external partner email(s)src/lib/services/residential.service.ts + admin settings UI + new template + BullMQ enqueue. ~2-3 h.
  4. [L] Auto-link residential interests to existing main-client records (same person) — schema migration + service join + UI surfaces on both sides + backfill script. ~3-4 h.

Group J — Activity feed + EntityActivityFeed (~2 h)

  1. [M] EntityActivityFeed: rewrite per-row rendering to surface what changedsrc/components/shared/entity-activity-feed.tsx. Current rows are flat "user X did Y"; rewrite to show the field-level diff (old → new) using the existing audit-log diff shape. ~2 h.
  2. [M] Client → Companies tab: add CTA to link or create a company membershipsrc/components/clients/client-companies-tab.tsx. Empty-state CTA + dialog. ~1 h.

Group K — OnboardingChecklist + nudges (~6-8 h, single big PR)

  1. [L] OnboardingChecklist: auto-check resolver-chain fix + super_admin discoverabilitysrc/components/admin/onboarding-checklist.tsx + src/lib/services/port-config.ts + new dashboard tile + new topbar banner. Two linked issues:
    • (a) Replace each autoCheckSettingKey with an autoCheckResolver function that runs the full resolver chain and returns true when the functional config is complete. Belt-and-braces: surface what's resolving from where ("Email: ✓ Using global SMTP" vs "Per-port override").
    • (b) Topbar banner (slim chip "Setup X% complete · Continue →" dismissible per-session), dashboard rail tile "Continue setup", in-app weekly notification, 🎉 100% celebration. Gate all on super_admin.

Group L — UploadForSigningDialog comprehensive rework (~12-16 h, dedicated PR)

  1. [L] UploadForSigningDialog comprehensive rework — 4 linked issues — Documenso PDF preview rebuild, metadata + draft persistence, dialog width responsive sizing, field-placement UX. Bundles with Documenso v2 follow-ups. Single coordinated PR.

Group M — Universal preview + form-templates (~12-16 h)

  1. [L] Universal in-system preview for every file type — extend FilePreviewDialog beyond PDF + images. .docx / .xlsx / .pptx via google-doc-viewer iframe or libreoffice headless; .txt / .csv / .md inline; .eml / .msg via mailparser; .zip see-into. ~6-10 h.
  2. [L] Form-template fields bind to Interest/Client data — autofill, override-preservation history, dual-surface audit trailsrc/lib/db/schema/documents.ts:290-309 (formTemplates.fields JSONB) + the New-form-template dialog UI + supplemental-forms.service.ts + new interest_field_history table + Interest/Client detail surfaces. ~8-12 h.

Group N — Dashboard upgrades (~10-14 h)

  1. [L] Pipeline Value tile should respect dashboard timeframe — Dashboard-wide timeframe context (Zustand store or React Query keyed by range); forecast/KPI service variants accept a range; "realized vs forecast" line. ~3-4 h.
  2. [L] "Clients by country" dashboard widget — compact ranked list with mini bars per row, deep-link /clients?country=DE. ~2-3 h.
  3. [L] Drag-and-drop rearrangable dashboard widgets — extend useDashboardWidgets to read a dashboardWidgetOrder preference; @dnd-kit/core + @dnd-kit/sortable; persist via PATCH /api/v1/me/preferences. ~4-6 h.

Group O — Umami analytics phases 3 / 4 / 5 (~14-18 h)

  1. [L] Umami Phase 4a — Marketing-site instrumentationBLOCKS Phase 3 + Phase 5. Wire umami.track() calls into the marketing site for every CRM event we want to surface (inquiry submitted, brochure download, contact-form, etc.). ~3-4 h on the marketing-site repo + alignment with this repo.
  2. [L] Umami Phase 4c UI — Tracked-link composer buttonsrc/components/email/email-composer.tsx or wherever the rep writes a templated email; add a button that opens a tracked-link composer + injects the resulting URL. ~2-3 h.
  3. [L] Umami Phase 3 — Events tabsrc/components/website-analytics/events-list.tsx (new). Blocked on 4a. ~3-4 h.
  4. [L] Umami Phase 5 — Funnels + Journeys — Funnel builder + journey-flow sankey. Blocked on 4a. ~6-8 h.
  5. [M] Umami: Empty-state nudges on quiet rangessrc/components/website-analytics/. Stable copy when the range has < N events ("Nothing happened here; try a wider range"). ~30 min.
  6. [M] Umami: Apple Mail privacy disclaimer copysrc/components/email/email-open-rate-pill.tsx — small tooltip explaining that Apple Mail Privacy Protection inflates open rates. ~15 min.
  7. [M] Umami: Open-rate column on the document_sends listsrc/components/documents/document-sends-list.tsx. New column reading the per-send open count. ~30 min.
  8. [M] Umami: Click-to-filter the page from the world mapsrc/components/website-analytics/visitor-world-map.tsx. Wire onCountryClick(iso2) into a new country filter store + thread through every useUmami* hook. ~2-3 h.
  9. [M] Umami: Verify pixel + tracked-link end-to-end with a real send — manual UAT. ~15 min once 4a is live.

Group P — Nested document subfolders — phases 2/3 (~5-6 h)

  1. [L] Nested document subfolders — phases 2 and 3 — foundation shipped in e91055f. Remaining:
    • (a) UploadZone gains scopeOptions radio: "This deal (Interest )" vs "Client-level (all deals)". Single-scope contexts (client/yacht/company) hide the radio.
    • (b) Lifecycle hooks: interest outcome → folder rename (Deal A1-A3 (Won)); soft-rescue on outcome change.
    • (c) listFilesAggregatedByEntity rewrite — surface BOTH "This deal" subheading + "From client" subheading on the InterestDocumentsTab "Attachments" list.
    • (d) Documents Hub tree rendering for nested interest folders + outcome chip per interest folder.
    • (e) Backfill script pnpm tsx scripts/backfill-nested-document-folders.ts --apply — idempotent, per-port advisory-locked.

Group Q — Platform-wide refactors (~14-18 h, do as coordinated passes when time allows)

  1. [L] Platform-wide chart library migration: recharts → ECharts — port the 8 existing recharts components to ECharts. ~6-10 h.
  2. [L] SelectTrigger height (h-9) doesn't match Input height (h-11)src/components/ui/select.tsx. Introduce size variant; default to h-11. Audit compact-context call sites for explicit size="sm" override. ~1 h.
  3. [L] Platform-wide table density: column min-widths + nowrap defaultssrc/components/shared/data-table.tsx + per-table column definitions. Add a widthPx / nowrap field to column defs; default text cells to whitespace-nowrap; surface horizontal scroll only when content actually exceeds. ~2-3 h.
  4. [L] Platform-wide admin-settings tooltip auditsrc/components/admin/. Sweep every admin setting; add FieldLabel + tooltip wherever the setting isn't self-explanatory to a basic admin user. Use the FieldLabel primitive shipped in PR4.2 / 552b966. ~3-4 h.
  5. [L] Platform-wide error message audit for prod debuggabilitycross-cutting. The Documenso 502 / "Invalid token" diagnosis loop showed errors don't self-describe in prod. Two layers: (a) service-side: wrap upstream errors with the resolver chain that's actually in effect; (b) UI: render the wrapped error verbatim in the toast / dialog so operators can see "fell back to env, env value is stale" without reading logs. ~4-6 h.

Group R — Documenso-first templates (~6-8 h)

  1. [L] Documenso-first templates: pull templates from Documenso instead of uploading through CRMsrc/components/admin/document-templates/template-form.tsx + new admin endpoint GET /api/v1/admin/documenso/templates + per-template field-mapping editor + "Sync now" button + template-list badges. Generalizes the existing per-port EOI sync. ~5-7 h. Pairs nicely with: Group L (UploadForSigningDialog rework) — they share the same Documenso-side surface area.

Group S — AI assistance + extraction (~10-14 h, deferred until user asks)

  1. [DEFERRED] AI-assisted action extraction from contact-log entriessrc/components/interests/interest-contact-log-tab.tsx + new LLM service. "Extract action items" button next to Save; LLM-parses body + returns proposed follow-ups; rep approves each individually. ~6-10 h. Defer until a user is genuinely asking.

Group T — Deferred bugs (~1 h each, do when surfacing)

  1. [DEFERRED] Duplicate row for berth E17 in port-nimara + missing unique index — DB cleanup + partial unique index (port_id, mooring_number) WHERE archived_at IS NULL. Deferred per session call.
  2. [DEFERRED] Stage advance allowed without berth priceValidationError gate in changeInterestStage for stages ≥ eoi. Deferred per session call.

Group U — EOI bundle UX rework (~10-14 h)

  1. [L] EOI bundle UX rework (multi-berth interests)src/lib/services/interest-berths.service.ts, src/components/interests/linked-berths-list.tsx, src/components/documents/eoi-generate-dialog.tsx. Per the locked design notes in master line ~492. Refines the "which berths sign the EOI?" UX now that the underlying schema supports it. ~10-14 h. Partially shipped (a) in 05e727f; remaining is the picker-inside-generate-dialog.

Execution discipline

For each item we tackle:

  1. Quote the master-doc bullet so we're aligned on scope.
  2. Verify it isn't already shipped — re-read the master entry for sub-bullets with SHIPPED markers I may have missed.
  3. Implement to production quality — tests where the feature has logic worth testing; tsc clean; vitest 1454+/1454+; commit with a descriptive message.
  4. Annotate the master doc — add **SHIPPED in <sha>:** line under the original entry.
  5. Tick off this plan — once a group lands, mark the item as [SHIPPED] here.

When in doubt about an item's scope, surface the question first rather than guessing — several items already locked design decisions in the source entry that we should reuse verbatim.