'use client'; import { useQuery } from '@tanstack/react-query'; import Link from 'next/link'; import { useParams } from 'next/navigation'; import { Flame } from 'lucide-react'; import { formatDistanceToNow } from 'date-fns'; import { apiFetch } from '@/lib/api/client'; import { Badge } from '@/components/ui/badge'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Skeleton } from '@/components/ui/skeleton'; interface HotDeal { id: string; stage: string; clientName: string; mooringNumber: string | null; lastContact: string | null; } interface HotDealsResponse { data: HotDeal[]; } // Local label map intentionally narrowed to the stages this widget // surfaces. Keys MUST match the canonical DB values (deposit_10pct + // in_communication) — the reporting audit caught typos that broke the // rank ladder server-side AND rendered raw enum to the user. const STAGE_LABELS: Record = { contract_signed: 'Contract Signed', contract_sent: 'Contract Sent', deposit_10pct: 'Deposit 10%', eoi_signed: 'EOI Signed', eoi_sent: 'EOI Sent', in_communication: 'In Comms', details_sent: 'Details Sent', open: 'Open', completed: 'Completed', }; /** * Top 5 in-flight interests closest to closing. Ranked server-side by * pipeline stage (the further along, the closer to signing) with most- * recent activity as a tiebreaker. Gives reps a "what should I be * chasing this week" view without opening the full pipeline board. */ export function HotDealsCard() { const params = useParams<{ portSlug: string }>(); const portSlug = params?.portSlug ?? ''; const { data, isLoading } = useQuery({ queryKey: ['dashboard', 'hot_deals'], queryFn: () => apiFetch('/api/v1/dashboard/hot-deals'), staleTime: 60_000, }); const deals = data?.data ?? []; return ( Hot deals Active interests closest to closing. {isLoading ? (
) : deals.length === 0 ? (

No active deals to chase. New leads will surface here once they advance past Open.

) : (
    {deals.map((d) => (
  • {d.clientName}

    {d.mooringNumber ? `Berth ${d.mooringNumber}` : 'No berth linked'} {d.lastContact ? ( <> {' · '} last touched {formatDistanceToNow(new Date(d.lastContact))} ago ) : null}

    {STAGE_LABELS[d.stage] ?? d.stage}
  • ))}
)}
); }