import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';
import { AppLayout } from '../../components/layout/AppLayout';
import { leadGenApi, type AdCreative } from '../../api/leadGen';
import { useAuth } from '../../contexts/AuthContext';
import {
ArrowLeft,
Loader2,
Trophy,
Eye,
MousePointer,
Target,
BarChart3,
Filter,
Search,
TrendingUp,
TrendingDown,
} from 'lucide-react';
export function CreativesLibraryPage() {
const navigate = useNavigate();
const { user } = useAuth();
const companyId = user?.company_id;
const [search, setSearch] = useState('');
const [verticalFilter, setVerticalFilter] = useState('');
const [sortBy, setSortBy] = useState<'ctr' | 'clicks' | 'conversions' | 'date'>('ctr');
const { data, isLoading } = useQuery({
queryKey: ['lead-gen-creatives', companyId, verticalFilter],
queryFn: () => leadGenApi.getCreatives(companyId!, {
vertical: verticalFilter || undefined,
}),
enabled: !!companyId,
});
const creatives = data?.data?.data?.creatives || [];
// Filter by search
const filtered = creatives.filter(c => {
if (!search) return true;
const s = search.toLowerCase();
return (
c.vertical.toLowerCase().includes(s) ||
c.service_type.toLowerCase().includes(s) ||
c.headlines.some(h => h.toLowerCase().includes(s)) ||
c.descriptions.some(d => d.toLowerCase().includes(s))
);
});
// Sort
const sorted = [...filtered].sort((a, b) => {
switch (sortBy) {
case 'ctr': return (b.avg_ctr || 0) - (a.avg_ctr || 0);
case 'clicks': return b.total_clicks - a.total_clicks;
case 'conversions': return b.total_conversions - a.total_conversions;
case 'date': return new Date(b.created_at).getTime() - new Date(a.created_at).getTime();
default: return 0;
}
});
const totalClicks = creatives.reduce((s, c) => s + c.total_clicks, 0);
const totalConversions = creatives.reduce((s, c) => s + c.total_conversions, 0);
const winners = creatives.filter(c => c.is_winner).length;
return (
<AppLayout title="Creatives Library">
<div className="max-w-6xl mx-auto">
{/* Header */}
<div className="flex items-center gap-4 mb-8">
<button
type="button"
onClick={() => navigate('/app/lead-gen')}
className="p-2 hover:bg-surface-100 rounded-lg transition-colors"
>
<ArrowLeft className="h-5 w-5" />
</button>
<div className="flex-1">
<h1 className="text-2xl font-bold text-surface-900">Creatives Library</h1>
<p className="text-sm text-surface-500">
Ad headlines, descriptions, and performance data
</p>
</div>
</div>
{/* Summary */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8">
<div className="rounded-xl border border-surface-200 bg-white p-4">
<div className="flex items-center gap-2 mb-2">
<BarChart3 className="h-4 w-4 text-blue-600" />
<span className="text-xs font-medium uppercase tracking-wider text-surface-400">Total</span>
</div>
<p className="text-xl font-bold text-surface-900">{creatives.length}</p>
</div>
<div className="rounded-xl border border-surface-200 bg-white p-4">
<div className="flex items-center gap-2 mb-2">
<Trophy className="h-4 w-4 text-amber-600" />
<span className="text-xs font-medium uppercase tracking-wider text-surface-400">Winners</span>
</div>
<p className="text-xl font-bold text-amber-600">{winners}</p>
</div>
<div className="rounded-xl border border-surface-200 bg-white p-4">
<div className="flex items-center gap-2 mb-2">
<MousePointer className="h-4 w-4 text-orange-600" />
<span className="text-xs font-medium uppercase tracking-wider text-surface-400">Clicks</span>
</div>
<p className="text-xl font-bold text-orange-600">{totalClicks.toLocaleString()}</p>
</div>
<div className="rounded-xl border border-surface-200 bg-white p-4">
<div className="flex items-center gap-2 mb-2">
<Target className="h-4 w-4 text-emerald-600" />
<span className="text-xs font-medium uppercase tracking-wider text-surface-400">Conversions</span>
</div>
<p className="text-xl font-bold text-emerald-600">{totalConversions}</p>
</div>
</div>
{/* Filters */}
<div className="flex flex-wrap items-center gap-3 mb-6">
<div className="relative flex-1 min-w-[200px]">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-surface-400" />
<input
type="text"
value={search}
onChange={e => setSearch(e.target.value)}
placeholder="Search headlines, descriptions..."
className="w-full rounded-lg border border-surface-200 pl-10 pr-3 py-2 text-sm focus:border-brand-500 focus:ring-2 focus:ring-brand-100"
/>
</div>
<div className="flex items-center gap-2">
<Filter className="h-4 w-4 text-surface-400" />
<select
value={verticalFilter}
onChange={e => setVerticalFilter(e.target.value)}
className="rounded-lg border border-surface-200 px-3 py-2 text-sm bg-white focus:border-brand-500"
>
<option value="">All verticals</option>
<option value="roofing">Roofing</option>
<option value="hvac">HVAC</option>
<option value="plumbing">Plumbing</option>
</select>
</div>
<select
value={sortBy}
onChange={e => setSortBy(e.target.value as typeof sortBy)}
className="rounded-lg border border-surface-200 px-3 py-2 text-sm bg-white focus:border-brand-500"
>
<option value="ctr">Sort: CTR</option>
<option value="clicks">Sort: Clicks</option>
<option value="conversions">Sort: Conversions</option>
<option value="date">Sort: Newest</option>
</select>
</div>
{/* Creatives Grid */}
{isLoading ? (
<div className="flex justify-center py-12">
<Loader2 className="h-8 w-8 animate-spin text-brand-500" />
</div>
) : sorted.length === 0 ? (
<div className="rounded-xl border border-surface-200 bg-white p-12 text-center">
<Eye className="h-8 w-8 mx-auto mb-3 text-surface-300" />
<p className="text-surface-500 font-medium">No creatives found</p>
<p className="text-sm text-surface-400 mt-1">
Creatives will appear here as campaigns run and generate performance data.
</p>
</div>
) : (
<div className="space-y-4">
{sorted.map(creative => (
<CreativeCard key={creative.id} creative={creative} />
))}
</div>
)}
</div>
</AppLayout>
);
}
function CreativeCard({ creative }: { creative: AdCreative }) {
const ctrDisplay = creative.avg_ctr ? `${creative.avg_ctr.toFixed(2)}%` : '—';
return (
<div className={`rounded-xl border-2 p-5 transition-all ${
creative.is_winner
? 'border-amber-200 bg-amber-50/50'
: 'border-surface-200 bg-white hover:border-surface-300'
}`}>
{/* Header */}
<div className="flex items-start justify-between mb-4">
<div className="flex items-center gap-3">
<div className={`flex h-8 w-8 items-center justify-center rounded-lg ${
creative.is_winner
? 'bg-amber-100 text-amber-700'
: 'bg-brand-50 text-brand-600'
}`}>
<span className="text-xs font-bold uppercase">{creative.ad_type.slice(0, 2)}</span>
</div>
<div>
<div className="flex items-center gap-2">
<h3 className="font-semibold text-surface-900 capitalize">{creative.service_type}</h3>
{creative.is_winner && (
<span className="inline-flex items-center gap-1 rounded-full bg-amber-100 px-2 py-0.5 text-xs font-medium text-amber-700">
<Trophy className="h-3 w-3" />
Winner
</span>
)}
</div>
<div className="flex items-center gap-2 text-xs text-surface-400">
<span className="capitalize">{creative.vertical}</span>
<span>·</span>
<span className="capitalize">{creative.ad_type}</span>
</div>
</div>
</div>
{/* Metrics */}
<div className="flex items-center gap-6 text-right">
<div>
<p className="text-xs text-surface-400">CTR</p>
<p className={`text-sm font-bold ${
creative.avg_ctr && creative.avg_ctr > 3 ? 'text-emerald-600' : 'text-surface-700'
}`}>{ctrDisplay}</p>
</div>
<div>
<p className="text-xs text-surface-400">Clicks</p>
<p className="text-sm font-bold text-surface-700">{creative.total_clicks.toLocaleString()}</p>
</div>
<div>
<p className="text-xs text-surface-400">Conv.</p>
<p className="text-sm font-bold text-emerald-600">{creative.total_conversions}</p>
</div>
</div>
</div>
{/* Headlines */}
{creative.headlines.length > 0 && (
<div className="mb-3">
<p className="text-xs font-medium uppercase tracking-wider text-surface-400 mb-2">
Headlines ({creative.headlines.length})
</p>
<div className="flex flex-wrap gap-1.5">
{creative.headlines.map((h, i) => (
<span key={i} className="inline-flex items-center rounded-md bg-surface-100 px-2.5 py-1 text-xs text-surface-700">
{h}
</span>
))}
</div>
</div>
)}
{/* Descriptions */}
{creative.descriptions.length > 0 && (
<div>
<p className="text-xs font-medium uppercase tracking-wider text-surface-400 mb-2">
Descriptions ({creative.descriptions.length})
</p>
<div className="space-y-1">
{creative.descriptions.map((d, i) => (
<p key={i} className="text-xs text-surface-500 leading-relaxed">{d}</p>
))}
</div>
</div>
)}
{/* Footer */}
<div className="mt-4 flex items-center justify-between border-t border-surface-100 pt-3">
<span className="text-xs text-surface-400">
{creative.total_impressions.toLocaleString()} impressions · Created {new Date(creative.created_at).toLocaleDateString()}
</span>
<div className="flex items-center gap-1 text-xs text-surface-400">
<Eye className="h-3 w-3" />
<span>{creative.total_impressions.toLocaleString()}</span>
</div>
</div>
</div>
);
}