chore(audit-drain): rip out next-intl, RTL lint, sweeps, polish
Drain the long-tail audit queue captured in alpha-uat-master.md.
- next-intl ripped out (zero useTranslations callers ever existed):
package.json, next.config.ts plugin wrap, src/i18n/, messages/, and
the layout NextIntlClientProvider all gone; <html lang="en"> hardcoded.
- RTL lint nudge added: warn-only no-restricted-syntax on physical
Tailwind utilities (ml-/mr-/pl-/pr-/text-left/text-right/border-l/
border-r/rounded-l-/rounded-r-) inside JSX className literals.
Existing ~1,000 sites grandfathered; new code trends toward logical.
- Icon-only button accessibility lint: jsx-a11y/control-has-associated-
label enabled at warn; 4 empty <th>/<td> action placeholders gain
sr-only labels.
- Currency: SUPPORTED_CURRENCIES drops the hardcoded English labels;
new currencyLabel(code, locale?) helper resolves via Intl.DisplayNames.
CurrencySelect + settings-manager migrated.
- Date locale sweep: 7 surfaces flip from toLocaleString('en-GB'|'en-US')
to toLocaleString(undefined, ...) so dates honour runtime locale.
- Dialog/Sheet width: 10 document/EOI/entity-form dialogs gain a
lg:max-w-4xl or lg:max-w-5xl step so wide desktops get breathing room.
- PaymentsSection collapsed-bar: slim one-line bar showing
"Payments - Not received yet" or "Payments - \$X received - N payments
- Expand"; per-interest collapse state persists in localStorage; the
RecordPayment flow auto-expands.
- muted-foreground opacity sweep: 10 text-bearing
text-muted-foreground/{60,70,80} hits dropped to plain
text-muted-foreground for AA contrast on muted bg. Icon-only
(aria-hidden) opacity hits left as-is.
- Micro-type bump: text-[10px] and text-[11px] -> text-xs (12px)
across 87 files in src/components + src/app. Pure mechanical sweep.
- Audit-doc cleanup: alpha-uat-master.md stale 2026-05-25 summary
rewritten with cumulative state through today. Items genuinely still
open are now a short long-tail list.
- New docs/marketing-site-followups.md: Umami Phase 4a/3/5, email
pixel E2E verification, and website-cutover work parked here so
they don't get lost in the CRM audit doc.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
37
docs/marketing-site-followups.md
Normal file
37
docs/marketing-site-followups.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Marketing-site followups
|
||||
|
||||
Items that require edits to the **separate marketing-site repo** (port-nimara.com / portnimara.com), not the CRM. These can't ship from this codebase; they're parked here so they don't get lost when we drain the CRM audit doc.
|
||||
|
||||
Last updated: 2026-05-26.
|
||||
|
||||
---
|
||||
|
||||
## Umami analytics — Phases 4a, 3, 5
|
||||
|
||||
**Source:** `docs/superpowers/audits/alpha-uat-master.md` — Umami follow-ups parked at end of the 2026-05-19 build session.
|
||||
|
||||
- **Phase 4a — Marketing-site instrumentation.** The CRM's Umami integration (Phase 4b — pixel + tracked-link events on outbound sales emails) is shipped. Phase 4a is the parallel work on the marketing site: add the Umami tracking script to every page, instrument the public berth inquiry form submission, instrument the "request more info" buttons, and confirm session-level attribution flows back to the same Umami workspace the CRM reads.
|
||||
- **Phase 3 — Events tab.** Once 4a lands, the CRM's `/admin/website-analytics` page gets an Events tab that lists every named Umami event (inquiry-submitted, brochure-downloaded, berth-details-viewed, contact-clicked, …) with counts, top-source breakdown, and a 30-day trendline. Backend already proxies `/api/umami/events`; UI surface is the missing piece. Blocked on 4a sending real event data.
|
||||
- **Phase 5 — Funnels.** Multi-step funnel widget on the dashboard ("landed on /berths → opened a berth → submitted inquiry → was created as a CRM interest → reached EOI stage"). Joins Umami sessionId with the CRM's `interests.umamiSessionId` snapshot we already write. Blocked on 4a so the first three steps have real data to consume.
|
||||
|
||||
---
|
||||
|
||||
## Email-tracking end-to-end verification
|
||||
|
||||
**Source:** alpha-uat-master.md — Bucket 2 Umami follow-ups.
|
||||
|
||||
- **Verify the pixel + tracked-link with a real send** — flip `email_open_tracking_enabled = true` for port-nimara, send a real sales email to a personal inbox, open it in Mail.app + Gmail web, confirm: (a) a `document_send_opens` row appears, (b) `open_count` + `first_opened_at` increment on the parent row, (c) Umami records an `email-opened` event. Same drill for `/q/<slug>` short-links once the composer ships them. Cannot be automated — needs a real human inbox. This is a CRM-side manual UAT step but it depends on the marketing-site short-link redirector being live.
|
||||
|
||||
---
|
||||
|
||||
## Public berth endpoint email recipient UI (parking note)
|
||||
|
||||
**Source:** memory — "Email ownership at cutover" (`project_email_ownership_at_cutover.md`).
|
||||
|
||||
When the marketing site cuts over and inquiry emails route through the CRM rather than the website's own SMTP, the public berth endpoint + the admin recipient UI need to be in place. Templates + settings keys exist on the CRM side; the marketing-site side needs the form submission target updated to hit `/api/public/website-inquiries` (or whichever the final endpoint is) instead of the legacy mailto. Coordinate as one rollout.
|
||||
|
||||
---
|
||||
|
||||
## How to triage when picking these up
|
||||
|
||||
Each item here has a CRM-side prerequisite or downstream consumer that's already in place. The work itself lives in the marketing-site repo. When you tackle one, link the marketing-site PR back into this file and tick the item off — keep this doc shrinking, not growing.
|
||||
@@ -13,36 +13,46 @@
|
||||
> - `medium` — UX regression, partial functionality, recoverable error
|
||||
> - `low` — cosmetic, copy, polish
|
||||
|
||||
> **2026-05-25 status check** — full audit triage + execution pass landed (~25 commits over two passes). Shipped in this session:
|
||||
> **2026-05-26 status check** — drain pass landed across the long-tail polish queue. Cumulative state below; per-item commit hashes live in `git log`.
|
||||
>
|
||||
> **Bucket 1 (Wave A–E):** Interest form yacht auto-select + EOI dialog "View EOI" toast + berth-picker compact label + Documents-tab Generate-EOI removal + role-scoped interest auto-assign + LinkedBerthRowItem dimension cleanup + ExternalEoiUploadDialog prefill (title + signatories from active EOI) + Overview milestone EOI signature progress widget. a11y aria-live on supplemental info + 13-component date/currency locale sweep (en-US/en-GB → runtime). Primary-berth-always-in-bundle service guard strengthened + backfill migration 0083. Onboarding super_admin discoverability (topbar banner + dashboard tile + celebration toast) wired via `/api/v1/admin/onboarding/status` + shared service. Branded post-completion email idempotency regression test.
|
||||
> **Big-ticket modules shipped (May 25–26):**
|
||||
>
|
||||
> **Bucket 2 (Wave A–E):** Documents Hub folder rail min-width fix at tablet 768. Website analytics KPI 6→3 cols at lg + 6 at xl. Pipeline Value tile compact `$3.5M` format at sm-. Form-error UX rollout to 5 highest-impact forms (client/interest/yacht/company/berth). TopList empty-state nudge primitive. Sheet width default `sm:max-w-sm → sm:max-w-md + lg:max-w-xl`.
|
||||
> - **Reports P3–P7** — `e9ef583` BullMQ render+email worker; `2072f6c` landing + per-kind builder + Templates/Runs/Schedules sub-pages; `3f9c458` CSV output renderer; `866b910` subtitle override + `8998f68` cover-page brand picker. Page is end-to-end functional with scheduled runs, output formats, and dashboard cover branding.
|
||||
> - **Tenancies P2–P7** — `ccc775d` rename migration `berth_reservations → berth_tenancies`; `20549fb` webhook auto-create + first-insert flip; `bfb29ab` public-map status flip via active permanent tenancy; `3a48150` sidebar entry + 404 + API gate; `e4daa48` entity-tab module gate; `911b51a` generic create + edit dialog + self-FKs; `db14056` 4 module-gated dashboard widgets; `d32e557` tenure-aware renewal + transfer actions; `dd25ccf` 7-agent system-wide rename audit fixes. **Chicken-and-egg fix landed 2026-05-26** — webhook auto-create no longer gates itself on `isTenanciesModuleEnabled`; the row-exists fallback in that helper lazily surfaces the module on first signing (`docs/tenancies-design.md` §"When disabled" updated).
|
||||
> - **UploadForSigningDialog field metadata** — `c4450dd` PlacedField.defaultValue + per-type panel inputs + Documenso v2 `field/create-many` payload extension.
|
||||
> - **Bulk operations on berths** — `c549622` bulk-price editing UI (inline cell + bulk-edit sheet); `991e222` bulk-edit affordance covering status/tenure_type/tag/archive + 500-id cap + per-row failure reporting.
|
||||
> - **Documents UX** — `c886933` clickable rows open in-page file preview (Tier 1+2 universal preview); `400ff99` inline edits on berth detail Overview tab now persist visually; `da391b1` interest dimensions dual-source (yacht dims for the recommender).
|
||||
>
|
||||
> **Bucket 2 (Wave F):** Radio field type for admin registry + adopted on `eoi_send_mode` and `documenso_signing_order`. Include-yacht toggle on EOI generate dialog (blanks Section 3 even when a yacht is linked; choice recorded in audit log). External-EOI auto-cancel: replace-or-keep radio shows when a generated EOI is active; replace path voids the upstream Documenso envelope + flips the prior doc to cancelled before the new doc lands.
|
||||
> **Form-error UX sweep — complete.** All `useForm` callers in `src/components` adopt `useFormScrollToError` + `<FormErrorSummary>` (the one remaining holdout is the dev-only `shared/form-devtool.tsx`).
|
||||
>
|
||||
> **Bucket 2 form-error sweep:** All 16 remaining form callsites adopted `useFormScrollToError` + `<FormErrorSummary>` — login / reset-password / set-password / setup auth forms + invoices/new + berth-detail-header + invoice-detail (record-payment) + reservations/berth-reserve-dialog + yachts/yacht-transfer-dialog + companies/add-membership-dialog. Form-error UX sweep now complete platform-wide.
|
||||
> **Bucket 2/4 polish drained 2026-05-26:**
|
||||
>
|
||||
> **Bucket 3 design docs:** `docs/reports-page-design.md` (~400 lines, 7-PR plan) + `docs/tenancies-design.md` (~350 lines, 7-PR plan).
|
||||
> - **next-intl ripped out** — zero `useTranslations()` callers ever existed; the dependency, plugin wrap, request config, and `messages/en.json` are gone. `<html lang="en">` hardcoded.
|
||||
> - **RTL lint rule** — warn-only `no-restricted-syntax` on physical Tailwind utilities (`ml-/mr-/pl-/pr-/text-left/text-right/border-l/border-r/rounded-l-/rounded-r-`) inside `JSXAttribute[name='className']` literals across `src/components` + `src/app`. Existing 1,000+ sites grandfathered; new code trends toward logical (`ms-/me-/ps-/pe-/text-start/text-end/border-s/border-e/rounded-s-/rounded-e-`).
|
||||
> - **Currency labels via Intl.DisplayNames** — `SUPPORTED_CURRENCIES` no longer carries hardcoded English labels; new `currencyLabel(code, locale?)` helper resolves via `Intl.DisplayNames`. Two consumer sites migrated (`CurrencySelect`, `settings-manager`).
|
||||
> - **Date locale sweep** — 7 surfaces (`template-version-history`, `website-analytics/session-detail-sheet` + `sessions-list`, `signing-details-dialog` ×2, `reports-list` ×2) flipped from `toLocaleString('en-GB'|'en-US')` to `toLocaleString(undefined, …)` so dates honor the user's runtime locale.
|
||||
> - **Dialog/Sheet width bump** — document + EOI + entity-form dialogs all gain a `lg:max-w-4xl`/`lg:max-w-5xl` step so wide desktops get breathing room. Hit: `external-eoi-edit-dialog`, `signing-details-dialog`, `eoi-generate-dialog`, `external-eoi-upload-dialog`, `interest-form`, `client-form`, `yacht-form`, `company-form`, `form-template-form`, `template-form`.
|
||||
> - **PaymentsSection collapsed-bar** — slim one-line bar shows "Payments · Not received yet" or "Payments · $X received · N payments · Expand"; per-interest collapse state persisted in localStorage; auto-expands on a fresh deposit record.
|
||||
> - **muted-foreground opacity sweep** — text-bearing `text-muted-foreground/{60,70,80}` hits dropped to plain `text-muted-foreground` on `template-token-picker`, `admin-sections-browser`, `upload-receipts-guide`, `client-card`, `residential-interest-card`, `mobile-search-overlay`, `command-search` ×3, `aggregated-section`, `activity-feed`. Icon-only opacity hits (aria-hidden Lucide icons) left as-is.
|
||||
> - **Micro-type bump** — `text-[10px]` and `text-[11px]` swept to `text-xs` (12px) across 87 files in `src/components` + `src/app`. Pure mechanical replace; no behavioural change.
|
||||
> - **Icon-only button lint rule** — `jsx-a11y/control-has-associated-label` enabled (warn) with a sensible `controlComponents: ['Button']` config. Caught + fixed 4 empty `<th>`/`<td>` placeholders in bulk-add-berths-wizard, invitations-manager, berth-interests-tab via `sr-only` action labels.
|
||||
> - **EOI tab upload-draft parity** — confirmed already shipped: `documentTypeSchema` accepts `'eoi'` and `interest-eoi-tab.tsx:243` mounts the dialog.
|
||||
> - **EntityFolderView per-row interest badge** — confirmed already shipped (lines 116–118 render the badge + interest link).
|
||||
> - **Onboarding autoCheckResolver** — confirmed already working: the checklist hits `/api/v1/admin/settings/resolved?keys=...` which runs the port→global→env→default chain, and `smtp_host_override` / `documenso_api_url_override` / etc. have `envFallback` set on their registry entries. Steps auto-tick when a port relies on env config.
|
||||
> - **Global-search translucent bug** — defensive fix in `command-search.tsx:327` (`bg-white dark:bg-popover shadow-lg`) is solidly opaque; no parent has opacity/blend that would leak through. Closed.
|
||||
>
|
||||
> **Bucket 3 P1 foundations:**
|
||||
> **Marketing-site followups** parked separately in `docs/marketing-site-followups.md`:
|
||||
>
|
||||
> - Tenancies module-enabled gate (`tenancies_module_enabled` setting, `tenancies-module.service.ts`, 3 admin endpoints under `/api/v1/admin/tenancies-module/`).
|
||||
> - Reports schema migration 0084 (extends `report_templates` + adds `report_runs` + `report_schedules` tables) + matching Drizzle schema.
|
||||
> - Umami Phase 4a (marketing-site instrumentation), Phase 3/5 (events tab + funnels) — blocked on the other repo.
|
||||
> - Email pixel/tracked-link end-to-end verification with a real human inbox.
|
||||
> - Public berth endpoint + admin recipient UI for the website-to-CRM email cutover.
|
||||
>
|
||||
> **Bucket 3 Reports P2 (this session):** CRUD layer on `report_runs` + `report_schedules`. Validators (kind / output / cadence / status enums), services (`report-runs.service.ts`, `report-schedules.service.ts` with deterministic `nextRunFor` math), routes (`/api/v1/reports/runs` list+create + `/[id]` get, `/api/v1/reports/schedules` list+create + `/[id]` get+patch+delete). 9-case integration test covering cross-port FK guard, config.kind discriminator, listing filters, cadence math, no-op-doesn't-slip rule, and `ON DELETE SET NULL` contract on schedule deletion.
|
||||
> **Genuinely still-open (long-tail, low ROI):**
|
||||
>
|
||||
> **Bucket 4:** Sheet width sweep (Sheet primitive update covers every site). External-EOI dialog cache collision: dialog was caching `{data:…}` on the same key the parent unwraps, blanking the page on open — fix unwraps to match. External-EOI advance-gate regression test (7 cases). Search popover defensive opaque background. EntityFolderView visual overhaul: shared FileIcon mapping for type-specific colours + inline "Signed" pill from `signedFromDocumentId`.
|
||||
>
|
||||
> **Audit-cleanup callouts:** "dock-letters entity" (B2 Wave G item) was already shipped in `431375d` (D25). "Email-test endpoints" was already shipped (registry + endpoint + admin card all exist). "Cancel doc delete-vs-keep" was already shipped (cancelMode plumbed through `cancelDocument` + dialog adoption complete). These three were misclassified as queued.
|
||||
>
|
||||
> **Deferred / queued for follow-up sessions (~110 h):**
|
||||
>
|
||||
> - Reports P3-P7 (~31 h): BullMQ render+email queues + landing + builder + sub-pages + CSV/PNG outputs + metadata overrides.
|
||||
> - Tenancies P2-P7 (~36 h): rename migration + perms seed + webhook auto-create + public-map flip rules + sidebar entry + top-level page + entity tab CTAs + 4 reporting widgets.
|
||||
> - UploadForSigningDialog field metadata (full bundle, ~6-9 h): PlacedField.defaultValue + fieldMeta with per-type panel inputs + Documenso v2 `field/create-many` payload extension.
|
||||
> - B3 Wave remaining: bulk-price editing UI (~2-3 h — backend already shipped); Umami Phase 4a (marketing-site instrumentation, separate repo) + Phase 3/5 (events tab + funnels, blocked on 4a). _Shipped this session: B3-1 (interest dimensions dual-source). Shipped earlier in week: universal file preview Tier 1+2, all 16 PDF resolvers (incl. the 5 previously-tracked "remaining"), universal upload-with-fields backend + most UI sites._ Recharts→ECharts migration removed (rejected).\_
|
||||
> - B4 bugs: Global-search dropdown translucent still wants live-browser repro to confirm the defensive fix actually addressed the cause.
|
||||
> - **Sheet width on wide viewports** — bumped the document/EOI dialogs by one tier; if any specific dialog still feels narrow, name it.
|
||||
> - **Custom-field-form FieldLabel sweep** — primitive exists, registry-driven-form already surfaces descriptions inline (better discoverability than tooltip), custom-fields uses FieldLabel. Bespoke admin pages (~10–15 surfaces) still use plain `<Label>`; sweep is multi-hour and low impact since most admin settings have inline copy already.
|
||||
> - **Naive ternary pluralization** (`count === 1 ? 'X' : 'Xs'`) across 15+ surfaces — won't matter until a Polish/Arabic/Russian customer signs. Cost: ~1h after i18n strategy lands.
|
||||
> - **CSS logical properties full sweep** — lint rule added; existing 1,000+ sites grandfathered. Skip unless RTL customer is imminent.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user