// Analytics screen — KPIs, charts, per-post table. // Hand-rolled SVG line/bar charts (no external lib). const { useState: useStateAn, useMemo: useMemoAn } = React; function fmt(n) { if (n >= 1000000) return (n / 1000000).toFixed(1) + 'M'; if (n >= 1000) return (n / 1000).toFixed(1) + 'K'; return String(n); } function LineSpark({ data = [], color = '#0F0F0F', height = 80, width = 280 }) { if (!data.length) return null; const max = Math.max(...data, 1); const min = Math.min(...data, 0); const span = Math.max(1, max - min); const stepX = width / (data.length - 1 || 1); const pts = data.map((v, i) => [i * stepX, height - ((v - min) / span) * (height - 10) - 5]); const d = pts.map((p, i) => (i === 0 ? `M${p[0]},${p[1]}` : `L${p[0]},${p[1]}`)).join(' '); const area = d + ` L${width},${height} L0,${height} Z`; return ( ); } function BarSeries({ data = [], color = '#0F0F0F', height = 80, width = 280 }) { if (!data.length) return null; const max = Math.max(...data, 1); const bw = width / data.length; const gap = Math.min(4, bw * 0.25); return ( ); } function Analytics({ org, analytics, onOpenPost }) { const { Button, Card, Badge, Pill, SectionHead } = window.UI; const I = window.Icons; const [metric, setMetric] = useStateAn('reach'); // reach | impressions | clicks | comments const [range, setRange] = useStateAn('14d'); const [net, setNet] = useStateAn('all'); const METRICS = [ { id: 'reach', label: 'Охват', icon: 'Eye', tint: 'lavender' }, { id: 'impressions', label: 'Показы', icon: 'Layers', tint: 'sky' }, { id: 'clicks', label: 'Клики', icon: 'Link', tint: 'peach' }, { id: 'comments', label: 'Комментарии', icon: 'Text', tint: 'mint' }, ]; const tintBg = { lavender: 'bg-lavender-soft text-lavender-ink', sky: 'bg-sky-soft text-sky-ink', peach: 'bg-peach-soft text-peach-ink', mint: 'bg-mint-soft text-mint-ink', }; const tintCard = { lavender: 'bg-lavender-soft/40', sky: 'bg-sky-soft/40', peach: 'bg-peach-soft/45', mint: 'bg-mint-soft/40', }; const colors = { reach: 'oklch(0.52 0.22 285)', impressions: 'oklch(0.45 0.16 240)', clicks: 'oklch(0.55 0.16 50)', comments: 'oklch(0.50 0.14 165)' }; const filteredPosts = useMemoAn(() => { if (!analytics) return []; if (net === 'all') return analytics.posts; return analytics.posts.filter(p => p.network === net || p.network === 'both'); }, [analytics, net]); if (!analytics) { return (