'use client'; import { useMemo, useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { formatDistanceToNow } from 'date-fns'; import { PageHeader } from '@/components/shared/page-header'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { apiFetch } from '@/lib/api/client'; interface Submission { id: string; portId: string; submissionId: string; kind: 'berth_inquiry' | 'residence_inquiry' | 'contact_form'; payload: Record | null; legacyNocodbId: string | null; sourceIp: string | null; userAgent: string | null; receivedAt: string; } interface ListResponse { data: Submission[]; pagination: { nextCursor: { receivedAt: string; id: string } | null }; counts: Record; } const KIND_LABELS: Record = { berth_inquiry: 'Berth inquiry', residence_inquiry: 'Residence inquiry', contact_form: 'Contact form', }; const KIND_COLORS: Record = { berth_inquiry: 'bg-blue-100 text-blue-800', residence_inquiry: 'bg-amber-100 text-amber-800', contact_form: 'bg-slate-100 text-slate-800', }; function pickName(payload: Record | null): string { if (!payload) return ''; const candidates = ['name', 'fullName', 'full_name', 'firstName', 'first_name']; for (const k of candidates) { const v = payload[k]; if (typeof v === 'string' && v.trim()) return v.trim(); } return ''; } function pickEmail(payload: Record | null): string { if (!payload) return ''; const v = payload['email']; return typeof v === 'string' ? v : ''; } function pickPhone(payload: Record | null): string { if (!payload) return ''; const v = payload['phone'] ?? payload['phoneNumber'] ?? payload['phone_number']; return typeof v === 'string' ? v : ''; } export function InquiryInbox() { const [kind, setKind] = useState('all'); const [expanded, setExpanded] = useState(null); const { data, isLoading, error } = useQuery({ queryKey: ['inquiry-inbox', kind], queryFn: () => apiFetch( `/api/v1/admin/website-submissions${kind === 'all' ? '' : `?kind=${kind}`}`, ), }); const counts = data?.counts ?? {}; const totalAll = useMemo(() => Object.values(counts).reduce((sum, n) => sum + n, 0), [counts]); const rows = data?.data ?? []; return (
setKind('all')} /> setKind('berth_inquiry')} /> setKind('residence_inquiry')} /> setKind('contact_form')} />
{isLoading ? (

Loading…

) : error ? (

Failed to load inquiries: {error instanceof Error ? error.message : 'unknown error'}

) : rows.length === 0 ? ( No website submissions yet for this filter. ) : (
{rows.map((row) => { const name = pickName(row.payload); const email = pickEmail(row.payload); const phone = pickPhone(row.payload); const ago = formatDistanceToNow(new Date(row.receivedAt), { addSuffix: true }); const isOpen = expanded === row.id; return (
{KIND_LABELS[row.kind]} {ago}
{name || '(no name supplied)'}
{email ? {email} : null} {phone ? {phone} : null} {row.sourceIp ? ( from {row.sourceIp} ) : null}
{isOpen && (
                        {JSON.stringify(row.payload, null, 2)}
                      
)}
); })}
)}
); } function FilterChip({ label, active, onClick, }: { label: string; active: boolean; onClick: () => void; }) { return ( ); }