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

@@ -42,7 +42,7 @@ function setText(form: ReturnType<PDFDocument['getForm']>, name: string, value:
try {
form.getTextField(name).setText(value);
} catch {
// Field absent or wrong type skip silently so a slightly different PDF
// Field absent or wrong type - skip silently so a slightly different PDF
// template still produces output. Missing field issues surface in QA, not
// at runtime as a 500.
}
@@ -80,7 +80,7 @@ export async function fillEoiFormFields(
setText(form, 'Name', context.client.fullName);
setText(form, 'Email', context.client.primaryEmail ?? '');
setText(form, 'Address', formatAddress(context.client.address));
// Yacht + berth (EOI Section 3) are optional leave the AcroForm fields
// Yacht + berth (EOI Section 3) are optional - leave the AcroForm fields
// blank when the interest hasn't been linked to either.
setText(form, 'Yacht Name', context.yacht?.name ?? '');
setText(form, 'Length', context.yacht?.lengthFt ?? '');

View File

@@ -4,16 +4,86 @@ export const berthSpecTemplate: Template = {
basePdf: 'BLANK_PDF' as unknown as string,
schemas: [
[
{ name: 'portName', type: 'text', position: { x: 20, y: 15 }, width: 100, height: 10, fontSize: 16 },
{ name: 'title', type: 'text', position: { x: 20, y: 30 }, width: 170, height: 8, fontSize: 14 },
{ name: 'berthInfo', type: 'text', position: { x: 20, y: 45 }, width: 80, height: 25, fontSize: 9 },
{ name: 'dimensions', type: 'text', position: { x: 110, y: 45 }, width: 80, height: 25, fontSize: 9 },
{ name: 'pricing', type: 'text', position: { x: 20, y: 75 }, width: 80, height: 20, fontSize: 9 },
{ name: 'tenure', type: 'text', position: { x: 110, y: 75 }, width: 80, height: 20, fontSize: 9 },
{ name: 'infrastructure', type: 'text', position: { x: 20, y: 100 }, width: 170, height: 25, fontSize: 9 },
{ name: 'waitingList', type: 'text', position: { x: 20, y: 130 }, width: 170, height: 50, fontSize: 8 },
{ name: 'maintenanceLog', type: 'text', position: { x: 20, y: 185 }, width: 170, height: 75, fontSize: 8 },
{ name: 'generatedAt', type: 'text', position: { x: 20, y: 275 }, width: 170, height: 6, fontSize: 7 },
{
name: 'portName',
type: 'text',
position: { x: 20, y: 15 },
width: 100,
height: 10,
fontSize: 16,
},
{
name: 'title',
type: 'text',
position: { x: 20, y: 30 },
width: 170,
height: 8,
fontSize: 14,
},
{
name: 'berthInfo',
type: 'text',
position: { x: 20, y: 45 },
width: 80,
height: 25,
fontSize: 9,
},
{
name: 'dimensions',
type: 'text',
position: { x: 110, y: 45 },
width: 80,
height: 25,
fontSize: 9,
},
{
name: 'pricing',
type: 'text',
position: { x: 20, y: 75 },
width: 80,
height: 20,
fontSize: 9,
},
{
name: 'tenure',
type: 'text',
position: { x: 110, y: 75 },
width: 80,
height: 20,
fontSize: 9,
},
{
name: 'infrastructure',
type: 'text',
position: { x: 20, y: 100 },
width: 170,
height: 25,
fontSize: 9,
},
{
name: 'waitingList',
type: 'text',
position: { x: 20, y: 130 },
width: 170,
height: 50,
fontSize: 8,
},
{
name: 'maintenanceLog',
type: 'text',
position: { x: 20, y: 185 },
width: 170,
height: 75,
fontSize: 8,
},
{
name: 'generatedAt',
type: 'text',
position: { x: 20, y: 275 },
width: 170,
height: 6,
fontSize: 7,
},
],
],
};
@@ -35,22 +105,23 @@ export function buildBerthSpecInputs(
.filter(Boolean)
.join('\n');
const dimensions = [
berth.lengthFt
? `Length: ${berth.lengthFt}ft${berth.lengthM ? ` / ${berth.lengthM}m` : ''}`
: null,
berth.widthFt
? `Beam: ${berth.widthFt}ft${berth.widthM ? ` / ${berth.widthM}m` : ''}${berth.widthIsMinimum ? ' (min)' : ''}`
: null,
berth.draftFt
? `Draft: ${berth.draftFt}ft${berth.draftM ? ` / ${berth.draftM}m` : ''}`
: null,
berth.waterDepth
? `Water depth: ${berth.waterDepth}ft${berth.waterDepthM ? ` / ${berth.waterDepthM}m` : ''}${berth.waterDepthIsMinimum ? ' (min)' : ''}`
: null,
]
.filter(Boolean)
.join('\n') || 'Dimensions not specified';
const dimensions =
[
berth.lengthFt
? `Length: ${berth.lengthFt}ft${berth.lengthM ? ` / ${berth.lengthM}m` : ''}`
: null,
berth.widthFt
? `Beam: ${berth.widthFt}ft${berth.widthM ? ` / ${berth.widthM}m` : ''}${berth.widthIsMinimum ? ' (min)' : ''}`
: null,
berth.draftFt
? `Draft: ${berth.draftFt}ft${berth.draftM ? ` / ${berth.draftM}m` : ''}`
: null,
berth.waterDepth
? `Water depth: ${berth.waterDepth}ft${berth.waterDepthM ? ` / ${berth.waterDepthM}m` : ''}${berth.waterDepthIsMinimum ? ' (min)' : ''}`
: null,
]
.filter(Boolean)
.join('\n') || 'Dimensions not specified';
const pricing = berth.price
? `Price: ${berth.priceCurrency ?? 'USD'} ${Number(berth.price).toLocaleString()}`
@@ -65,25 +136,30 @@ export function buildBerthSpecInputs(
.filter(Boolean)
.join('\n');
const infrastructure = [
berth.mooringType ? `Mooring type: ${berth.mooringType}` : null,
berth.powerCapacity ? `Power: ${berth.powerCapacity}${berth.voltage ? ` / ${berth.voltage}V` : ''}` : null,
berth.cleatType ? `Cleat: ${berth.cleatType}${berth.cleatCapacity ? ` (${berth.cleatCapacity})` : ''}` : null,
berth.bollardType
? `Bollard: ${berth.bollardType}${berth.bollardCapacity ? ` (${berth.bollardCapacity})` : ''}`
: null,
berth.sidePontoon ? `Side pontoon: ${berth.sidePontoon}` : null,
berth.access ? `Access: ${berth.access}` : null,
]
.filter(Boolean)
.join(' | ') || 'Infrastructure details not specified';
const infrastructure =
[
berth.mooringType ? `Mooring type: ${berth.mooringType}` : null,
berth.powerCapacity
? `Power: ${berth.powerCapacity}${berth.voltage ? ` / ${berth.voltage}V` : ''}`
: null,
berth.cleatType
? `Cleat: ${berth.cleatType}${berth.cleatCapacity ? ` (${berth.cleatCapacity})` : ''}`
: null,
berth.bollardType
? `Bollard: ${berth.bollardType}${berth.bollardCapacity ? ` (${berth.bollardCapacity})` : ''}`
: null,
berth.sidePontoon ? `Side pontoon: ${berth.sidePontoon}` : null,
berth.access ? `Access: ${berth.access}` : null,
]
.filter(Boolean)
.join(' | ') || 'Infrastructure details not specified';
const waitingListText =
waitingList.length > 0
? waitingList
.map(
(w) =>
`${w.position}. ${w.clientName ?? 'Unknown'}${w.priority === 'high' ? ' [HIGH]' : ''}${w.notes ? ` ${w.notes}` : ''}`,
`${w.position}. ${w.clientName ?? 'Unknown'}${w.priority === 'high' ? ' [HIGH]' : ''}${w.notes ? ` - ${w.notes}` : ''}`,
)
.join('\n')
: 'No clients on waiting list';
@@ -100,7 +176,7 @@ export function buildBerthSpecInputs(
return {
portName: (port?.name as string) ?? 'Port Nimara',
title: `Berth Specification Mooring ${berth.mooringNumber}`,
title: `Berth Specification - Mooring ${berth.mooringNumber}`,
berthInfo,
dimensions,
pricing,

View File

@@ -130,7 +130,7 @@ export function buildClientSummaryInputs(
? interestList
.map(
(i) =>
`${i.pipelineStage ?? 'open'}${i.berthMooringNumber ? ` Berth ${i.berthMooringNumber}` : ''}${i.leadCategory ? ` [${i.leadCategory}]` : ''} (${new Date(i.createdAt as string | Date).toLocaleDateString('en-GB')})`,
`${i.pipelineStage ?? 'open'}${i.berthMooringNumber ? ` - Berth ${i.berthMooringNumber}` : ''}${i.leadCategory ? ` [${i.leadCategory}]` : ''} (${new Date(i.createdAt as string | Date).toLocaleDateString('en-GB')})`,
)
.join('\n')
: 'No pipeline interests on file';
@@ -147,7 +147,7 @@ export function buildClientSummaryInputs(
return {
portName: (port?.name as string) ?? 'Port Nimara',
title: `Client Summary ${client.fullName ?? ''}`,
title: `Client Summary - ${client.fullName ?? ''}`,
clientInfo,
contacts: contactsText,
yachts: yachtsText,

View File

@@ -61,7 +61,7 @@ export function getStandardEoiTemplateHtml(): string {
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Expression of Interest Letter of Intent</title>
<title>Expression of Interest - Letter of Intent</title>
<style>
@page {
size: letter;
@@ -165,7 +165,7 @@ export function getStandardEoiTemplateHtml(): string {
<body>
<div class="header">
<div class="port-name">{{port.name}}</div>
<div class="doc-title">Expression of Interest Letter of Intent</div>
<div class="doc-title">Expression of Interest - Letter of Intent</div>
</div>
<div class="meta">
@@ -317,7 +317,7 @@ export function getStandardEoiTemplateHtml(): string {
<div class="signatures">
<div class="slot">
<div class="sig-line">
Applicant {{client.fullName}}
Applicant - {{client.fullName}}
</div>
<div class="muted" style="font-size:10pt; margin-top:2pt;">Date: __________________</div>
</div>

View File

@@ -152,7 +152,7 @@ export function buildInterestSummaryInputs(
return {
portName: (port?.name as string) ?? 'Port Nimara',
title: `Interest Summary ${client?.fullName ?? 'Unknown Client'}`,
title: `Interest Summary - ${client?.fullName ?? 'Unknown Client'}`,
clientInfo,
berthInfo,
stageAndCategory,