Spaces:
Configuration error
Configuration error
| "use client" | |
| import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card" | |
| import { Badge } from "@/components/ui/badge" | |
| import { Progress } from "@/components/ui/progress" | |
| import { | |
| BarChart3, | |
| TrendingUp, | |
| TrendingDown, | |
| Users, | |
| Play, | |
| Star, | |
| GitFork, | |
| Eye, | |
| Clock, | |
| Zap | |
| } from "lucide-react" | |
| interface AnalyticsStat { | |
| label: string | |
| value: string | number | |
| change?: number | |
| changeLabel?: string | |
| icon: React.ReactNode | |
| } | |
| interface EnhancedAnalyticsProps { | |
| stats: { | |
| totalRuns: number | |
| totalStars: number | |
| totalRemixes: number | |
| totalViews: number | |
| averageResponseTime: number | |
| tokenUsage: number | |
| topPrompts: { title: string; runs: number; stars: number }[] | |
| runsByDay: { date: string; runs: number }[] | |
| modelUsage: { model: string; percentage: number }[] | |
| } | |
| } | |
| export function EnhancedAnalytics({ stats }: EnhancedAnalyticsProps) { | |
| const mainStats: AnalyticsStat[] = [ | |
| { | |
| label: "Total Runs", | |
| value: stats.totalRuns.toLocaleString(), | |
| change: 12.5, | |
| changeLabel: "vs last week", | |
| icon: <Play className="h-5 w-5 text-green-500" /> | |
| }, | |
| { | |
| label: "Total Stars", | |
| value: stats.totalStars.toLocaleString(), | |
| change: 8.3, | |
| changeLabel: "vs last week", | |
| icon: <Star className="h-5 w-5 text-yellow-500" /> | |
| }, | |
| { | |
| label: "Remixes", | |
| value: stats.totalRemixes.toLocaleString(), | |
| change: 25.0, | |
| changeLabel: "vs last week", | |
| icon: <GitFork className="h-5 w-5 text-purple-500" /> | |
| }, | |
| { | |
| label: "Total Views", | |
| value: stats.totalViews.toLocaleString(), | |
| change: -2.1, | |
| changeLabel: "vs last week", | |
| icon: <Eye className="h-5 w-5 text-blue-500" /> | |
| } | |
| ] | |
| return ( | |
| <div className="space-y-6"> | |
| {/* Main Stats Grid */} | |
| <div className="grid grid-cols-2 lg:grid-cols-4 gap-4"> | |
| {mainStats.map((stat, index) => ( | |
| <Card key={index}> | |
| <CardContent className="p-4"> | |
| <div className="flex items-center justify-between mb-2"> | |
| {stat.icon} | |
| {stat.change !== undefined && ( | |
| <Badge | |
| variant="outline" | |
| className={stat.change >= 0 ? "text-green-500" : "text-red-500"} | |
| > | |
| {stat.change >= 0 ? ( | |
| <TrendingUp className="h-3 w-3 mr-1" /> | |
| ) : ( | |
| <TrendingDown className="h-3 w-3 mr-1" /> | |
| )} | |
| {Math.abs(stat.change)}% | |
| </Badge> | |
| )} | |
| </div> | |
| <p className="text-2xl font-bold">{stat.value}</p> | |
| <p className="text-sm text-muted-foreground">{stat.label}</p> | |
| </CardContent> | |
| </Card> | |
| ))} | |
| </div> | |
| {/* Performance Metrics */} | |
| <div className="grid md:grid-cols-2 gap-6"> | |
| <Card> | |
| <CardHeader> | |
| <CardTitle className="text-lg flex items-center gap-2"> | |
| <Clock className="h-5 w-5" /> | |
| Performance Metrics | |
| </CardTitle> | |
| </CardHeader> | |
| <CardContent className="space-y-4"> | |
| <div> | |
| <div className="flex items-center justify-between mb-2"> | |
| <span className="text-sm">Avg Response Time</span> | |
| <span className="font-medium">{stats.averageResponseTime}ms</span> | |
| </div> | |
| <Progress | |
| value={Math.min((stats.averageResponseTime / 5000) * 100, 100)} | |
| className="h-2" | |
| /> | |
| <p className="text-xs text-muted-foreground mt-1"> | |
| {stats.averageResponseTime < 2000 ? "Excellent" : | |
| stats.averageResponseTime < 4000 ? "Good" : "Needs improvement"} | |
| </p> | |
| </div> | |
| <div> | |
| <div className="flex items-center justify-between mb-2"> | |
| <span className="text-sm">Token Efficiency</span> | |
| <span className="font-medium">{(stats.tokenUsage / 1000).toFixed(1)}k tokens</span> | |
| </div> | |
| <Progress value={75} className="h-2" /> | |
| <p className="text-xs text-muted-foreground mt-1">Above average efficiency</p> | |
| </div> | |
| </CardContent> | |
| </Card> | |
| <Card> | |
| <CardHeader> | |
| <CardTitle className="text-lg flex items-center gap-2"> | |
| <Zap className="h-5 w-5" /> | |
| Model Usage | |
| </CardTitle> | |
| </CardHeader> | |
| <CardContent className="space-y-3"> | |
| {stats.modelUsage.map((model, index) => ( | |
| <div key={index}> | |
| <div className="flex items-center justify-between mb-1"> | |
| <span className="text-sm">{model.model}</span> | |
| <span className="text-sm font-medium">{model.percentage}%</span> | |
| </div> | |
| <Progress value={model.percentage} className="h-2" /> | |
| </div> | |
| ))} | |
| </CardContent> | |
| </Card> | |
| </div> | |
| {/* Top Prompts */} | |
| <Card> | |
| <CardHeader> | |
| <CardTitle className="text-lg flex items-center gap-2"> | |
| <BarChart3 className="h-5 w-5" /> | |
| Top Performing Prompts | |
| </CardTitle> | |
| <CardDescription>Your most popular prompts by runs</CardDescription> | |
| </CardHeader> | |
| <CardContent> | |
| <div className="space-y-4"> | |
| {stats.topPrompts.map((prompt, index) => ( | |
| <div key={index} className="flex items-center gap-4"> | |
| <div className="h-8 w-8 rounded-full bg-primary/10 flex items-center justify-center text-primary font-medium"> | |
| {index + 1} | |
| </div> | |
| <div className="flex-1 min-w-0"> | |
| <p className="font-medium truncate">{prompt.title}</p> | |
| <div className="flex items-center gap-3 text-sm text-muted-foreground"> | |
| <span className="flex items-center gap-1"> | |
| <Play className="h-3 w-3" /> | |
| {prompt.runs} runs | |
| </span> | |
| <span className="flex items-center gap-1"> | |
| <Star className="h-3 w-3" /> | |
| {prompt.stars} stars | |
| </span> | |
| </div> | |
| </div> | |
| <Progress | |
| value={(prompt.runs / stats.topPrompts[0].runs) * 100} | |
| className="w-24 h-2" | |
| /> | |
| </div> | |
| ))} | |
| </div> | |
| </CardContent> | |
| </Card> | |
| {/* Activity Chart (Simple Bar Representation) */} | |
| <Card> | |
| <CardHeader> | |
| <CardTitle className="text-lg">Weekly Activity</CardTitle> | |
| <CardDescription>Runs per day over the last 7 days</CardDescription> | |
| </CardHeader> | |
| <CardContent> | |
| <div className="flex items-end gap-2 h-32"> | |
| {stats.runsByDay.map((day, index) => { | |
| const maxRuns = Math.max(...stats.runsByDay.map(d => d.runs)) | |
| const height = (day.runs / maxRuns) * 100 | |
| return ( | |
| <div key={index} className="flex-1 flex flex-col items-center"> | |
| <div | |
| className="w-full bg-primary rounded-t transition-all hover:bg-primary/80" | |
| style={{ height: `${height}%`, minHeight: '4px' }} | |
| /> | |
| <span className="text-xs text-muted-foreground mt-2"> | |
| {day.date} | |
| </span> | |
| </div> | |
| ) | |
| })} | |
| </div> | |
| </CardContent> | |
| </Card> | |
| </div> | |
| ) | |
| } | |