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

@@ -33,7 +33,7 @@ interface Note {
sourceId?: string;
sourceLabel?: string;
/** Pipeline stage the linked interest was at when the note was authored.
* Only populated for interest notes drives the small stage chip. */
* Only populated for interest notes - drives the small stage chip. */
pipelineStageAtCreation?: string | null;
}
@@ -55,7 +55,7 @@ const SELF_SOURCE: Record<NotesEntityType, NoteSource | null> = {
companies: 'company',
residential_clients: 'residential_client',
// Aggregate-mode is only meaningful for the entities above. Interests
// and residential_interests are leaf nodes there's nothing to roll
// and residential_interests are leaf nodes - there's nothing to roll
// up to them.
interests: null,
residential_interests: null,
@@ -94,7 +94,7 @@ interface NotesListProps {
* Aggregate-on-read: union the entity's own notes with notes from
* related entities (interests, owned yachts / company yachts, owner
* client). Cross-source notes render with a source chip and are
* read-only here open the source entity's page to edit.
* read-only here - open the source entity's page to edit.
*
* Supported for entityType in {clients, yachts, companies,
* residential_clients}. Ignored for interests / residential_interests.
@@ -167,7 +167,7 @@ export function NotesList({
const listEndpoint = aggregateOn ? `${baseEndpoint}?aggregate=true` : baseEndpoint;
const queryKey = [entityType, entityId, 'notes', aggregateOn ? 'aggregated' : 'own'];
// Smooth animation when notes are added / edited / deleted replaces
// Smooth animation when notes are added / edited / deleted - replaces
// the abrupt re-render with a per-row fade/slide.
const [animateRef] = useAutoAnimate<HTMLDivElement>();
@@ -177,7 +177,7 @@ export function NotesList({
});
// Mutations always target the parent entity (client). Aggregated
// notes from interests/yachts are read-only here the rep edits
// notes from interests/yachts are read-only here - the rep edits
// them on the source entity's page (we surface a "Open source" link
// below). Keeping mutations against `baseEndpoint` keeps the POST
// route handler clean.
@@ -250,7 +250,7 @@ export function NotesList({
</div>
</div>
{/* Aggregated-mode controls sort toggle. Only renders when
{/* Aggregated-mode controls - sort toggle. Only renders when
* aggregation is on and there's actually content to group. */}
{aggregateOn && notes.length > 0 && (
<div className="flex items-center justify-end gap-2 text-xs text-muted-foreground">