{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "student-gradebook-table",
  "title": "Student Gradebook Table",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-react/blocks/student-gradebook-table/StudentGradebookTable.tsx",
      "content": "'use client'\n\nimport {\n  CalendarCheck,\n  ClipboardCheck,\n  Download,\n  GraduationCap,\n  Mail,\n  MoreHorizontal,\n  Pencil,\n  Plus,\n  User,\n  Users,\n} from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Avatar, AvatarFallback } from '@/components/ui/avatar'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent } from '@/components/ui/card'\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu'\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'\n\nexport type LetterGrade = 'A+' | 'A' | 'A-' | 'B+' | 'B' | 'B-'\n\nexport interface StudentGradeRecord {\n  id: string\n  name: string\n  studentId: string\n  homework: string\n  midterm: string\n  labProjects: string\n  finalProject: string\n  overallGrade: string\n  letterGrade: LetterGrade\n  attendanceRate: string\n  absences: number\n}\n\nconst metrics = [\n  {\n    title: 'Class GPA',\n    value: '3.62 / 4.0',\n    description: '+0.18 vs departmental target',\n    icon: GraduationCap,\n    iconClass: 'bg-success/10 text-success',\n    valueClass: 'text-success',\n  },\n  {\n    title: 'Total Enrolled Students',\n    value: '28 students',\n    description: '100% active roster',\n    icon: Users,\n    iconClass: 'bg-info/10 text-info',\n    valueClass: 'text-foreground',\n  },\n  {\n    title: 'Assignments Graded',\n    value: '12 / 14 assignments',\n    description: '2 pending final submissions',\n    icon: ClipboardCheck,\n    iconClass: 'bg-chart-1/10 text-chart-1',\n    valueClass: 'text-foreground',\n  },\n  {\n    title: 'Class Attendance Rate',\n    value: '96.2% average',\n    description: '36 lectures & labs logged',\n    icon: CalendarCheck,\n    iconClass: 'bg-warning/10 text-warning',\n    valueClass: 'text-foreground',\n  },\n]\n\nconst gradeBadgeConfig: Record<LetterGrade, { className: string }> = {\n  'A+': {\n    className: 'bg-success/10 text-success border-success/20 font-semibold',\n  },\n  A: {\n    className: 'bg-success/10 text-success border-success/20 font-semibold',\n  },\n  'A-': {\n    className: 'bg-success/10 text-success border-success/20 font-semibold',\n  },\n  'B+': {\n    className: 'bg-info/10 text-info border-info/20 font-semibold',\n  },\n  B: {\n    className: 'bg-warning/10 text-warning border-warning/20 font-semibold',\n  },\n  'B-': {\n    className: 'bg-warning/10 text-warning border-warning/20 font-semibold',\n  },\n}\n\nconst students: StudentGradeRecord[] = [\n  {\n    id: 's1',\n    name: 'Elena Rostova',\n    studentId: '#STU-84920',\n    homework: '95.0%',\n    midterm: '92.0%',\n    labProjects: '98.0%',\n    finalProject: '94.0%',\n    overallGrade: '94.5%',\n    letterGrade: 'A',\n    attendanceRate: '100%',\n    absences: 0,\n  },\n  {\n    id: 's2',\n    name: 'David Chen',\n    studentId: '#STU-84921',\n    homework: '88.0%',\n    midterm: '91.0%',\n    labProjects: '86.0%',\n    finalProject: '89.0%',\n    overallGrade: '88.6%',\n    letterGrade: 'B+',\n    attendanceRate: '96%',\n    absences: 1,\n  },\n  {\n    id: 's3',\n    name: 'Sarah Jenkins',\n    studentId: '#STU-84922',\n    homework: '98.0%',\n    midterm: '96.0%',\n    labProjects: '100.0%',\n    finalProject: '95.0%',\n    overallGrade: '97.1%',\n    letterGrade: 'A',\n    attendanceRate: '100%',\n    absences: 0,\n  },\n  {\n    id: 's4',\n    name: 'Marcus Vance',\n    studentId: '#STU-84923',\n    homework: '82.0%',\n    midterm: '79.0%',\n    labProjects: '85.0%',\n    finalProject: '80.0%',\n    overallGrade: '81.4%',\n    letterGrade: 'B',\n    attendanceRate: '92%',\n    absences: 2,\n  },\n  {\n    id: 's5',\n    name: 'Sofia Rossi',\n    studentId: '#STU-84924',\n    homework: '91.0%',\n    midterm: '88.0%',\n    labProjects: '94.0%',\n    finalProject: '90.0%',\n    overallGrade: '90.6%',\n    letterGrade: 'A-',\n    attendanceRate: '98%',\n    absences: 1,\n  },\n  {\n    id: 's6',\n    name: 'Alex Rivera',\n    studentId: '#STU-84925',\n    homework: '84.0%',\n    midterm: '86.0%',\n    labProjects: '82.0%',\n    finalProject: '85.0%',\n    overallGrade: '84.3%',\n    letterGrade: 'B',\n    attendanceRate: '94%',\n    absences: 2,\n  },\n]\n\nfunction initials(name: string) {\n  return name\n    .split(' ')\n    .map((part) => part[0])\n    .slice(0, 2)\n    .join('')\n    .toUpperCase()\n}\n\nexport function StudentGradebookTable({ className }: { className?: string }) {\n  return (\n    <div data-slot=\"student-gradebook-table\" className={cn('w-full space-y-6', className)}>\n      {/* Header */}\n      <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n        <div>\n          <div className=\"flex flex-wrap items-center gap-2.5\">\n            <h2 className=\"text-2xl font-bold tracking-tight\">CS 301: Advanced Software Systems &amp; Compilers</h2>\n            <Badge variant=\"outline\" className=\"font-mono text-xs\">\n              CS-301-B\n            </Badge>\n          </div>\n          <div className=\"text-muted-foreground mt-1.5 flex flex-wrap items-center gap-2 text-sm\">\n            <span>Fall 2026 · Section B</span>\n            <span className=\"text-foreground inline-flex items-center gap-1 font-medium\">\n              Class Average: <span className=\"tabular-nums\">88.4%</span> · Grade B+\n            </span>\n          </div>\n        </div>\n        <div className=\"flex flex-wrap items-center gap-2.5\">\n          <Button aria-label=\"Download attachment\" variant=\"outline\">\n            <Download aria-hidden=\"true\" />\n            Export Grades CSV\n          </Button>\n          <Button>\n            <Plus aria-hidden=\"true\" />\n            New Grade Entry\n          </Button>\n        </div>\n      </div>\n\n      {/* 4 Class Overview Metric Cards */}\n      <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n        {metrics.map((metric) => {\n          const Icon = metric.icon\n          return (\n            <Card key={metric.title} className=\"shadow-xs\">\n              <CardContent className=\"space-y-2 p-5\">\n                <div className=\"flex items-center justify-between\">\n                  <p className=\"text-muted-foreground text-sm font-medium\">{metric.title}</p>\n                  <div className={cn('flex size-8 items-center justify-center rounded-md', metric.iconClass)}>\n                    <Icon aria-hidden=\"true\" className=\"size-4\" />\n                  </div>\n                </div>\n                <div>\n                  <p className={cn('text-2xl font-bold tracking-tight tabular-nums', metric.valueClass)}>\n                    {metric.value}\n                  </p>\n                  <p className=\"text-muted-foreground mt-1 text-xs\">{metric.description}</p>\n                </div>\n              </CardContent>\n            </Card>\n          )\n        })}\n      </div>\n\n      {/* Gradebook Table */}\n      <div className=\"bg-card overflow-x-auto rounded-lg border shadow-xs\">\n        <Table>\n          <TableHeader>\n            <TableRow>\n              <TableHead>Student</TableHead>\n              <TableHead className=\"text-right\">Homework (25%)</TableHead>\n              <TableHead className=\"text-right\">Midterm (30%)</TableHead>\n              <TableHead className=\"text-right\">Lab Projects (25%)</TableHead>\n              <TableHead className=\"text-right\">Final Project (20%)</TableHead>\n              <TableHead className=\"text-right font-semibold\">Overall Grade</TableHead>\n              <TableHead className=\"text-center\">Letter Grade</TableHead>\n              <TableHead>Attendance</TableHead>\n              <TableHead className=\"w-12 text-right\">\n                <span className=\"sr-only\">Actions</span>\n              </TableHead>\n            </TableRow>\n          </TableHeader>\n          <TableBody>\n            {students.map((student) => (\n              <TableRow key={student.id} className=\"hover:bg-muted/50\">\n                <TableCell>\n                  <div className=\"flex items-center gap-3\">\n                    <Avatar className=\"size-8\">\n                      <AvatarFallback className=\"text-xs font-medium\">{initials(student.name)}</AvatarFallback>\n                    </Avatar>\n                    <div className=\"min-w-0\">\n                      <p className=\"truncate text-sm font-semibold\">{student.name}</p>\n                      <p className=\"text-muted-foreground font-mono text-xs\">{student.studentId}</p>\n                    </div>\n                  </div>\n                </TableCell>\n                <TableCell className=\"text-right font-medium tabular-nums\">{student.homework}</TableCell>\n                <TableCell className=\"text-right font-medium tabular-nums\">{student.midterm}</TableCell>\n                <TableCell className=\"text-right font-medium tabular-nums\">{student.labProjects}</TableCell>\n                <TableCell className=\"text-right font-medium tabular-nums\">{student.finalProject}</TableCell>\n                <TableCell className=\"text-foreground text-right font-bold tabular-nums\">\n                  {student.overallGrade}\n                </TableCell>\n                <TableCell className=\"text-center\">\n                  <Badge\n                    variant=\"outline\"\n                    className={cn('font-semibold', gradeBadgeConfig[student.letterGrade].className)}\n                  >\n                    {student.letterGrade}\n                  </Badge>\n                </TableCell>\n                <TableCell>\n                  <div className=\"inline-flex items-center gap-1.5 text-xs\">\n                    <span\n                      className={cn(\n                        'inline-block size-1.5 rounded-full',\n                        student.absences === 0 ? 'bg-success' : 'bg-warning',\n                      )}\n                      aria-hidden=\"true\"\n                    />\n                    <span className=\"text-foreground font-medium tabular-nums\">{student.attendanceRate}</span>\n                    <span className=\"text-muted-foreground\">\n                      ·{' '}\n                      {student.absences === 0\n                        ? '0 absences'\n                        : `${student.absences} absence${student.absences > 1 ? 's' : ''}`}\n                    </span>\n                  </div>\n                </TableCell>\n                <TableCell className=\"text-right\">\n                  <DropdownMenu>\n                    <DropdownMenuTrigger asChild>\n                      <Button variant=\"ghost\" size=\"icon-sm\" className=\"text-muted-foreground\">\n                        <MoreHorizontal aria-hidden=\"true\" />\n                        <span className=\"sr-only\">Open actions for {student.name}</span>\n                      </Button>\n                    </DropdownMenuTrigger>\n                    <DropdownMenuContent align=\"end\" className=\"w-48\">\n                      <DropdownMenuItem>\n                        <Pencil aria-hidden=\"true\" />\n                        Edit Grades\n                      </DropdownMenuItem>\n                      <DropdownMenuItem>\n                        <User aria-hidden=\"true\" />\n                        View Student Profile\n                      </DropdownMenuItem>\n                      <DropdownMenuSeparator />\n                      <DropdownMenuItem>\n                        <Mail aria-hidden=\"true\" />\n                        Send Email Alert\n                      </DropdownMenuItem>\n                    </DropdownMenuContent>\n                  </DropdownMenu>\n                </TableCell>\n              </TableRow>\n            ))}\n          </TableBody>\n        </Table>\n      </div>\n\n      {/* Table Footer / Pagination */}\n      <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n        <p className=\"text-muted-foreground text-sm\">\n          Showing <span className=\"text-foreground font-medium\">6</span> of{' '}\n          <span className=\"text-foreground font-medium\">28</span> enrolled students\n        </p>\n        <div className=\"flex items-center gap-2\">\n          <Button variant=\"outline\" size=\"sm\" disabled>\n            Previous\n          </Button>\n          <Button variant=\"outline\" size=\"sm\">\n            Next\n          </Button>\n        </div>\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:block",
      "target": "~/components/blocks/StudentGradebookTable.tsx"
    }
  ],
  "dependencies": [
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/react/avatar.json",
    "https://uipkge.dev/r/react/badge.json",
    "https://uipkge.dev/r/react/button.json",
    "https://uipkge.dev/r/react/card.json",
    "https://uipkge.dev/r/react/dropdown-menu.json",
    "https://uipkge.dev/r/react/table.json"
  ],
  "description": "Academic gradebook ledger with course header, weighted assignment categories (homework, midterm, labs, final project), class GPA & enrollment metric cards, overall percentage, letter grade badges, attendance tags, and student action menus.",
  "categories": [
    "education",
    "app",
    "data",
    "dashboard"
  ]
}