'use client'; import { useState } from 'react'; import Link from 'next/link'; import { useParams } from 'next/navigation'; import { useQuery } from '@tanstack/react-query'; import { Input } from '@/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { PageHeader } from '@/components/shared/page-header'; import { useRealtimeInvalidation } from '@/hooks/use-realtime-invalidation'; import { apiFetch } from '@/lib/api/client'; import { PIPELINE_STAGES } from '@/lib/validators/residential'; interface ResidentialInterestRow { id: string; residentialClientId: string; pipelineStage: string; source: string | null; notes: string | null; preferences: string | null; assignedTo: string | null; updatedAt: string; } interface ListResponse { data: ResidentialInterestRow[]; pagination: { total: number }; } const STAGE_LABELS: Record = { new: 'New', contacted: 'Contacted', viewing_scheduled: 'Viewing scheduled', offer_made: 'Offer made', offer_accepted: 'Offer accepted', closed_won: 'Closed — won', closed_lost: 'Closed — lost', }; export function ResidentialInterestsList() { const params = useParams<{ portSlug: string }>(); const portSlug = params?.portSlug ?? ''; const [search, setSearch] = useState(''); const [stage, setStage] = useState('all'); const { data, isLoading } = useQuery({ queryKey: ['residential-interests', { search, stage }], queryFn: () => { const qs = new URLSearchParams({ search, limit: '50' }); if (stage !== 'all') qs.set('pipelineStage', stage); return apiFetch(`/api/v1/residential/interests?${qs.toString()}`); }, }); useRealtimeInvalidation({ 'residential_interest:created': [['residential-interests']], 'residential_interest:updated': [['residential-interests']], 'residential_interest:archived': [['residential-interests']], }); return (
setSearch(e.target.value)} className="max-w-sm" />
{/* Desktop: table layout. Hidden below lg; mobile renders cards. */}
{isLoading && ( )} {!isLoading && data?.data.length === 0 && ( )} {data?.data.map((i) => ( ))}
Stage Preferences Notes Source Updated
Loading…
No interests match.
{STAGE_LABELS[i.pipelineStage] ?? i.pipelineStage} {i.preferences ?? '—'} {i.notes ?? '—'} {i.source ?? '—'} {new Date(i.updatedAt).toLocaleDateString()}
{/* Mobile: card list. Stage as the headline (it's the most actionable field for triage), preferences/notes truncated below. */}
{isLoading && (
Loading…
)} {!isLoading && data?.data.length === 0 && (
No interests match.
)} {data?.data.map((i) => (

{STAGE_LABELS[i.pipelineStage] ?? i.pipelineStage}

{new Date(i.updatedAt).toLocaleDateString()}
{i.preferences ? (

{i.preferences}

) : null} {i.notes ? (

{i.notes}

) : null} {i.source ? (

{i.source}

) : null} ))}
); }