import { useState, useEffect } from 'react' import { Loader2, Star } from 'lucide-react' import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, } from 'recharts' import { analyticsApi } from '@/api' import { cn } from '@/lib/utils' import type { FlowAnalyticsResponse, AnalyticsPeriod } from '@/types' const CHART_COLORS = { resolved: '#34d399', escalated: '#f87171', workaround: '#eab308', unresolved: '#94a3b8', } const PERIOD_OPTIONS: { value: AnalyticsPeriod; label: string }[] = [ { value: '7d', label: 'Last 7 days' }, { value: '30d', label: 'Last 30 days' }, { value: '90d', label: 'Last 90 days' }, ] interface FlowAnalyticsPanelProps { treeId: string } export function FlowAnalyticsPanel({ treeId }: FlowAnalyticsPanelProps) { const [period, setPeriod] = useState('30d') const [data, setData] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(false) useEffect(() => { // eslint-disable-next-line react-hooks/set-state-in-effect setLoading(true) // eslint-disable-next-line react-hooks/set-state-in-effect setError(false) analyticsApi .getFlowAnalytics(treeId, period) .then(setData) .catch(() => { setError(true) setData(null) }) .finally(() => setLoading(false)) }, [treeId, period]) if (loading) { return (
) } if (error || !data) { return (
No analytics data available for this flow.
) } const { summary, avg_csat, total_ratings, time_series, step_feedback, recent_comments } = data return (
{/* Period selector */}

Flow Analytics

{/* Summary stat cards */}
0 ? `${total_ratings} rating${total_ratings !== 1 ? 's' : ''}` : undefined} />
{/* Area chart - Sessions over time */} {time_series.length > 0 && (

Sessions Over Time

{ const d = new Date(String(value)) return `${d.getMonth() + 1}/${d.getDate()}` }} /> { const d = new Date(String(value)) return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric', }) }} /> {/* Chart legend */}
{Object.entries(CHART_COLORS).map(([key, color]) => (
{key}
))}
)} {/* Step Feedback Table with Dropoff Metrics */} {step_feedback.length > 0 && (

Step Performance

{step_feedback.map((step) => ( 0.2 && 'bg-red-400/5' )} > ))}
Step Visits Dropoffs Dropoff Rate
{step.node_title} {step.visit_count} {step.dropoff_count} 0.2 ? 'text-red-400' : 'text-muted-foreground' )} > {(step.dropoff_rate * 100).toFixed(1)}%
)} {/* Recent Comments (Anonymous) */} {recent_comments.length > 0 && (

Recent Feedback

{recent_comments.map((item, i) => (
{[1, 2, 3, 4, 5].map((v) => ( ))}
{item.comment && (

{item.comment}

)}

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

))}
)}
) } function StatCard({ label, value, subtitle, }: { label: string value: string | number subtitle?: string }) { return (

{label}

{value}

{subtitle && (

{subtitle}

)}
) }