chore(autonomous-session): consolidate uncommitted work from prior session

Bundles the prior autonomous-session output that was sitting unstaged:

- Em-dash sweep across src/ + tests/ (en-dash/em-dash to hyphen, ~2280 instances)
- country-flag-icons rollout (CountryFlag component, replaces emoji glyphs that
  never rendered on Windows; lazy-loads the 3x2 SVG index as a single chunk
  after the per-subpath dynamic-import approach silently failed in webpack)
- Admin IA Phase 1+2: 7-domain regroup, 41 to 38 pages, /admin/berths index,
  redirects (ocr to ai, reports to dashboard, invitations to users),
  docs/admin-ia-proposal.md
- Per-template email tester (registry + endpoint + UI on Email admin page)
- Cancel-document mode picker (delete-from-Documenso vs keep-for-audit)
- Dashboard PDF report: 25 widgets, SVG charts, date-range picker, 11 resolvers
- Customize-widgets per-region sortables at xl+ (charts/rails/feed); single
  flat sortable below xl when the layout stacks; per-viewport saved orders
- Audit doc updates capturing each shipped item
- Lint fixes: react-compiler immutability in DonutChart (reduce instead of
  let-reassign), set-state-in-effect disables in CountryFlag and
  UploadForSigning preview-bytes effect, unused 'confirm' destructures in
  interest contract + reservation tabs, unescaped apostrophe in test-template
  card copy
This commit is contained in:
2026-05-23 00:52:59 +02:00
parent 43719b49e9
commit 221ae5784e
749 changed files with 7440 additions and 3118 deletions

View File

@@ -0,0 +1,88 @@
import Link from 'next/link';
import type { Route } from 'next';
import { AlertCircle, Anchor, FileSearch } from 'lucide-react';
import { PageHeader } from '@/components/shared/page-header';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
/**
* Berths admin index. Both sub-pages (`bulk-add`, `reconcile`) existed
* pre-2026-05-22 but were only reachable via deep links from inside the
* Berths list. Surfacing them on a dedicated admin landing tile so the
* tools are discoverable without prior knowledge of the URL - part of
* the admin IA regroup (B3 #10 Phase 2).
*/
export default async function BerthsAdminIndex({
params,
}: {
params: Promise<{ portSlug: string }>;
}) {
const { portSlug } = await params;
const tools = [
{
href: `/${portSlug}/admin/berths/bulk-add` as Route,
label: 'Bulk add berths',
description:
'Generate many berth rows in one wizard - set pier, prefix, mooring number range, and per-berth defaults; preview before commit.',
icon: Anchor,
},
{
href: `/${portSlug}/admin/berths/reconcile` as Route,
label: 'Reconciliation queue',
description:
"Berths missing required fields after import / PDF parse. Surface what's missing per row and link straight to the edit sheet.",
icon: FileSearch,
},
] as const;
return (
<div className="space-y-6">
<PageHeader
title="Berths admin"
eyebrow="ADMIN"
description="Tools for bulk berth creation and post-import reconciliation. Single-berth edits stay on the Berths list - these surfaces are for batch operations."
/>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
{tools.map((t) => {
const Icon = t.icon;
return (
<Link key={t.href} href={t.href} className="block group">
<Card className="h-full transition-colors group-hover:border-primary/50 group-hover:bg-muted/30">
<CardHeader className="flex flex-row items-start gap-3 space-y-0 pb-2">
<Icon
className="h-5 w-5 mt-0.5 text-muted-foreground group-hover:text-primary"
aria-hidden
/>
<CardTitle className="text-base">{t.label}</CardTitle>
</CardHeader>
<CardContent>
<CardDescription>{t.description}</CardDescription>
</CardContent>
</Card>
</Link>
);
})}
</div>
<Card className="border-amber-200 bg-amber-50/50">
<CardHeader className="flex flex-row items-start gap-3 space-y-0 pb-2">
<AlertCircle className="h-5 w-5 mt-0.5 text-amber-600" aria-hidden />
<CardTitle className="text-sm">Not what you&apos;re looking for?</CardTitle>
</CardHeader>
<CardContent>
<CardDescription className="text-xs">
For single-berth edits, browse to the{' '}
<Link
href={`/${portSlug}/berths` as Route}
className="font-medium text-primary hover:underline"
>
Berths list
</Link>{' '}
and click any row. Per-berth PDF uploads + brochure assignment also live there.
</CardDescription>
</CardContent>
</Card>
</div>
);
}