'use client' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table' import { Trophy, AlertTriangle, Lightbulb, Brain, Flame, Wrench, Clock, MessageSquare, FolderOpen, LayoutList, DollarSign, Terminal, Zap, Search, Ban, Calendar, } from 'lucide-react' import { formatCost, formatDuration, formatNumber, formatTokens } from '@/lib/format' import type { ReportContent } from '@/lib/report' import type { CoachInsight, InsightSeverity, InsightCategory } from '@/lib/coach' // ─── Score Ring ────────────────────────────────────────────────────── function ScoreRing({ score, size = 140 }: { score: number; size?: number }) { const radius = (size - 14) / 2 const circumference = 2 * Math.PI * radius const offset = circumference - (score / 100) * circumference const getColor = (s: number) => { if (s >= 85) return 'var(--chart-2)' if (s >= 70) return 'var(--chart-1)' if (s >= 55) return 'var(--chart-3)' return 'var(--chart-5)' } return ( {score} / 100 ) } // ─── Insight Card ──────────────────────────────────────────────────── const SEVERITY_BORDER: Record = { achievement: 'border-l-chart-2', warning: 'border-l-chart-5', tip: 'border-l-chart-1', } const SEVERITY_ICON: Record = { achievement: Trophy, warning: AlertTriangle, tip: Lightbulb, } function InsightCard({ insight }: { insight: CoachInsight }) { const Icon = SEVERITY_ICON[insight.severity] return ( {insight.title} {insight.description} {insight.recommendation && ( {insight.recommendation} )} {insight.metric && ( {insight.metric} )} ) } // ─── Main Report View ──────────────────────────────────────────────── export function ReportView({ content }: { content: ReportContent }) { const g = content.atAGlance return ( {/* At a Glance */} At a Glance {g.dateRange.from} to {g.dateRange.to} Fitness: {g.scoreLabel} {g.currentStreak > 0 ? `${g.currentStreak}d streak` : 'No active streak'} {g.longestStreak > 0 && (best: {g.longestStreak}d)} Sessions{formatNumber(g.totalSessions)} Projects{formatNumber(g.totalProjects)} Messages{formatNumber(g.totalMessages)} Total Time{formatDuration(g.totalDurationMinutes)} Tool Calls{formatNumber(g.totalToolCalls)} Total Cost{formatCost(g.totalCostUSD)} API Errors{formatNumber(g.totalApiErrors)} Interruptions{formatNumber(g.totalUserInterruptions)} {/* Project Areas */} {content.projectAreas.length > 0 && ( What You Work On Top projects by session count Project Sessions Messages Duration Top Tools {content.projectAreas.map(p => ( {p.name} {p.sessions} {formatNumber(p.totalMessages)} {formatDuration(p.totalDurationMinutes)} {p.topTools.map(([name, count]) => `${name} (${count})`).join(', ')} ))} )} {/* Interaction Style */} How You Use Your Agent Interaction patterns and coding style {content.interactionStyle.mbtiType} {content.interactionStyle.mbtiDescription} Avg Messages/Session {Math.round(content.interactionStyle.avgMessagesPerSession)} Avg Duration {formatDuration(content.interactionStyle.avgDurationMinutes)} Read/Edit Ratio {content.interactionStyle.readEditRatio.toFixed(1)}x Bash Usage {Math.round(content.interactionStyle.bashRatio * 100)}% Subagent Calls {formatNumber(content.interactionStyle.agentCallsTotal)} Peak Hour {content.interactionStyle.peakHour}:00 Most Active Day {content.interactionStyle.mostActiveDay} Avg Cost/Session {formatCost(content.interactionStyle.avgCostPerSession)} {/* What Works */} {content.whatWorks.length > 0 && ( What's Working Patterns and habits that are paying off {content.whatWorks.map(i => )} )} {/* Friction Analysis */} {content.frictionAnalysis.length > 0 && ( Where Things Go Wrong Friction points that slow you down {content.frictionAnalysis.map(i => )} )} {/* Suggestions */} Suggestions Actionable ways to improve your workflow {/* CLAUDE.md rules */} {content.suggestions.claudeMdRules.length > 0 && ( Add to CLAUDE.md {content.suggestions.claudeMdRules.map((rule, i) => ( {rule} ))} )} {/* Coach tips */} {content.suggestions.coachTips.length > 0 && ( Workflow Tips {content.suggestions.coachTips.map(i => )} )} {/* Command tips */} {content.suggestions.commandTips.length > 0 && ( Commands to Discover {content.suggestions.commandTips.map(i => ( {i.title} {i.description} {i.recommendation && ( {i.recommendation} )} ))} )} ) }
{insight.description}
{i.description}