{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "team-analytics",
  "title": "Team Analytics",
  "description": "View team analytics and usage statistics with charts and breakdowns.",
  "registryDependencies": [
    "avatar",
    "badge",
    "card",
    "progress",
    "separator"
  ],
  "files": [
    {
      "path": "registry/new-york/blocks/team/team-analytics.tsx",
      "content": "\"use client\";\n\nimport { ArrowDown, ArrowUp, TrendingUp } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport {\n  Avatar,\n  AvatarFallback,\n  AvatarImage,\n} from \"@/registry/new-york/ui/avatar\";\nimport { Badge } from \"@/registry/new-york/ui/badge\";\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/registry/new-york/ui/card\";\nimport { Progress } from \"@/registry/new-york/ui/progress\";\nimport { Separator } from \"@/registry/new-york/ui/separator\";\n\nexport interface AnalyticsDataPoint {\n  date: Date;\n  value: number;\n  category?: string;\n}\n\nexport interface MemberUsage {\n  id: string;\n  name: string;\n  avatar?: string;\n  tokens: number;\n  sessions: number;\n  files: number;\n}\n\nexport interface TeamAnalyticsProps {\n  period?: \"7d\" | \"30d\" | \"90d\" | \"all\";\n  tokenUsage?: {\n    current: number;\n    previous: number;\n    dataPoints?: AnalyticsDataPoint[];\n  };\n  sessionCount?: {\n    current: number;\n    previous: number;\n    dataPoints?: AnalyticsDataPoint[];\n  };\n  memberUsage?: MemberUsage[];\n  topProjects?: {\n    id: string;\n    name: string;\n    usage: number;\n  }[];\n  className?: string;\n}\n\nfunction formatNumber(num: number): string {\n  if (num >= 1_000_000) {\n    return `${(num / 1_000_000).toFixed(1)}M`;\n  }\n  if (num >= 1000) {\n    return `${(num / 1000).toFixed(1)}K`;\n  }\n  return num.toString();\n}\n\nfunction calculateChange(\n  current: number,\n  previous: number\n): {\n  percentage: number;\n  isIncrease: boolean;\n} {\n  if (previous === 0) {\n    return { percentage: current > 0 ? 100 : 0, isIncrease: current > 0 };\n  }\n  const change = ((current - previous) / previous) * 100;\n  return {\n    percentage: Math.abs(change),\n    isIncrease: change > 0,\n  };\n}\n\nfunction getInitials(name: string): string {\n  return name\n    .split(\" \")\n    .map((n) => n[0])\n    .join(\"\")\n    .toUpperCase()\n    .slice(0, 2);\n}\n\nexport default function TeamAnalytics({\n  period = \"30d\",\n  tokenUsage,\n  sessionCount,\n  memberUsage = [],\n  topProjects = [],\n  className,\n}: TeamAnalyticsProps) {\n  const tokenChange = tokenUsage\n    ? calculateChange(tokenUsage.current, tokenUsage.previous)\n    : null;\n\n  const sessionChange = sessionCount\n    ? calculateChange(sessionCount.current, sessionCount.previous)\n    : null;\n\n  const sortedMemberUsage = [...memberUsage]\n    .sort((a, b) => b.tokens - a.tokens)\n    .slice(0, 5);\n\n  const sortedProjects = [...topProjects]\n    .sort((a, b) => b.usage - a.usage)\n    .slice(0, 5);\n\n  const maxMemberTokens = Math.max(...memberUsage.map((m) => m.tokens), 1);\n\n  return (\n    <div className={cn(\"flex w-full flex-col gap-6\", className)}>\n      {/* Overview Cards */}\n      <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-4\">\n        {tokenUsage && (\n          <Card className=\"gap-4 shadow-xs\">\n            <CardHeader>\n              <CardTitle className=\"font-medium text-sm\">AI Tokens</CardTitle>\n              <CardDescription className=\"text-muted-foreground\">\n                Total AI tokens used\n              </CardDescription>\n            </CardHeader>\n            <CardContent>\n              <div className=\"flex items-baseline gap-2\">\n                <span className=\"font-semibold text-2xl\">\n                  {formatNumber(tokenUsage.current)}\n                </span>\n                {tokenChange && (\n                  <div\n                    className={cn(\n                      \"flex items-center gap-1 text-xs\",\n                      tokenChange.isIncrease ? \"text-green-600\" : \"text-red-600\"\n                    )}\n                  >\n                    {tokenChange.isIncrease ? (\n                      <ArrowUp className=\"size-3\" />\n                    ) : (\n                      <ArrowDown className=\"size-3\" />\n                    )}\n                    {tokenChange.percentage.toFixed(1)}%\n                  </div>\n                )}\n              </div>\n              <p className=\"text-muted-foreground text-xs\">\n                vs previous period\n              </p>\n            </CardContent>\n          </Card>\n        )}\n\n        {sessionCount && (\n          <Card className=\"gap-4 shadow-xs\">\n            <CardHeader>\n              <CardTitle className=\"font-medium text-sm\">AI Sessions</CardTitle>\n              <CardDescription className=\"text-muted-foreground\">\n                Total AI sessions used\n              </CardDescription>\n            </CardHeader>\n            <CardContent>\n              <div className=\"flex items-baseline gap-2\">\n                <span className=\"font-semibold text-2xl\">\n                  {sessionCount.current}\n                </span>\n                {sessionChange && (\n                  <div\n                    className={cn(\n                      \"flex items-center gap-1 text-xs\",\n                      sessionChange.isIncrease\n                        ? \"text-green-600\"\n                        : \"text-red-600\"\n                    )}\n                  >\n                    {sessionChange.isIncrease ? (\n                      <ArrowUp className=\"size-3\" />\n                    ) : (\n                      <ArrowDown className=\"size-3\" />\n                    )}\n                    {sessionChange.percentage.toFixed(1)}%\n                  </div>\n                )}\n              </div>\n              <p className=\"text-muted-foreground text-xs\">\n                vs previous period\n              </p>\n            </CardContent>\n          </Card>\n        )}\n\n        <Card className=\"gap-4 shadow-xs\">\n          <CardHeader>\n            <CardTitle className=\"font-medium text-sm\">\n              Active Members\n            </CardTitle>\n            <CardDescription className=\"text-muted-foreground\">\n              Total active members\n            </CardDescription>\n          </CardHeader>\n          <CardContent>\n            <div className=\"flex items-baseline gap-2\">\n              <span className=\"font-semibold text-2xl\">\n                {memberUsage.length}\n              </span>\n            </div>\n            <p className=\"text-muted-foreground text-xs\">\n              Members with activity\n            </p>\n          </CardContent>\n        </Card>\n\n        <Card className=\"gap-4 shadow-xs\">\n          <CardHeader>\n            <CardTitle className=\"font-medium text-sm\">Projects</CardTitle>\n            <CardDescription className=\"text-muted-foreground\">\n              Total projects\n            </CardDescription>\n          </CardHeader>\n          <CardContent>\n            <div className=\"flex items-baseline gap-2\">\n              <span className=\"font-semibold text-2xl\">\n                {topProjects.length}\n              </span>\n            </div>\n            <p className=\"text-muted-foreground text-xs\">Active projects</p>\n          </CardContent>\n        </Card>\n      </div>\n\n      <div className=\"grid gap-6 lg:grid-cols-2\">\n        {/* Top Members */}\n        {sortedMemberUsage.length > 0 && (\n          <Card className=\"gap-4 shadow-xs\">\n            <CardHeader>\n              <CardTitle>Top Members by Usage</CardTitle>\n              <CardDescription>Most active team members</CardDescription>\n            </CardHeader>\n            <CardContent>\n              <div className=\"flex flex-col gap-4\">\n                {sortedMemberUsage.map((member) => {\n                  const percentage = (member.tokens / maxMemberTokens) * 100;\n                  return (\n                    <div className=\"flex flex-col gap-2\" key={member.id}>\n                      <div className=\"flex items-center justify-between\">\n                        <div className=\"flex items-center gap-2\">\n                          <Avatar className=\"size-8\">\n                            <AvatarImage\n                              alt={member.name}\n                              src={member.avatar}\n                            />\n                            <AvatarFallback className=\"text-xs\">\n                              {getInitials(member.name)}\n                            </AvatarFallback>\n                          </Avatar>\n                          <div className=\"flex flex-col\">\n                            <span className=\"font-medium text-sm\">\n                              {member.name}\n                            </span>\n                            <span className=\"text-muted-foreground text-xs\">\n                              {member.sessions} session\n                              {member.sessions !== 1 ? \"s\" : \"\"}\n                            </span>\n                          </div>\n                        </div>\n                        <div className=\"flex flex-col items-end\">\n                          <span className=\"font-medium text-sm\">\n                            {formatNumber(member.tokens)}\n                          </span>\n                          <span className=\"text-muted-foreground text-xs\">\n                            tokens\n                          </span>\n                        </div>\n                      </div>\n                      <Progress value={percentage} />\n                    </div>\n                  );\n                })}\n              </div>\n            </CardContent>\n          </Card>\n        )}\n\n        {/* Top Projects */}\n        {sortedProjects.length > 0 && (\n          <Card className=\"shadow-xs\">\n            <CardHeader>\n              <CardTitle>Top Projects</CardTitle>\n              <CardDescription>Most active projects</CardDescription>\n            </CardHeader>\n            <CardContent>\n              <div className=\"flex flex-col gap-3\">\n                {sortedProjects.map((project, idx) => {\n                  const maxUsage = Math.max(\n                    ...sortedProjects.map((p) => p.usage),\n                    1\n                  );\n                  const percentage = (project.usage / maxUsage) * 100;\n                  return (\n                    <div key={project.id}>\n                      <div className=\"flex items-center justify-between\">\n                        <div className=\"flex items-center gap-2\">\n                          <div className=\"flex size-8 items-center justify-center rounded-full bg-primary/10\">\n                            <TrendingUp className=\"size-4 text-primary\" />\n                          </div>\n                          <span className=\"font-medium text-sm\">\n                            {project.name}\n                          </span>\n                        </div>\n                        <Badge variant=\"secondary\">\n                          {formatNumber(project.usage)} tokens\n                        </Badge>\n                      </div>\n                      {idx < sortedProjects.length - 1 && (\n                        <Separator className=\"mt-3\" />\n                      )}\n                    </div>\n                  );\n                })}\n              </div>\n            </CardContent>\n          </Card>\n        )}\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "block",
    "team"
  ],
  "type": "registry:ui"
}