feat(mobile): swap admin page headers to PageHeader
Mechanical sweep replacing the plain h1+p header markup with the
mobile-aware PageHeader primitive across 12 admin pages: index,
backup, branding, documenso, email, import, invitations, monitoring,
onboarding, reminders, reports, webhooks. Webhooks "Add Webhook"
button preserved via the actions slot.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 12:57:52 +02:00
|
|
|
import { PageHeader } from '@/components/shared/page-header';
|
2026-05-12 16:14:12 +02:00
|
|
|
import { AdminSectionsBrowser } from '@/components/admin/admin-sections-browser';
|
feat(admin): per-port email/Documenso/branding/reminder settings + invitations
Centralizes everything operators need to configure into the admin panel,
each setting per-port with env fallback.
New admin pages
- /admin landing page linking to every admin section as a card
- /admin/email FROM name+address, reply-to, signature/footer HTML,
optional SMTP host/port/user/pass override
- /admin/documenso API URL+key override, EOI Documenso template ID,
default EOI pathway (documenso-template vs inapp),
"Test connection" button
- /admin/branding logo URL, primary color, app name, email
header/footer HTML
- /admin/reminders port-level defaults for new interests +
port-wide daily-digest delivery window
- /admin/invitations send / list / resend / revoke CRM invitations
Per-user reminder digest
- /notifications/preferences gains a Reminder digest card:
immediate / daily / weekly / off, with HH:MM, day-of-week,
IANA timezone fields. Stored in user_profiles.preferences.reminders.
Plumbing
- port-config.ts typed accessors (getPortEmailConfig, getPortDocumensoConfig,
getPortBrandingConfig, getPortReminderConfig) — settings → env fallback.
- sendEmail accepts optional portId; resolves From/SMTP from settings
when supplied.
- documensoFetch + downloadSignedPdf accept optional portId; each public
function takes it through. checkDocumensoHealth() backs the test button.
- crm-invite.service gains listCrmInvites / revokeCrmInvite / resendCrmInvite
with audit-log entries (revoke_invite, resend_invite added to AuditAction).
- AdminLandingPage card grid + shared SettingsFormCard component to remove
per-page form boilerplate.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 23:21:54 +02:00
|
|
|
|
|
|
|
|
export default async function AdminLandingPage({
|
|
|
|
|
params,
|
|
|
|
|
}: {
|
|
|
|
|
params: Promise<{ portSlug: string }>;
|
|
|
|
|
}) {
|
|
|
|
|
const { portSlug } = await params;
|
|
|
|
|
return (
|
fix(ux): pass-2 audit fixes — admin grouping, Duplicates entry, header tooltips
Three small but high-leverage fixes from the second audit pass on main:
Admin index (src/app/(dashboard)/[portSlug]/admin/page.tsx):
- Grouped 21 sections into 7 categories: Access, Configuration, Content,
Data Quality, Operations, Tenancy, Integrations. Each group has a
one-line description so first-time admins can orient themselves
without reading every card.
- Added the missing Duplicates entry (links to /admin/duplicates from
the dedup-migration work) under Data Quality.
More sheet (mobile bottom-drawer nav):
- "Email" -> "Inbox". The page that opens is an email-inbox surface
(Inbox + Accounts tabs), not a generic email composer. The previous
label was ambiguous.
Interest detail header (Won / Lost outcome buttons):
- Added title="Mark as won" / "Close as lost" so the icon-only buttons
on mobile have a tooltip on long-press / desktop hover.
- Tightened mobile padding (px-2 vs px-2.5) so the full-text desktop
labels still fit on sm+ without re-introducing a regression where a
visible mobile "Won"/"Lost" inline label crowded the right cluster
enough to push Email/Call/WhatsApp action chips into a vertical
stack.
Verification: 0 tsc errors, 926/926 vitest passing, lint clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 16:35:32 +02:00
|
|
|
<div className="space-y-8">
|
feat(mobile): swap admin page headers to PageHeader
Mechanical sweep replacing the plain h1+p header markup with the
mobile-aware PageHeader primitive across 12 admin pages: index,
backup, branding, documenso, email, import, invitations, monitoring,
onboarding, reminders, reports, webhooks. Webhooks "Add Webhook"
button preserved via the actions slot.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 12:57:52 +02:00
|
|
|
<PageHeader
|
|
|
|
|
title="Administration"
|
feat: round 2 — stage prompts, berth header, EOI inline edit, measurement units
Berth surfaces
- New compact mooring-chip header (colored plate + status pill, dock-label
in tooltip) replaces the redundant "Berth B1 / Sold / B DOCK" stack
- Berth list gains a "Latest deal stage" column showing the most-advanced
pipeline stage of any active linked interest (server-aggregated, ranks by
PIPELINE_STAGES index)
- "Linked prospect" Select on the status-change dialog rebuilt as a Command
combobox: search, recent-first sort, stage-coloured pills
Pipeline UX
- Reverting an interest to Open with linked berths now prompts: keep the
links, unlink and reset, or cancel. Silent when no berths are linked
- Activity feed + entity-activity feed normalise enum field values via
STAGE_LABELS / formatSource: "deposit_10pct → contract_sent" reads as
"10% Deposit → Contract Sent"
EOI generate dialog
- Inline-editable rows for client name, nationality (country combobox), and
yacht name — pencil affordance saves directly via clients/yachts PATCH
- Replaces the single "Edit on client's page" link with two contextual links
framed by short copy explaining what's inline vs what needs the canonical
page
- Backend EoiContext now includes client.id + yacht.id so the dialog can
PATCH without an extra round-trip
Company form
- New "Connections" section lets the rep attach members (clients) and yachts
during create. Yacht attach uses the existing transfer endpoint so audit
log + ownership history capture the change
- Inline "+ New client" / "+ New yacht" buttons open the canonical forms
stacked over the company sheet
- After save, the form chains to a yacht pull-in prompt (if any attached
client owns yachts not yet linked) and an optional "Create interest" step
pre-filled with the first attached client
Admin
- /admin landing gains a searchable index — typed query flattens groups into
a result list matching label + description + group title
- "Documenso & EOI" card relabelled to "EOI signing service" (consistent
with the user-facing language rename from round 1)
Measurement units (migration 0053)
- interests gains desired_*_m columns + desired_*_unit discriminators so
the rep's literal entry (ft OR m) is preserved verbatim instead of being
reconstructed from a single canonical column on every render
- yachts + berths gain matching *_unit columns alongside their existing
ft + m pairs; defaults to 'ft' so legacy rows still render normally
- Interest form POST/PATCH now sends both ft + m + unit; computed m is
derived from the ft canonical to keep the recommender SQL unchanged
Misc
- Active-deals tile + topbar type their Link href as `Route` instead of `any`
- Unused REPORT_TYPE_LABELS const dropped from generate-report-form
- Test fixtures (fill-eoi-form, documenso-payload, public-berths) updated
to include the new id + unit fields on the EoiContext / Berth shapes
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 15:28:22 +02:00
|
|
|
description="Per-port configuration and system administration. Use the search to jump to a setting, or browse the grouped index below."
|
feat(mobile): swap admin page headers to PageHeader
Mechanical sweep replacing the plain h1+p header markup with the
mobile-aware PageHeader primitive across 12 admin pages: index,
backup, branding, documenso, email, import, invitations, monitoring,
onboarding, reminders, reports, webhooks. Webhooks "Add Webhook"
button preserved via the actions slot.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 12:57:52 +02:00
|
|
|
/>
|
2026-05-12 16:14:12 +02:00
|
|
|
<AdminSectionsBrowser portSlug={portSlug} />
|
feat(admin): per-port email/Documenso/branding/reminder settings + invitations
Centralizes everything operators need to configure into the admin panel,
each setting per-port with env fallback.
New admin pages
- /admin landing page linking to every admin section as a card
- /admin/email FROM name+address, reply-to, signature/footer HTML,
optional SMTP host/port/user/pass override
- /admin/documenso API URL+key override, EOI Documenso template ID,
default EOI pathway (documenso-template vs inapp),
"Test connection" button
- /admin/branding logo URL, primary color, app name, email
header/footer HTML
- /admin/reminders port-level defaults for new interests +
port-wide daily-digest delivery window
- /admin/invitations send / list / resend / revoke CRM invitations
Per-user reminder digest
- /notifications/preferences gains a Reminder digest card:
immediate / daily / weekly / off, with HH:MM, day-of-week,
IANA timezone fields. Stored in user_profiles.preferences.reminders.
Plumbing
- port-config.ts typed accessors (getPortEmailConfig, getPortDocumensoConfig,
getPortBrandingConfig, getPortReminderConfig) — settings → env fallback.
- sendEmail accepts optional portId; resolves From/SMTP from settings
when supplied.
- documensoFetch + downloadSignedPdf accept optional portId; each public
function takes it through. checkDocumensoHealth() backs the test button.
- crm-invite.service gains listCrmInvites / revokeCrmInvite / resendCrmInvite
with audit-log entries (revoke_invite, resend_invite added to AuditAction).
- AdminLandingPage card grid + shared SettingsFormCard component to remove
per-page form boilerplate.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 23:21:54 +02:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|