// ─── Pipeline Stages ───────────────────────────────────────────────────────── export const PIPELINE_STAGES = [ 'open', 'details_sent', 'in_communication', 'eoi_sent', 'eoi_signed', 'deposit_10pct', 'contract_sent', 'contract_signed', 'completed', ] as const; export type PipelineStage = (typeof PIPELINE_STAGES)[number]; export const STAGE_LABELS: Record = { open: 'Open', details_sent: 'Details Sent', in_communication: 'In Comms', eoi_sent: 'EOI Sent', eoi_signed: 'EOI Signed', deposit_10pct: 'Deposit 10%', contract_sent: 'Contract Sent', contract_signed: 'Contract Signed', completed: 'Completed', }; // Compact labels for cramped contexts (mobile chart axes, dense tables). export const STAGE_SHORT_LABELS: Record = { open: 'Open', details_sent: 'Details', in_communication: 'Comms', eoi_sent: 'EOI →', eoi_signed: 'EOI ✓', deposit_10pct: 'Dep.', contract_sent: 'Ctr →', contract_signed: 'Ctr ✓', completed: 'Done', }; export const STAGE_BADGE: Record = { open: 'bg-slate-100 text-slate-700', details_sent: 'bg-blue-100 text-blue-700', in_communication: 'bg-sky-100 text-sky-700', eoi_sent: 'bg-indigo-100 text-indigo-700', eoi_signed: 'bg-amber-100 text-amber-700', deposit_10pct: 'bg-orange-100 text-orange-700', contract_sent: 'bg-yellow-100 text-yellow-700', contract_signed: 'bg-green-100 text-green-700', completed: 'bg-emerald-100 text-emerald-700', }; export const STAGE_DOT: Record = { open: 'bg-slate-400', details_sent: 'bg-blue-500', in_communication: 'bg-sky-500', eoi_sent: 'bg-indigo-500', eoi_signed: 'bg-amber-500', deposit_10pct: 'bg-orange-500', contract_sent: 'bg-yellow-500', contract_signed: 'bg-green-500', completed: 'bg-emerald-500', }; // Default revenue-forecast probability weights per stage (0–1). // Editable per port via settings (`pipeline_weights`); these are the fallbacks. export const STAGE_WEIGHTS: Record = { open: 0.05, details_sent: 0.1, in_communication: 0.2, eoi_sent: 0.4, eoi_signed: 0.6, deposit_10pct: 0.75, contract_sent: 0.85, contract_signed: 0.95, completed: 1.0, }; // Allowed transitions out of each stage. Used by changeInterestStage to guard // against accidental skips (e.g. dragging a card from Completed back to Open, // or jumping Open straight to Completed). Forward moves of 1-2 stages are // permitted; backward moves are limited to the immediate predecessor unless // the lifecycle (EOI/contract chain) needs an explicit rewind. export const STAGE_TRANSITIONS: Record = { open: ['details_sent', 'in_communication', 'eoi_sent', 'eoi_signed'], details_sent: ['open', 'in_communication', 'eoi_sent', 'eoi_signed'], in_communication: ['open', 'details_sent', 'eoi_sent', 'eoi_signed'], eoi_sent: ['in_communication', 'eoi_signed', 'deposit_10pct'], eoi_signed: ['eoi_sent', 'deposit_10pct', 'contract_sent', 'contract_signed'], deposit_10pct: ['eoi_signed', 'contract_sent', 'contract_signed'], contract_sent: ['eoi_signed', 'deposit_10pct', 'contract_signed'], contract_signed: ['contract_sent', 'deposit_10pct', 'completed'], completed: ['contract_signed'], }; export function canTransitionStage(from: string, to: string): boolean { if (from === to) return true; const fromStage = safeStage(from); const toStage = safeStage(to); return STAGE_TRANSITIONS[fromStage].includes(toStage); } export function safeStage(value: string | null | undefined): PipelineStage { return PIPELINE_STAGES.includes(value as PipelineStage) ? (value as PipelineStage) : 'open'; } export function stageLabel(stage: string | null | undefined): string { return STAGE_LABELS[safeStage(stage)]; } export function stageBadgeClass(stage: string | null | undefined): string { return STAGE_BADGE[safeStage(stage)]; } export function stageDotClass(stage: string | null | undefined): string { return STAGE_DOT[safeStage(stage)]; } // ─── Berth Statuses ────────────────────────────────────────────────────────── export const BERTH_STATUSES = ['available', 'under_offer', 'sold'] as const; export type BerthStatus = (typeof BERTH_STATUSES)[number]; // ─── Berth single-select catalogues (mirror NocoDB) ────────────────────────── // Stored as free text in the DB so legacy values still load, but the form // presents only the canonical options below. export const BERTH_AREAS = ['A', 'B', 'C', 'D', 'E'] as const; export const BERTH_BOW_FACING_OPTIONS = ['North', 'South', 'East', 'West'] as const; export const BERTH_SIDE_PONTOON_OPTIONS = [ 'No', 'Quay SB', 'Quay PT', 'Quay SB, Yes PT', 'Quay PT, Yes SB', 'Yes SB', 'Yes PT', 'Yes SB, PT', 'Finger SB', 'Finger PT', ] as const; export const BERTH_MOORING_TYPES = [ 'Side Pier / Med Mooring', '2x Med Mooring', 'Side Pier / Finger', 'Finger / Med Mooring', '2x Finger', ] as const; export const BERTH_CLEAT_TYPES = ['A3', 'A5'] as const; export const BERTH_CLEAT_CAPACITIES = ['10-14 ton break load', '20-24 ton break load'] as const; export const BERTH_BOLLARD_TYPES = ['Bull bollard type A', 'Bull bollard type B'] as const; export const BERTH_BOLLARD_CAPACITIES = ['20 ton break load', '40 ton break load'] as const; export const BERTH_ACCESS_OPTIONS = [ 'Car to Vessel', 'Car to Quai, Cart to Vessel', 'Cart to Vessel', 'Car (3t) to Vessel', 'Car (3.5t) to Vessel', ] as const; /** Helper to map a readonly enum tuple into shadcn `