chore(style): codebase em-dash sweep + minor layout polish
Some checks failed
Build & Push Docker Images / lint (push) Failing after 1m18s
Build & Push Docker Images / build-and-push (push) Has been skipped

Replaces every em-dash and en-dash with regular ASCII hyphens
across comments, JSX strings, and dev-facing logs. Mostly cosmetic
but stops the inconsistent mix that crept in over the last few
months (some files used em-dashes in comments, others didn't,
some used both).

Bundles two small dashboard-layout tweaks that touch a couple of
already-modified files:
- (dashboard)/layout.tsx main padding goes from p-6 to pt-3 px-6
  pb-6 so page content sits closer to the topbar.
- Sidebar now receives the ports list it needs for the footer
  port switcher.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matt Ciaccio
2026-05-04 22:57:01 +02:00
parent d62822c284
commit 8699f81879
225 changed files with 844 additions and 845 deletions

View File

@@ -237,7 +237,7 @@ export async function resolveTemplate(
tokenMap['{{client.phone}}'] = eoi.client.primaryPhone ?? '';
tokenMap['{{client.nationality}}'] = eoi.client.nationality ?? '';
// Yacht tokens `eoi.yacht` is null when no yacht is linked
// Yacht tokens - `eoi.yacht` is null when no yacht is linked
// (Section 3 of the EOI is optional). Tokens render as empty strings
// in that case so the template still produces output.
tokenMap['{{yacht.name}}'] = eoi.yacht?.name ?? '';
@@ -252,7 +252,7 @@ export async function resolveTemplate(
tokenMap['{{yacht.widthM}}'] = eoi.yacht?.widthM ?? '';
tokenMap['{{yacht.draftM}}'] = eoi.yacht?.draftM ?? '';
// EoiContext doesn't expose the yacht.registration column look it up
// EoiContext doesn't expose the yacht.registration column - look it up
// separately (cheap, indexed fetch) so the token resolves when present.
try {
const interestRow = await db.query.interests.findFirst({
@@ -283,7 +283,7 @@ export async function resolveTemplate(
tokenMap['{{owner.name}}'] = eoi.owner.name;
tokenMap['{{owner.legalName}}'] = eoi.owner.legalName ?? '';
// Berth tokens also optional. Render empty when no berth is linked.
// Berth tokens - also optional. Render empty when no berth is linked.
tokenMap['{{berth.mooringNumber}}'] = eoi.berth?.mooringNumber ?? '';
tokenMap['{{berth.area}}'] = eoi.berth?.area ?? '';
tokenMap['{{berth.lengthFt}}'] = eoi.berth?.lengthFt ?? '';
@@ -301,9 +301,9 @@ export async function resolveTemplate(
tokenMap['{{interest.notes}}'] = eoi.interest.notes ?? '';
} catch (err) {
// buildEoiContext throws ValidationError when the EOI's required client
// fields (name/email/address Section 2) are missing. For non-EOI
// fields (name/email/address - Section 2) are missing. For non-EOI
// templates (correspondence, welcome letters, etc.) those gates don't
// apply fall through to the legacy resolution path below. Re-throw
// apply - fall through to the legacy resolution path below. Re-throw
// anything else.
if (
!(err instanceof ValidationError) ||
@@ -323,7 +323,7 @@ export async function resolveTemplate(
where: eq(clients.id, context.clientId),
});
if (client && client.portId === context.portId) {
// Always resolve source from the DB EoiContext doesn't carry it.
// Always resolve source from the DB - EoiContext doesn't carry it.
if (tokenMap['{{client.source}}'] === undefined) {
tokenMap['{{client.source}}'] = client.source ?? '';
}
@@ -349,7 +349,7 @@ export async function resolveTemplate(
}
}
// Interest tokens (legacy path fills in fields EoiContext doesn't expose,
// Interest tokens (legacy path - fills in fields EoiContext doesn't expose,
// like eoiStatus / dateEoiSigned / dateContractSigned, or populates the
// whole interest.* block when EOI resolution was skipped).
if (context.interestId) {
@@ -365,7 +365,7 @@ export async function resolveTemplate(
: '';
tokenMap['{{interest.notes}}'] = interest.notes ?? '';
}
// These are never populated by EoiContext always fill them in.
// These are never populated by EoiContext - always fill them in.
tokenMap['{{interest.eoiStatus}}'] = interest.eoiStatus ?? '';
tokenMap['{{interest.dateEoiSigned}}'] = interest.dateEoiSigned
? new Date(interest.dateEoiSigned).toLocaleDateString('en-GB')
@@ -395,7 +395,7 @@ export async function resolveTemplate(
}
}
// Berth tokens (legacy path when a berthId is passed directly and EOI
// Berth tokens (legacy path - when a berthId is passed directly and EOI
// resolution didn't already populate the berth block).
if (context.berthId && !eoiContextLoaded) {
const berth = await db.query.berths.findFirst({
@@ -507,7 +507,7 @@ export async function generateFromTemplate(
const pdfBytes = await generatePdf(pdfTemplate, [
{
portName: `${port?.name ?? 'Port Nimara'} ${template.name}`,
portName: `${port?.name ?? 'Port Nimara'} - ${template.name}`,
body: wrappedContent,
generatedAt: `Generated: ${new Date().toLocaleString('en-GB')}`,
},
@@ -610,7 +610,7 @@ export async function generateAndSend(
);
} catch (err) {
logger.error({ err, templateId, recipientEmail }, 'Failed to send template email');
// Don't throw document was created successfully; email failure is non-fatal
// Don't throw - document was created successfully; email failure is non-fatal
}
void createAuditLog({
@@ -631,7 +631,7 @@ export async function generateAndSend(
/**
* BR-142: For EOI templates, the in-app pathway uses the same source PDF as
* the Documenso template filled via pdf-lib with values from EoiContext.
* the Documenso template - filled via pdf-lib with values from EoiContext.
* Same field names, same legal document; the only difference is who renders
* it. The form is left interactive so a recipient can adjust before signing.
*/
@@ -893,7 +893,7 @@ async function generateAndSignViaDocumensoTemplate(
payload as unknown as Record<string, unknown>,
);
// Record a documents row referencing the Documenso document. No local file
// Record a documents row referencing the Documenso document. No local file -
// Documenso owns the PDF and delivers signed copies via webhook (handled elsewhere).
const [documentRecord] = await db
.insert(documents)