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

@@ -57,7 +57,7 @@ export async function loadEoiTemplatePdf(): Promise<Uint8Array> {
if (actual !== EXPECTED_EOI_SHA256) {
logger.warn(
{ expected: EXPECTED_EOI_SHA256, actual },
'EOI source PDF sha256 mismatch template was modified without an EXPECTED_EOI_SHA256 bump. Update assets/README.md + EXPECTED_EOI_SHA256 in lockstep if this was intentional.',
'EOI source PDF sha256 mismatch - template was modified without an EXPECTED_EOI_SHA256 bump. Update assets/README.md + EXPECTED_EOI_SHA256 in lockstep if this was intentional.',
);
}
}
@@ -70,7 +70,7 @@ function formatAddress(address: EoiContext['client']['address']): string {
// EOI's Address field renders as: "street, city, REGION, postal, COUNTRY"
// with REGION as the ISO-3166-2 suffix (e.g. NY) and COUNTRY as the
// alpha-2 code (e.g. US) so the line fits in the PDF box. The separate
// `Nationality` PDF field has been retired the resident's country code
// `Nationality` PDF field has been retired - the resident's country code
// here is the canonical replacement.
return [address.street, address.city, address.subdivision, address.postalCode, address.countryIso]
.filter(Boolean)
@@ -90,7 +90,7 @@ function setText(form: ReturnType<PDFDocument['getForm']>, name: string, value:
if (value && value.trim().length > 0) {
logger.warn(
{ field: name },
`EOI in-app PDF template is missing AcroForm field "${name}" value was dropped. Update the source template.`,
`EOI in-app PDF template is missing AcroForm field "${name}" - value was dropped. Update the source template.`,
);
}
}
@@ -108,7 +108,7 @@ function setCheckbox(
} catch {
logger.warn(
{ field: name, checked },
`EOI in-app PDF template is missing checkbox AcroForm field "${name}" checkbox state was dropped. Update the source template.`,
`EOI in-app PDF template is missing checkbox AcroForm field "${name}" - checkbox state was dropped. Update the source template.`,
);
}
}
@@ -144,7 +144,7 @@ export async function fillEoiFormFields(
const yWid = dimUnit === 'ft' ? context.yacht?.widthFt : context.yacht?.widthM;
const yDra = dimUnit === 'ft' ? context.yacht?.draftFt : context.yacht?.draftM;
// Append the unit suffix so the rendered EOI reads "45 ft" / "13.7 m"
// rather than the bare number matches the Documenso pathway.
// rather than the bare number - matches the Documenso pathway.
const withDimUnit = (v: string | null | undefined): string =>
v && String(v).trim() ? `${String(v).trim()} ${dimUnit}` : '';
setText(form, 'Length', withDimUnit(yLen));
@@ -153,7 +153,7 @@ export async function fillEoiFormFields(
// Berth Number = compact range for multi-berth, primary mooring for
// single-berth (formatBerthRange(['A1']) === 'A1' so single-berth is
// byte-identical to the legacy primary-only path). The dedicated
// `Berth Range` AcroForm field was retired 2026-05-14 the source
// `Berth Range` AcroForm field was retired 2026-05-14 - the source
// PDF only carries `Berth Number`.
setText(form, 'Berth Number', context.eoiBerthRange || (context.berth?.mooringNumber ?? ''));