diff --git a/src/components/berths/berth-tabs.tsx b/src/components/berths/berth-tabs.tsx index 2fb1514..aa66f70 100644 --- a/src/components/berths/berth-tabs.tsx +++ b/src/components/berths/berth-tabs.tsx @@ -57,13 +57,45 @@ function SpecRow({ label, value }: { label: string; value: React.ReactNode }) { } function OverviewTab({ berth }: { berth: BerthData }) { + // Round to at most 2 decimals; trim trailing zeros so "5.00" -> "5". + const fmt = (v: string | null, fractionDigits = 2): string | null => { + if (v == null || v === '') return null; + const n = Number(v); + if (Number.isNaN(n)) return v; + return n.toLocaleString('en-US', { + minimumFractionDigits: 0, + maximumFractionDigits: fractionDigits, + }); + }; + const formatDim = (ft: string | null, m: string | null) => { const parts = []; - if (ft) parts.push(`${ft} ft`); - if (m) parts.push(`${m} m`); + const ftFmt = fmt(ft); + const mFmt = fmt(m); + if (ftFmt) parts.push(`${ftFmt} ft`); + if (mFmt) parts.push(`${mFmt} m`); return parts.length > 0 ? parts.join(' / ') : null; }; + const formatNominalBoatSize = (ft: string | null, m: string | null): string | null => { + const ftFmt = fmt(ft, 0); + const mFmt = fmt(m); + const parts: string[] = []; + if (ftFmt) parts.push(`${ftFmt} ft`); + if (mFmt) parts.push(`${mFmt} m`); + return parts.length > 0 ? parts.join(' / ') : null; + }; + + const formatPower = (kw: string | null) => { + const v = fmt(kw, 0); + return v ? `${v} kW` : null; + }; + + const formatVoltage = (v: string | null) => { + const fv = fmt(v, 0); + return fv ? `${fv} V` : null; + }; + const price = berth.price ? new Intl.NumberFormat('en-US', { style: 'currency', @@ -97,7 +129,7 @@ function OverviewTab({ berth }: { berth: BerthData }) { Infrastructure - - + + diff --git a/src/lib/db/seed.ts b/src/lib/db/seed.ts index 1a351d5..c23ca10 100644 --- a/src/lib/db/seed.ts +++ b/src/lib/db/seed.ts @@ -2,16 +2,16 @@ * Seed script for Port Nimara CRM. * * Top-level orchestrator: - * 1. Create 3 ports (idempotent): - * - Port Nimara - * - Marina Azzurra - * - Harbor Royale + * 1. Create the operational ports (idempotent): + * - Port Nimara (primary install — the real marina) + * - Port Amador (secondary, kept for multi-tenant isolation tests + * and as scaffolding for a future Panama install) * 2. Create 5 system roles with full permission maps * 3. Create the super admin user profile placeholder (matt@portnimara.com) * 4. For each port, call `seedPortData(portId, portSlug)` from seed-data.ts * to produce the realistic multi-cardinality fixture - * (berths, clients, companies, yachts, memberships, interests, - * reservations, ownership-transfer history). + * (117 berths from the NocoDB snapshot, plus clients, companies, yachts, + * memberships, interests, reservations, ownership-transfer history). * 5. Print a summary. * * Run with: pnpm db:seed @@ -413,19 +413,15 @@ const PORT_DEFINITIONS: Array<{ defaultCurrency: 'USD', timezone: 'America/Anguilla', }, + // Second port kept for multi-tenant isolation tests (cross-port scoping, + // permission boundaries). Drop or rename if the production install is + // single-port. { - name: 'Marina Azzurra', - slug: 'marina-azzurra', - primaryColor: '#2E86AB', - defaultCurrency: 'EUR', - timezone: 'Europe/Rome', - }, - { - name: 'Harbor Royale', - slug: 'harbor-royale', - primaryColor: '#8B1E3F', - defaultCurrency: 'GBP', - timezone: 'Europe/London', + name: 'Port Amador', + slug: 'port-amador', + primaryColor: '#D97706', + defaultCurrency: 'USD', + timezone: 'America/Panama', }, ];