'use client'; import { useEffect } from 'react'; import { useQuery } from '@tanstack/react-query'; import { useParams } from 'next/navigation'; import { DetailLayout } from '@/components/shared/detail-layout'; import { InterestDetailHeader } from '@/components/interests/interest-detail-header'; import { getInterestTabs } from '@/components/interests/interest-tabs'; import { useMobileChrome } from '@/components/layout/mobile/mobile-layout-provider'; import { useRealtimeInvalidation } from '@/hooks/use-realtime-invalidation'; import { useBreadcrumbHint } from '@/hooks/use-breadcrumb-hint'; import { apiFetch } from '@/lib/api/client'; interface InterestData { id: string; portId: string; clientId: string; clientName: string | null; /** Linked client's primary email (display value). Powers the header * "Email" button and the EOI prereq checklist. */ clientPrimaryEmail: string | null; /** Linked client's primary phone (display value). Powers the header * "Call" button. */ clientPrimaryPhone: string | null; /** Linked client's primary phone in E.164 form ("+1XXXXXXXXXX"). Used * by wa.me to assemble the WhatsApp deep-link. */ clientPrimaryPhoneE164: string | null; /** True when the linked client has any primary address row. Used by * the EOI prereq checklist on the Documents tab. */ clientHasAddress: boolean; /** Surfaced for the bell badge on the detail header (pending/snoozed * reminders linked to this interest). */ activeReminderCount?: number; /** Surfaced for the most-recent-note teaser on the Overview tab. */ notesCount?: number; recentNote?: { id: string; content: string; authorId: string; createdAt: string; } | null; berthId: string | null; berthMooringNumber: string | null; /** Yacht-fit dimensions (numeric strings from postgres). Drive the * recommender panel guard ("Set desired dimensions to see recommendations"). */ desiredLengthFt: string | null; desiredWidthFt: string | null; desiredDraftFt: string | null; pipelineStage: string; leadCategory: string | null; source: string | null; eoiStatus: string | null; contractStatus: string | null; depositStatus: string | null; reservationStatus: string | null; dateFirstContact: string | null; dateLastContact: string | null; dateEoiSent: string | null; dateEoiSigned: string | null; dateContractSent: string | null; dateContractSigned: string | null; dateDepositReceived: string | null; reminderEnabled: boolean; reminderDays: number | null; reminderLastFired: string | null; notes: string | null; archivedAt: string | null; createdAt: string; updatedAt: string; outcome?: string | null; outcomeReason?: string | null; tags: Array<{ id: string; name: string; color: string }>; } interface InterestDetailProps { interestId: string; currentUserId?: string; } export function InterestDetail({ interestId, currentUserId }: InterestDetailProps) { const params = useParams<{ portSlug: string }>(); const portSlug = params?.portSlug ?? ''; const { data, isLoading } = useQuery({ queryKey: ['interests', interestId], queryFn: () => apiFetch<{ data: InterestData }>(`/api/v1/interests/${interestId}`).then((r) => r.data), }); useRealtimeInvalidation({ 'interest:updated': [['interests', interestId]], 'interest:stageChanged': [['interests', interestId]], 'interest:archived': [['interests', interestId]], 'interest:berthLinked': [['interests', interestId]], 'interest:berthUnlinked': [['interests', interestId]], }); const { setChrome } = useMobileChrome(); const titleForChrome: string | null = data?.clientName ?? null; useEffect(() => { setChrome({ title: titleForChrome, showBackButton: true }); return () => setChrome({ title: null, showBackButton: false }); }, [titleForChrome, setChrome]); // Topbar breadcrumb: Clients › Mary Smith › Interest › B17. // Parent client links straight back to the client detail; the // current crumb is the primary berth's mooring (or "Interest" if // no berth linked yet — same trick the page H1 uses). useBreadcrumbHint( data ? { parents: data.clientId && data.clientName ? [{ label: data.clientName, href: `/${portSlug}/clients/${data.clientId}` }] : [], current: data.berthMooringNumber ?? 'Interest', } : null, ); const tabs = data ? getInterestTabs({ interestId, currentUserId, clientId: data.clientId ?? null, interest: data, }) : []; return ( : null} tabs={tabs} defaultTab="overview" isLoading={isLoading} /> ); }