import { useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom' import { useAppPath } from '@core/hooks/useAppPath' import { apiFetch } from '@core/lib/api' interface Deal { id: string title: string data: { stage?: string; value?: number; close_date?: string; probability?: number; source?: string } created_at: string } const STAGES = ['prospecting', 'qualification', 'proposal', 'negotiation', 'closed_won', 'closed_lost'] const STAGE_STYLE: Record = { prospecting: { bg: 'bg-slate-50', header: 'bg-slate-100', badge: 'bg-slate-200 text-slate-700' }, qualification: { bg: 'bg-blue-50', header: 'bg-blue-100', badge: 'bg-blue-200 text-blue-700' }, proposal: { bg: 'bg-yellow-50', header: 'bg-yellow-100', badge: 'bg-yellow-200 text-yellow-700' }, negotiation: { bg: 'bg-orange-50', header: 'bg-orange-100', badge: 'bg-orange-200 text-orange-700' }, closed_won: { bg: 'bg-green-50', header: 'bg-green-100', badge: 'bg-green-200 text-green-700' }, closed_lost: { bg: 'bg-red-50', header: 'bg-red-100', badge: 'bg-red-200 text-red-700' }, } function DealCard({ deal, onClick }: { deal: Deal; onClick: () => void }) { return (
{deal.title}
{deal.data?.value != null && (
${deal.data.value.toLocaleString()}
)}
{deal.data?.source || '—'} {deal.data?.close_date || ''}
) } export default function DealsPage() { const navigate = useNavigate() const appPath = useAppPath() const [deals, setDeals] = useState([]) const [loading, setLoading] = useState(true) const [view, setView] = useState<'kanban' | 'list'>('kanban') useEffect(() => { apiFetch('/api/admin-data?action=list&entity=items&type_slug=deal&limit=200') .then(r => r.json()) .then(json => setDeals(Array.isArray(json?.data) ? json.data : json || [])) .catch(() => setDeals([])) .finally(() => setLoading(false)) }, []) const byStage = (stage: string) => deals.filter(d => (d.data?.stage || 'prospecting') === stage) return (

Deals

{deals.length} deals across {STAGES.length} stages

{loading ? (
Loading deals…
) : view === 'kanban' ? (
{STAGES.map(stage => { const s = STAGE_STYLE[stage] const stageDeals = byStage(stage) const stageValue = stageDeals.reduce((sum, d) => sum + (d.data?.value || 0), 0) return (
{stage.replace('_', ' ')}
{stageDeals.length} · {stageValue ? `$${(stageValue / 1000).toFixed(0)}k` : '$0'}
{stageDeals.map(deal => ( navigate(`/crm/deals/${deal.id}`)} /> ))}
) })}
) : (
{deals.length === 0 ? ( ) : deals.map(deal => { const s = STAGE_STYLE[deal.data?.stage || 'prospecting'] return ( navigate(`/crm/deals/${deal.id}`)} className="hover:bg-slate-50 cursor-pointer" > ) })}
Deal Stage Value Source Close Date
No deals yet.{' '}
{deal.title} {(deal.data?.stage || 'prospecting').replace('_', ' ')} {deal.data?.value ? `$${deal.data.value.toLocaleString()}` : '—'} {deal.data?.source || '—'} {deal.data?.close_date || '—'}
)}
) }