import { useEffect, useState } from 'react' import { useParams, useNavigate } from 'react-router-dom' import { useAppPath } from '@core/hooks/useAppPath' import { apiFetch } from '@core/lib/api' import { Tabs, TabsList, TabsTrigger, TabsContent } from '@core/components/ui/tabs' import { Badge } from '@core/components/ui/badge' import { Skeleton } from '@core/components/ui/skeleton' import { Button } from '@core/components/ui/button' import { ScrollArea } from '@core/components/ui/scroll-area' import { Separator } from '@core/components/ui/separator' import { ArrowLeft, User, Ticket, Handshake, Activity, Heart, Funnel, TrendingUp, Target, Clock } from 'lucide-react' interface Account { id: string slug: string display_name?: string created_at: string data?: { segment?: string lifecycle_stage?: string lead_score?: number temperature?: 'cold' | 'warm' | 'hot' last_signal_at?: string ratings?: { anonymous?: { rating: number; raw_score: number } identified?: { rating: number; raw_score: number } engaged?: { rating: number; raw_score: number } } attribution?: { anonymous_first_touch?: { referrer?: string; url?: string; at?: string } identified_first_touch?: { referrer?: string; url?: string; at?: string } } queue?: { pending_opportunity_id?: string primary_opportunity_type?: string } } } interface Person { id: string email: string first_name?: string last_name?: string created_at: string } interface Item { id: string title: string status?: string data?: Record created_at: string } function PeopleTab({ accountId }: { accountId: string }) { const [people, setPeople] = useState([]) const [loading, setLoading] = useState(true) useEffect(() => { apiFetch(`/api/admin-data?action=list&entity=people&account_id=${accountId}&limit=100`) .then(r => r.json()).then(j => setPeople(Array.isArray(j?.data) ? j.data : Array.isArray(j) ? j : [])).catch(() => setPeople([])).finally(() => setLoading(false)) }, [accountId]) if (loading) return
{Array.from({ length: 3 }).map((_, i) => )}
if (people.length === 0) return

No people found.

return (
{people.map(p => (

{[p.first_name, p.last_name].filter(Boolean).join(' ') || '—'}

{p.email}

{new Date(p.created_at).toLocaleDateString()}

))}
) } function ItemsTab({ accountId, typeSlug, emptyText }: { accountId: string; typeSlug: string; emptyText: string }) { const navigate = useNavigate() const appPath = useAppPath() const [items, setItems] = useState([]) const [loading, setLoading] = useState(true) useEffect(() => { apiFetch(`/api/admin-data?action=list&entity=items&type_slug=${typeSlug}&account_id=${accountId}&limit=100`) .then(r => r.json()).then(j => setItems(Array.isArray(j?.data) ? j.data : Array.isArray(j) ? j : [])).catch(() => setItems([])).finally(() => setLoading(false)) }, [accountId, typeSlug]) if (loading) return
{Array.from({ length: 3 }).map((_, i) => )}
if (items.length === 0) return

{emptyText}

return (
{items.map(item => (
typeSlug === 'support_ticket' ? navigate(appPath(`/support/${item.id}`)) : typeSlug === 'deal' ? navigate(appPath(`/crm/deals/${item.id}`)) : undefined} >

{item.title}

{new Date(item.created_at).toLocaleDateString()}

{item.status && {item.status}}
))}
) } function ActivityTab({ accountId }: { accountId: string }) { const [items, setItems] = useState([]) const [loading, setLoading] = useState(true) useEffect(() => { Promise.all([ apiFetch(`/api/admin-data?action=list&entity=items&type_slug=marketing_touch&account_id=${accountId}&limit=20`).then(r => r.json()), apiFetch(`/api/admin-data?action=list&entity=items&type_slug=site_visit&account_id=${accountId}&limit=20`).then(r => r.json()), apiFetch(`/api/admin-data?action=list&entity=items&type_slug=support_ticket&account_id=${accountId}&limit=20`).then(r => r.json()), ]).then(([tor, vor, tkr]) => { const touches = tor?.data ?? tor const visits = vor?.data ?? vor const tickets = tkr?.data ?? tkr const all = [...(touches || []), ...(visits || []), ...(tickets || [])] .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()) setItems(all) }).catch(() => setItems([])).finally(() => setLoading(false)) }, [accountId]) if (loading) return
{Array.from({ length: 5 }).map((_, i) => )}
if (items.length === 0) return

No activity yet.

return (
{items.map(item => (

{item.title}

{new Date(item.created_at).toLocaleDateString()}

))}
) } function FunnelTab({ account }: { account: Account }) { const stage = account.data?.lifecycle_stage const score = account.data?.lead_score ?? 0 const temp = account.data?.temperature const ratings = account.data?.ratings const attr = account.data?.attribution const queue = account.data?.queue return (
{/* Header Stats */}
Lifecycle Stage
{stage ? ( {stage.replace(/_/g, ' ')} ) : ( Not set )}
Lead Score
= 70 ? 'bg-green-500' : score >= 40 ? 'bg-yellow-500' : 'bg-gray-400'}`} style={{ width: `${Math.min(score, 100)}%` }} />
{score}
Last Signal
{account.data?.last_signal_at ? new Date(account.data.last_signal_at).toLocaleDateString() : 'Never' }
{/* Temperature Badge */} {temp && (
Temperature: {temp}
)} {/* Queue Status */} {queue?.pending_opportunity_id && (
Opportunity in Queue

Type: {queue.primary_opportunity_type?.replace(/_/g, ' ') || 'Unknown'}

)} {/* Stage Ratings */} {ratings && (

Stage Ratings

{ratings.anonymous && (
Anonymous
{Array.from({ length: 5 }).map((_, i) => (
))}
{ratings.anonymous.raw_score}
)} {ratings.identified && (
Identified
{Array.from({ length: 5 }).map((_, i) => (
))}
{ratings.identified.raw_score}
)} {ratings.engaged && (
Engaged
{Array.from({ length: 5 }).map((_, i) => (
))}
{ratings.engaged.raw_score}
)}
)} {/* Attribution */} {(attr?.anonymous_first_touch || attr?.identified_first_touch) && (

Attribution

{attr.anonymous_first_touch && (
Anonymous First Touch {attr.anonymous_first_touch.referrer || 'Direct'} {attr.anonymous_first_touch.at ? new Date(attr.anonymous_first_touch.at).toLocaleDateString() : ''}
)} {attr.identified_first_touch && (
Identified First Touch {attr.identified_first_touch.referrer || 'Direct'} {attr.identified_first_touch.at ? new Date(attr.identified_first_touch.at).toLocaleDateString() : ''}
)}
)} {/* Empty State */} {!stage && !score && !temp && !ratings && !queue?.pending_opportunity_id && (

No funnel data yet.

Signals will appear here as they are processed.

)}
) } export default function AccountDetailPage() { const { id } = useParams<{ id: string }>() const navigate = useNavigate() const appPath = useAppPath() const [account, setAccount] = useState(null) const [loading, setLoading] = useState(true) useEffect(() => { if (!id) return apiFetch(`/api/admin-data?action=get&entity=accounts&id=${id}`) .then(r => r.json()).then(j => setAccount(j?.data ?? j ?? null)).catch(() => setAccount(null)).finally(() => setLoading(false)) }, [id]) if (loading) return
if (!account) return
Account not found.
return (
{(account.display_name || account.slug).charAt(0).toUpperCase()}

{account.display_name || account.slug}

{account.slug}

{account.data?.segment && {account.data.segment}}
{[ { value: 'people', label: 'People', icon: User }, { value: 'funnel', label: 'Funnel', icon: Funnel }, { value: 'tickets', label: 'Tickets', icon: Ticket }, { value: 'deals', label: 'Deals', icon: Handshake }, { value: 'health', label: 'Health', icon: Heart }, { value: 'activity', label: 'Activity', icon: Activity }, ].map(tab => ( {tab.label} ))}
) }