Files
pn-new-crm/src/lib/route-labels.ts

52 lines
1.6 KiB
TypeScript
Raw Normal View History

feat(launch-readiness-batch): UAT drains, navigation refactor, launch infra, trackers Bundles the rest of the in-flight work from this UAT round into one checkpoint. Each sub-area is independent; see the headings below. UAT polish (drained 11 findings from active-uat.md): - Dialog primitive default bumped sm:max-w-xl/lg:max-w-3xl → sm:max-w-2xl/lg:max-w-4xl so multi-field forms + PDF previews aren't cramped at 1440-1920px. - Notes tab badge aggregation: new countFor{Client,Yacht,Company} Aggregated helpers in notes.service mirror the listFor*Aggregated symmetric-reach joins. yacht-tabs + company-tabs render the badge; client-tabs already had badge support. - Supplemental-info form polish bundle: BrandedAuthShell gains a `width: 'sm' | 'md'` prop (md uses min-h-dvh scroll instead of fixed inset-0 pin so long forms scroll naturally). Form picks up port branding (logoUrl + backgroundUrl + appName) via loadByToken. Address fields completed (street + city + region + postal + country). Port name eyebrow + success-state copy added. - new-document-menu Upload-file landing toast: per-file completion emits toast.success with action link to the destination entity or folder. - interest-tabs OverviewTab "from client" pill on Email + Phone rows via new EditableRow `inheritedFrom` prop. - create-document-wizard subject picker → segmented button strip (5 types visible at once). Launch infra: - UTM column wiring (Init 1b step 4): migration 0089_website_submissions_utm.sql adds utm_source/medium/campaign/ term/content + composite index (port_id, utm_source, received_at) for per-campaign rollups. website-inquiries intake accepts the five fields. Residential intake intentionally untouched per audit scope. - Invoicing module gate (Init 1c spike): new invoices-module.service + invoices layout guard + registry entry invoices_module_enabled (default false). Audit conclusion in launch-readiness.md: payments table is canonical money path; /invoices flow is parallel infrastructure now hidden by default. Smart-back navigation refactor: - Replaced breadcrumb component with history-aware Back button. New route-labels.ts + use-smart-back hook + navigation-history-tracker so back falls through to the parent route when there's no prior page in history. - Sidebar / topbar / mobile-topbar adopt the new pattern; old breadcrumb-store kept for back-compat consumers but the breadcrumbs component is gone. - 6 detail pages (admin/errors per-id + codes, invoices/ upload-receipts, reports kind, tenancies detail, analytics metric, client detail) migrated. Trackers + docs: - docs/launch-readiness.md — master pre-launch tracker. Includes the reports gap audit (cross-cutting filter set, Marketing + Financial blockers, custom builder remaining entities, scheduled CSV/XLSX, template scope picker). - docs/superpowers/audits/active-uat.md — 15 findings flipped OPEN → SHIPPED locally with fix-applied notes; 4 OPEN remaining (each blocked on user input or cross-repo). - CLAUDE.md — minor session notes carried forward. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 22:42:37 +02:00
/**
* Canonical human-readable labels for URL path segments. Used by the smart
* back button to derive a sensible "Back to <X>" label from the URL when a
* detail page hasn't registered an explicit back-context hint, and by the
* mobile topbar's title fallback.
*
* Add new top-level routes here so the back button doesn't fall through to
* a slugified guess (e.g. "berths" -> "Berths" works automatically via
* `formatSegment`, but "audit" would render as "Audit" instead of "Audit Log"
* without the explicit entry).
*/
export const SEGMENT_LABELS: Record<string, string> = {
dashboard: 'Dashboard',
clients: 'Clients',
yachts: 'Yachts',
companies: 'Companies',
interests: 'Interests',
berths: 'Berths',
documents: 'Documents',
files: 'Files',
expenses: 'Expenses',
invoices: 'Invoices',
email: 'Email',
inbox: 'Inbox',
reminders: 'Reminders',
alerts: 'Alerts',
settings: 'Settings',
admin: 'Administration',
reports: 'Reports',
tenancies: 'Tenancies',
residential: 'Residential',
new: 'New',
edit: 'Edit',
profile: 'Profile',
notifications: 'Notifications',
'website-analytics': 'Website Analytics',
};
/** UUID v4-ish (or any 36-char hex+dash) - used to skip entity-id segments
* from URL-derived labels since they're never human-readable. */
export const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
export function isIdSegment(segment: string): boolean {
return UUID_RE.test(segment);
}
export function formatSegment(segment: string): string {
return (
SEGMENT_LABELS[segment] ?? segment.replace(/-/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase())
);
}