{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "team-dashboard",
  "title": "Team Dashboard",
  "description": "Team dashboard with overview and metrics.",
  "registryDependencies": [
    "avatar",
    "badge",
    "button",
    "card",
    "progress",
    "separator"
  ],
  "files": [
    {
      "path": "registry/new-york/blocks/team/team-dashboard.tsx",
      "content": "\"use client\";\n\nimport {\n  Activity,\n  Bot,\n  FileText,\n  MessageSquare,\n  Plus,\n  Settings,\n  TrendingUp,\n  Users,\n} from \"lucide-react\";\nimport Link from \"next/link\";\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 { Button } from \"@/registry/new-york/ui/button\";\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 TeamMember {\n  id: string;\n  name: string;\n  avatar?: string;\n  role: \"owner\" | \"admin\" | \"member\" | \"viewer\";\n  status: \"active\" | \"away\" | \"offline\";\n}\n\nexport interface TeamActivity {\n  id: string;\n  type: \"member_joined\" | \"ai_session\" | \"file_uploaded\" | \"note_created\";\n  user: {\n    name: string;\n    avatar?: string;\n  };\n  description: string;\n  timestamp: Date;\n}\n\nexport interface TeamUsage {\n  aiTokens: {\n    used: number;\n    limit: number;\n  };\n  storage: {\n    used: number;\n    limit: number;\n  };\n  members: {\n    current: number;\n    limit: number;\n  };\n}\n\nexport interface TeamDashboardProps {\n  teamName: string;\n  teamAvatar?: string;\n  plan?: \"free\" | \"pro\" | \"enterprise\";\n  members?: TeamMember[];\n  recentActivities?: TeamActivity[];\n  usage?: TeamUsage;\n  onInviteMember?: () => void;\n  onManageSettings?: () => void;\n  className?: string;\n}\n\nfunction formatBytes(bytes: number): string {\n  if (bytes === 0) return \"0 Bytes\";\n  const k = 1024;\n  const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\"];\n  const i = Math.floor(Math.log(bytes) / Math.log(k));\n  return `${Math.round((bytes / k ** i) * 100) / 100} ${sizes[i]}`;\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 formatTimeAgo(date: Date): string {\n  const now = Date.now();\n  const diff = now - date.getTime();\n  const minutes = Math.floor(diff / 60_000);\n  const hours = Math.floor(minutes / 60);\n  const days = Math.floor(hours / 24);\n\n  if (minutes < 1) return \"Just now\";\n  if (minutes < 60) return `${minutes}m ago`;\n  if (hours < 24) return `${hours}h ago`;\n  if (days < 7) return `${days}d ago`;\n  return new Intl.DateTimeFormat(\"en-US\", {\n    month: \"short\",\n    day: \"numeric\",\n  }).format(date);\n}\n\nfunction getActivityIcon(type: TeamActivity[\"type\"]) {\n  switch (type) {\n    case \"member_joined\":\n      return Users;\n    case \"ai_session\":\n      return Bot;\n    case \"file_uploaded\":\n      return FileText;\n    case \"note_created\":\n      return MessageSquare;\n    default:\n      return Activity;\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 TeamDashboard({\n  teamName,\n  teamAvatar,\n  plan = \"free\",\n  members = [],\n  recentActivities = [],\n  usage,\n  onInviteMember,\n  onManageSettings,\n  className,\n}: TeamDashboardProps) {\n  const activeMembers = members.filter((m) => m.status === \"active\").length;\n  const onlineMembers = members.filter((m) => m.status === \"active\").length;\n\n  return (\n    <div className={cn(\"flex w-full flex-col gap-6\", className)}>\n      {/* Header */}\n      <div className=\"flex flex-col flex-wrap gap-4 md:flex-row md:items-center md:justify-between\">\n        <div className=\"flex items-center gap-4\">\n          <Avatar className=\"size-12\">\n            <AvatarImage alt={teamName} src={teamAvatar} />\n            <AvatarFallback>{getInitials(teamName)}</AvatarFallback>\n          </Avatar>\n          <div className=\"flex flex-col gap-1\">\n            <h1 className=\"font-semibold text-xl\">{teamName}</h1>\n            <div className=\"flex items-center gap-2\">\n              <Badge variant=\"secondary\">{plan}</Badge>\n              <span className=\"text-muted-foreground text-sm\">\n                {members.length} member{members.length !== 1 ? \"s\" : \"\"}\n              </span>\n            </div>\n          </div>\n        </div>\n        <div className=\"flex flex-wrap items-center gap-2\">\n          {onInviteMember && (\n            <Button onClick={onInviteMember} type=\"button\">\n              <Plus className=\"size-4\" />\n              Invite Member\n            </Button>\n          )}\n          {onManageSettings && (\n            <Button onClick={onManageSettings} type=\"button\" variant=\"outline\">\n              <Settings className=\"size-4\" />\n              Settings\n            </Button>\n          )}\n        </div>\n      </div>\n\n      {/* Usage Stats */}\n      {usage && (\n        <div className=\"grid gap-4 md:grid-cols-3\">\n          <Card className=\"shadow-xs\">\n            <CardHeader className=\"pb-3\">\n              <CardTitle className=\"font-medium text-sm\">AI Usage</CardTitle>\n              <CardDescription className=\"text-muted-foreground\">\n                How many AI tokens your team used this month.\n              </CardDescription>\n            </CardHeader>\n            <CardContent className=\"flex flex-col gap-2\">\n              <div className=\"flex items-baseline gap-2\">\n                <span className=\"font-semibold text-2xl\">\n                  {formatNumber(usage.aiTokens.used)}\n                </span>\n                <span className=\"text-muted-foreground text-sm\">\n                  / {formatNumber(usage.aiTokens.limit)} tokens\n                </span>\n              </div>\n              <Progress\n                value={(usage.aiTokens.used / usage.aiTokens.limit) * 100}\n              />\n            </CardContent>\n          </Card>\n\n          <Card className=\"shadow-xs\">\n            <CardHeader className=\"pb-3\">\n              <CardTitle className=\"font-medium text-sm\">Storage</CardTitle>\n              <CardDescription className=\"text-muted-foreground\">\n                Space your team is using for storing files.\n              </CardDescription>\n            </CardHeader>\n            <CardContent className=\"flex flex-col gap-2\">\n              <div className=\"flex items-baseline gap-2\">\n                <span className=\"font-semibold text-2xl\">\n                  {formatBytes(usage.storage.used)}\n                </span>\n                <span className=\"text-muted-foreground text-sm\">\n                  / {formatBytes(usage.storage.limit)}\n                </span>\n              </div>\n              <Progress\n                value={(usage.storage.used / usage.storage.limit) * 100}\n              />\n            </CardContent>\n          </Card>\n\n          <Card className=\"shadow-xs\">\n            <CardHeader className=\"pb-3\">\n              <CardTitle className=\"font-medium text-sm\">Members</CardTitle>\n              <CardDescription className=\"text-muted-foreground\">\n                Number of people in your current team.\n              </CardDescription>\n            </CardHeader>\n            <CardContent className=\"flex flex-col gap-2\">\n              <div className=\"flex items-baseline gap-2\">\n                <span className=\"font-semibold text-2xl\">\n                  {usage.members.current}\n                </span>\n                <span className=\"text-muted-foreground text-sm\">\n                  / {usage.members.limit} members\n                </span>\n              </div>\n              <Progress\n                value={(usage.members.current / usage.members.limit) * 100}\n              />\n            </CardContent>\n          </Card>\n        </div>\n      )}\n\n      <div className=\"grid gap-6 lg:grid-cols-2\">\n        {/* Quick Actions */}\n        <Card className=\"shadow-xs\">\n          <CardHeader>\n            <CardTitle>Quick Actions</CardTitle>\n            <CardDescription>Common team operations</CardDescription>\n          </CardHeader>\n          <CardContent>\n            <div className=\"grid gap-3 md:grid-cols-2\">\n              <Button\n                asChild\n                className=\"h-auto flex-col gap-2 py-4\"\n                variant=\"outline\"\n              >\n                <Link href=\"#chat\">\n                  <MessageSquare className=\"size-5\" />\n                  <span>Team Chat</span>\n                </Link>\n              </Button>\n              <Button\n                asChild\n                className=\"h-auto flex-col gap-2 py-4\"\n                variant=\"outline\"\n              >\n                <Link href=\"#ai-room\">\n                  <Bot className=\"size-5\" />\n                  <span>AI Room</span>\n                </Link>\n              </Button>\n              <Button\n                asChild\n                className=\"h-auto flex-col gap-2 py-4\"\n                variant=\"outline\"\n              >\n                <Link href=\"#files\">\n                  <FileText className=\"size-5\" />\n                  <span>Files</span>\n                </Link>\n              </Button>\n              <Button\n                asChild\n                className=\"h-auto flex-col gap-2 py-4\"\n                variant=\"outline\"\n              >\n                <Link href=\"#analytics\">\n                  <TrendingUp className=\"size-5\" />\n                  <span>Analytics</span>\n                </Link>\n              </Button>\n            </div>\n          </CardContent>\n        </Card>\n\n        {/* Active Members */}\n        <Card className=\"shadow-xs\">\n          <CardHeader>\n            <CardTitle>Active Members</CardTitle>\n            <CardDescription>\n              {onlineMembers} member{onlineMembers !== 1 ? \"s\" : \"\"} online\n            </CardDescription>\n          </CardHeader>\n          <CardContent>\n            {members.length === 0 ? (\n              <div className=\"flex flex-col items-center justify-center gap-2 py-8 text-center\">\n                <Users className=\"size-8 text-muted-foreground\" />\n                <p className=\"text-muted-foreground text-sm\">No members yet</p>\n              </div>\n            ) : (\n              <div className=\"flex flex-wrap gap-3\">\n                {members.slice(0, 8).map((member) => (\n                  <div\n                    className=\"flex flex-col items-center gap-2\"\n                    key={member.id}\n                  >\n                    <div className=\"relative\">\n                      <Avatar className=\"size-10\">\n                        <AvatarImage alt={member.name} src={member.avatar} />\n                        <AvatarFallback>\n                          {getInitials(member.name)}\n                        </AvatarFallback>\n                      </Avatar>\n                      {member.status === \"active\" && (\n                        <div className=\"absolute right-0 bottom-0 size-3 rounded-full border-2 border-background bg-green-500\" />\n                      )}\n                    </div>\n                    <span className=\"max-w-[60px] truncate text-xs\">\n                      {member.name}\n                    </span>\n                  </div>\n                ))}\n                {members.length > 8 && (\n                  <div className=\"flex flex-col items-center gap-2\">\n                    <div className=\"flex size-10 items-center justify-center rounded-full border bg-muted\">\n                      <span className=\"text-muted-foreground text-xs\">\n                        +{members.length - 8}\n                      </span>\n                    </div>\n                  </div>\n                )}\n              </div>\n            )}\n          </CardContent>\n        </Card>\n      </div>\n\n      {/* Recent Activity */}\n      {recentActivities.length > 0 && (\n        <Card className=\"shadow-xs\">\n          <CardHeader>\n            <CardTitle>Recent Activity</CardTitle>\n            <CardDescription>Latest team updates</CardDescription>\n          </CardHeader>\n          <CardContent>\n            <div className=\"flex flex-col gap-4\">\n              {recentActivities.slice(0, 5).map((activity, idx) => {\n                const Icon = getActivityIcon(activity.type);\n                return (\n                  <div key={activity.id}>\n                    <div className=\"flex items-start gap-3\">\n                      <Avatar className=\"size-8 shrink-0\">\n                        <AvatarImage\n                          alt={activity.user.name}\n                          src={activity.user.avatar}\n                        />\n                        <AvatarFallback className=\"text-xs\">\n                          {getInitials(activity.user.name)}\n                        </AvatarFallback>\n                      </Avatar>\n                      <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n                        <div className=\"flex items-center gap-2\">\n                          <span className=\"font-medium text-sm\">\n                            {activity.user.name}\n                          </span>\n                          <div className=\"flex size-4 items-center justify-center rounded-full text-muted-foreground\">\n                            <Icon className=\"size-3\" />\n                          </div>\n                        </div>\n                        <p className=\"text-muted-foreground text-sm\">\n                          {activity.description}\n                        </p>\n                        <span className=\"text-muted-foreground text-xs\">\n                          {formatTimeAgo(activity.timestamp)}\n                        </span>\n                      </div>\n                    </div>\n                    {idx < recentActivities.slice(0, 5).length - 1 && (\n                      <Separator className=\"mt-4\" />\n                    )}\n                  </div>\n                );\n              })}\n            </div>\n          </CardContent>\n        </Card>\n      )}\n    </div>\n  );\n}\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "block",
    "team"
  ],
  "type": "registry:ui"
}