import { useEffect, useState, useCallback } from 'react'; import { api, type Referral, type ReferralCreate } from '@/lib/api'; import type { Client } from '@/types'; import { UserPlus, Plus, Trash2, ArrowRight, Edit3, Search } from 'lucide-react'; import { formatDate } from '@/lib/utils'; import Modal from './Modal'; const STATUSES = ['pending', 'contacted', 'converted', 'lost']; const TYPES = ['client', 'partner', 'event']; const statusColors: Record = { pending: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300', contacted: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300', converted: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-300', lost: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300', }; function formatCurrency(val: string | null): string { if (!val) return ''; const n = parseFloat(val); if (isNaN(n)) return ''; return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 }).format(n); } export default function ClientReferrals({ clientId, clientName }: { clientId: string; clientName: string }) { const [referrals, setReferrals] = useState([]); const [loading, setLoading] = useState(true); const [showAdd, setShowAdd] = useState(false); const [clients, setClients] = useState([]); const [searchQuery, setSearchQuery] = useState(''); const [form, setForm] = useState({ referredId: '', type: 'client', notes: '', value: '', status: 'pending' }); const [saving, setSaving] = useState(false); const fetchReferrals = useCallback(async () => { try { const data = await api.getClientReferrals(clientId); setReferrals(data); } catch {} setLoading(false); }, [clientId]); useEffect(() => { fetchReferrals(); }, [fetchReferrals]); const openAdd = async () => { setForm({ referredId: '', type: 'client', notes: '', value: '', status: 'pending' }); setSearchQuery(''); try { const allClients = await api.getClients(); setClients(allClients.filter((c: Client) => c.id !== clientId)); } catch {} setShowAdd(true); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!form.referredId) { alert('Please select a referred client'); return; } setSaving(true); try { const data: ReferralCreate = { referredId: form.referredId, type: form.type, notes: form.notes || undefined, value: form.value || undefined, status: form.status, }; await api.createReferral(clientId, data); setShowAdd(false); await fetchReferrals(); } catch (e: any) { alert(e.message || 'Failed to create referral'); } setSaving(false); }; const handleUpdateStatus = async (refId: string, status: string) => { try { await api.updateReferral(refId, { status }); await fetchReferrals(); } catch {} }; const handleDelete = async (refId: string) => { if (!confirm('Delete this referral?')) return; try { await api.deleteReferral(refId); setReferrals(prev => prev.filter(r => r.id !== refId)); } catch {} }; const filteredClients = clients.filter(c => { if (!searchQuery) return true; const q = searchQuery.toLowerCase(); return `${c.firstName} ${c.lastName}`.toLowerCase().includes(q) || (c.email || '').toLowerCase().includes(q) || (c.company || '').toLowerCase().includes(q); }); const given = referrals.filter(r => r.referrerId === clientId); const received = referrals.filter(r => r.referredId === clientId); return (

Referrals

{/* Given Referrals */}

Referrals Given ({given.length})

{loading ? (

Loading...

) : given.length === 0 ? (

No referrals given yet

) : ( given.map(ref => (
{ref.referrer.firstName} {ref.referrer.lastName} {ref.referred.firstName} {ref.referred.lastName}
{ref.value && ( {formatCurrency(ref.value)} )} {formatDate(ref.createdAt)}
)) )}
{/* Received Referrals */} {received.length > 0 && (

Referred By ({received.length})

{received.map(ref => (
{ref.referrer.firstName} {ref.referrer.lastName} {ref.referred.firstName} {ref.referred.lastName}
{ref.status} {formatDate(ref.createdAt)}
))}
)} {/* Add Referral Modal */} setShowAdd(false)} title="Add Referral">
setSearchQuery(e.target.value)} placeholder="Search clients..." className="w-full pl-9 pr-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-800 text-slate-900 dark:text-slate-100 text-sm" />
{filteredClients.slice(0, 20).map(c => ( ))} {filteredClients.length === 0 && (

No matching clients

)}
setForm(f => ({ ...f, value: e.target.value }))} placeholder="0.00" className="w-full px-3 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-800 text-slate-900 dark:text-slate-100 text-sm" />