{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "table-04",
  "type": "registry:block",
  "title": "Table with Grouped Rows",
  "description": "A table with grouped rows block.",
  "author": "ephraim duncan <https://ephraimduncan.com>",
  "registryDependencies": [
    "avatar",
    "badge",
    "table"
  ],
  "dependencies": [],
  "files": [
    {
      "path": "content/components/tables/table-04.tsx",
      "type": "registry:component",
      "target": "components/table-04.tsx",
      "content": "'use client';\n\nimport { Fragment } from 'react';\nimport { Avatar, AvatarFallback } from '@/components/ui/avatar';\nimport { Badge } from '@/components/ui/badge';\nimport {\n  Table,\n  TableBody,\n  TableCell,\n  TableHead,\n  TableHeader,\n  TableRow,\n} from '@/components/ui/table';\nimport { cn } from '@/lib/utils';\n\ninterface AssignedPerson {\n  name: string;\n  initials: string;\n}\n\ninterface TaskItem {\n  id: string;\n  task: string;\n  budget: string;\n  deadline: string;\n  assigned: AssignedPerson[];\n  status: string;\n}\n\ninterface TaskGroup {\n  name: string;\n  items: TaskItem[];\n}\n\ntype StatusVariant = 'success' | 'warning' | 'default' | 'secondary';\n\nconst avatarColors = [\n  'bg-blue-500',\n  'bg-purple-500',\n  'bg-emerald-500',\n  'bg-cyan-500',\n  'bg-rose-500',\n  'bg-indigo-500',\n];\n\nfunction getAvatarColor(initials: string) {\n  const seed = initials\n    .split('')\n    .reduce((acc, char) => acc + char.charCodeAt(0), 0);\n  return avatarColors[seed % avatarColors.length];\n}\n\nfunction AvatarStack({ people }: { people: AssignedPerson[] }) {\n  return (\n    <div className=\"-space-x-2 flex\">\n      {people.map((person, index) => (\n        <Avatar\n          className={cn(\n            'h-6 w-6 border-2 border-background text-[10px]',\n            getAvatarColor(person.initials)\n          )}\n          key={index}\n        >\n          <AvatarFallback\n            className={cn(\n              'font-medium text-white',\n              getAvatarColor(person.initials)\n            )}\n          >\n            {person.initials}\n          </AvatarFallback>\n        </Avatar>\n      ))}\n    </div>\n  );\n}\n\nconst statusStyles: Record<StatusVariant, { badge: string; dot: string }> = {\n  success: {\n    badge:\n      'bg-emerald-50 text-emerald-700 dark:bg-emerald-950 dark:text-emerald-300',\n    dot: 'bg-emerald-500',\n  },\n  warning: {\n    badge: 'bg-amber-50 text-amber-700 dark:bg-amber-950 dark:text-amber-300',\n    dot: 'bg-amber-500',\n  },\n  default: {\n    badge: 'bg-blue-50 text-blue-700 dark:bg-blue-950 dark:text-blue-300',\n    dot: 'bg-blue-500',\n  },\n  secondary: {\n    badge: 'bg-muted text-muted-foreground',\n    dot: 'bg-muted-foreground',\n  },\n};\n\nfunction StatusBadge({\n  status,\n  variant = 'default',\n}: {\n  status: string;\n  variant?: StatusVariant;\n}) {\n  const styles = statusStyles[variant];\n  return (\n    <Badge\n      className={cn('gap-1.5 rounded-full', styles.badge)}\n      variant=\"outline\"\n    >\n      <span\n        aria-hidden=\"true\"\n        className={cn('size-1.5 rounded-full', styles.dot)}\n      />\n      {status}\n    </Badge>\n  );\n}\n\nconst data: TaskGroup[] = [\n  {\n    name: 'Engineering',\n    items: [\n      {\n        id: '1',\n        task: 'API Integration Overhaul',\n        budget: '$32,000',\n        deadline: 'Dec 15, 2024',\n        assigned: [\n          { name: 'Marcus Chen', initials: 'MC' },\n          { name: 'Priya Sharma', initials: 'PS' },\n        ],\n        status: 'In Progress',\n      },\n      {\n        id: '2',\n        task: 'Database Migration',\n        budget: '$18,500',\n        deadline: 'Jan 20, 2025',\n        assigned: [{ name: 'David Kim', initials: 'DK' }],\n        status: 'Completed',\n      },\n      {\n        id: '3',\n        task: 'Mobile App Redesign',\n        budget: '$55,000',\n        deadline: 'Feb 28, 2025',\n        assigned: [\n          { name: 'Lena Rodriguez', initials: 'LR' },\n          { name: 'Tom Anderson', initials: 'TA' },\n          { name: 'Nina Patel', initials: 'NP' },\n        ],\n        status: 'Planning',\n      },\n    ],\n  },\n  {\n    name: 'Marketing',\n    items: [\n      {\n        id: '4',\n        task: 'Q1 Campaign Launch',\n        budget: '$24,000',\n        deadline: 'Jan 5, 2025',\n        assigned: [\n          { name: 'Rachel Green', initials: 'RG' },\n          { name: 'Chris Evans', initials: 'CE' },\n        ],\n        status: 'In Progress',\n      },\n      {\n        id: '5',\n        task: 'Brand Refresh Project',\n        budget: '$42,000',\n        deadline: 'Mar 1, 2025',\n        assigned: [{ name: 'Monica Geller', initials: 'MG' }],\n        status: 'Planning',\n      },\n    ],\n  },\n  {\n    name: 'Operations',\n    items: [\n      {\n        id: '6',\n        task: 'Vendor Contract Review',\n        budget: '$8,000',\n        deadline: 'Dec 30, 2024',\n        assigned: [\n          { name: 'Joe Tribbiani', initials: 'JT' },\n          { name: 'Phoebe Buffay', initials: 'PB' },\n        ],\n        status: 'Completed',\n      },\n      {\n        id: '7',\n        task: 'Office Expansion Setup',\n        budget: '$120,000',\n        deadline: 'Apr 15, 2025',\n        assigned: [{ name: 'Ross Geller', initials: 'RG' }],\n        status: 'On Hold',\n      },\n    ],\n  },\n];\n\nfunction getStatusVariant(status: string): StatusVariant {\n  switch (status) {\n    case 'Completed':\n      return 'success';\n    case 'In Progress':\n      return 'default';\n    case 'Planning':\n      return 'secondary';\n    case 'On Hold':\n      return 'warning';\n    default:\n      return 'default';\n  }\n}\n\nexport default function Table04() {\n  return (\n    <div className=\"rounded-lg border\">\n      <Table>\n        <TableHeader>\n          <TableRow>\n            <TableHead className=\"w-48 font-medium\">Task</TableHead>\n            <TableHead className=\"font-medium\">Budget</TableHead>\n            <TableHead className=\"font-medium\">Deadline</TableHead>\n            <TableHead className=\"font-medium\">Assigned</TableHead>\n            <TableHead className=\"w-28 font-medium\">Status</TableHead>\n          </TableRow>\n        </TableHeader>\n        <TableBody>\n          {data.map((group) => (\n            <Fragment key={group.name}>\n              <TableRow className=\"bg-muted/50 hover:bg-muted/50\">\n                <TableCell className=\"py-2 font-semibold\" colSpan={5}>\n                  {group.name}\n                  <span className=\"ml-2 font-normal text-muted-foreground\">\n                    {group.items.length}\n                  </span>\n                </TableCell>\n              </TableRow>\n              {group.items.map((item) => (\n                <TableRow key={item.id}>\n                  <TableCell className=\"font-medium\">{item.task}</TableCell>\n                  <TableCell>{item.budget}</TableCell>\n                  <TableCell>{item.deadline}</TableCell>\n                  <TableCell>\n                    <AvatarStack people={item.assigned} />\n                  </TableCell>\n                  <TableCell>\n                    <StatusBadge\n                      status={item.status}\n                      variant={getStatusVariant(item.status)}\n                    />\n                  </TableCell>\n                </TableRow>\n              ))}\n            </Fragment>\n          ))}\n        </TableBody>\n      </Table>\n    </div>\n  );\n}\n"
    }
  ],
  "categories": [
    "tables"
  ]
}