import { useState, useEffect } from 'react' import { Link } from 'react-router-dom' import { BarChart3, Target, Clock, TrendingUp, CheckCircle } from 'lucide-react' import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, } from 'recharts' import { Spinner } from '@/components/common/Spinner' import { EmptyState } from '@/components/common/EmptyState' import { AnalyticsIllustration } from '@/components/common/EmptyStateIllustrations' import { analyticsApi } from '@/api' import { usePermissions } from '@/hooks/usePermissions' import type { PersonalAnalyticsResponse, AnalyticsPeriod } from '@/types' const OUTCOME_COLORS: Record = { 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' }, ] export default function MyAnalyticsPage() { const { isAccountOwner, isSuperAdmin } = usePermissions() const [period, setPeriod] = useState('30d') const [data, setData] = useState(null) const [loading, setLoading] = useState(true) useEffect(() => { // eslint-disable-next-line react-hooks/set-state-in-effect setLoading(true) analyticsApi .getPersonalAnalytics(period) .then(setData) .catch(console.error) .finally(() => setLoading(false)) }, [period]) if (loading) { return (
) } if (!data) { return (
} title="Analytics unavailable" description="Failed to load analytics data. Please try again." />
) } if (data.summary.total_sessions === 0) { return (
} title="Track your troubleshooting performance" description="Analytics show resolution times, common paths, and team efficiency. Data appears automatically as you complete sessions." action={ Run Your First Session } learnMoreLink="/guides/analytics" />
) } const { summary, time_series, top_flows } = data const outcomeBreakdown = summary.outcome_breakdown return (
{/* Header */}

My Analytics

{(isAccountOwner || isSuperAdmin) && ( Team Analytics )}
{/* Stat Cards */}
{/* Area Chart — Sessions over Time */}

My Sessions Over Time

{ const d = new Date(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(OUTCOME_COLORS).map(([key, color]) => (
{key}
))}
{/* Two-Column: Top Flows & Outcome Distribution */}
{/* My Top Flows */}

My Top Flows

{top_flows.length === 0 ? (

No flow data for this period.

) : (
{top_flows.map((flow) => ( ))}
Name Sessions Completion Median
{flow.name} {flow.sessions} {(flow.completion_rate * 100).toFixed(1)}% {flow.median_duration_minutes} min
)}
{/* Outcome Distribution */}

Outcome Distribution

{summary.total_sessions === 0 ? (

No session data for this period.

) : (
{( Object.entries(outcomeBreakdown) as [string, number][] ).map(([outcome, count]) => { const total = Object.values(outcomeBreakdown).reduce( (sum, v) => sum + v, 0 ) const pct = total > 0 ? (count / total) * 100 : 0 return (
{outcome}
{count} ({pct.toFixed(1)}%)
) })}
)}
) } function StatCard({ icon: Icon, label, value, }: { icon: React.ComponentType<{ size?: number; className?: string }> label: string value: string }) { return (
{label}

{value}

) }