From 7ef7b9bb5fb6c46ba0788c8ab0f794c412d4ea8e Mon Sep 17 00:00:00 2001 From: Matt Ciaccio Date: Fri, 24 Apr 2026 16:13:51 +0200 Subject: [PATCH] feat(eoi): seed Standard EOI in-app template per port Adds a new per-port document_templates row of type 'eoi' containing an HTML EOI / Letter of Intent body with {{section.field}} merge tokens that mirror the EoiContext shape. Enables the in-app pdfme PDF path as an alternative to the Documenso template flow. - New getStandardEoiTemplateHtml() returns the Letter-sized HTML body with Applicant / Yacht / Owner / Berth / Interest / Signatures blocks - STANDARD_EOI_MERGE_FIELDS exported for resolveTemplate wiring (11.4) - seed-data.ts inserts one document_templates row per port inside the existing withTransaction block, between ownership transfers and interests, using SEED_USER_ID for audit consistency Co-Authored-By: Claude Opus 4.7 (1M context) --- src/lib/db/seed-data.ts | 20 ++ src/lib/pdf/templates/eoi-standard-inapp.ts | 337 ++++++++++++++++++++ 2 files changed, 357 insertions(+) create mode 100644 src/lib/pdf/templates/eoi-standard-inapp.ts diff --git a/src/lib/db/seed-data.ts b/src/lib/db/seed-data.ts index 5dcf5de..f12ba9f 100644 --- a/src/lib/db/seed-data.ts +++ b/src/lib/db/seed-data.ts @@ -33,7 +33,12 @@ import { berths, berthReservations, interests, + documentTemplates, } from './schema'; +import { + getStandardEoiTemplateHtml, + STANDARD_EOI_MERGE_FIELDS, +} from '@/lib/pdf/templates/eoi-standard-inapp'; // ─── Tunables ──────────────────────────────────────────────────────────────── @@ -840,6 +845,21 @@ export async function seedPortData(portId: string, portSlug: string): Promise + + + +Expression of Interest — Letter of Intent + + + +
+
{{port.name}}
+
Expression of Interest — Letter of Intent
+
+ +
+
Date: {{date.today}}
+
Port: {{port.name}}
+
+ +

+ This Expression of Interest (the “EOI”) is entered into between + {{port.name}} and the Applicant named below, and records the + Applicant’s non-binding intent to proceed toward a berth acquisition at + the port. It is subject to subsequent definitive documentation. +

+ +

1. Applicant

+ + + + + + + + + + + + + + + + + + + + + +
Full name{{client.fullName}}
Nationality{{client.nationality}}
Email{{client.primaryEmail}}
Phone{{client.primaryPhone}}
Address +

{{client.address.street}}

+

{{client.address.city}}

+

{{client.address.country}}

+
+ +

2. Yacht

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name{{yacht.name}}
Hull number{{yacht.hullNumber}}
Flag{{yacht.flag}}
Year built{{yacht.yearBuilt}}
Length (ft / m){{yacht.lengthFt}} ft  /  {{yacht.lengthM}} m
Beam (ft / m){{yacht.widthFt}} ft  /  {{yacht.widthM}} m
Draft (ft / m){{yacht.draftFt}} ft  /  {{yacht.draftM}} m
+ +

3. Owner

+

+ Owner type: {{owner.type}}
+ Owner name: {{owner.name}} + (legal: {{owner.legalName}}) +

+ + + + + + + + + + + + + + + + + +
Company name{{company.name}}
Legal name{{company.legalName}}
Tax ID{{company.taxId}}
Billing address{{company.billingAddress}}
+

+ The company block is populated only where the yacht is company-owned; for + client-owned yachts these fields render empty. +

+ +

4. Berth

+ + + + + + + + + + + + + + + + + + + + + +
Mooring number{{berth.mooringNumber}}
Area{{berth.area}}
Length{{berth.lengthFt}} ft
Price{{berth.price}} {{berth.priceCurrency}}
Tenure type{{berth.tenureType}}
+ +

5. Interest Summary

+ + + + + + + + + + + + + + + + + +
Pipeline stage{{interest.stage}}
Lead category{{interest.leadCategory}}
First contact{{interest.dateFirstContact}}
Notes{{interest.notes}}
+ +

6. Signatures

+
+
+
+ Applicant — {{client.fullName}} +
+
Date: __________________
+
+
+
+ For and on behalf of {{port.name}} +
+
Date: __________________
+
+
+ + + +`; +}