'use client'; import { AlignCommandIcon as IconCmd } from '@/components/misc/alignui-icons'; import * as React from 'react'; import { ChevronDown, Database, Filter, Laptop, MoreHorizontal, PenLine, PieChart, Search, ShieldCheck, Sparkles, ArrowUpDown, User, } from 'lucide-react'; import { flexRender, getCoreRowModel, getSortedRowModel, useReactTable, type ColumnDef, type SortingState, } from '@tanstack/react-table'; import * as Avatar from '@/components/ui/avatar'; import * as Badge from '@/components/ui/badge'; import * as Button from '@/components/ui/button'; import * as Checkbox from '@/components/ui/checkbox'; import * as Input from '@/components/ui/input'; import * as Kbd from '@/components/ui/kbd'; import * as SegmentedControl from '@/components/ui/segmented-control'; import { StarRating } from '@/components/ui/svg-rating-icons'; import * as Table from '@/components/ui/table'; type CourseData = { id: string; courseName: string; courseIcon?: React.ReactNode; categories: { name: string; color: | 'blue' | 'purple' | 'green' | 'yellow' | 'orange' | 'red' | 'pink' | 'gray' | 'sky' | 'teal'; additionalCount?: number; }[]; duration: string; instructor: { name: string; avatar: string; }; rating: number; additionalCount?: number; }; const data: CourseData[] = [ { id: '1', courseName: 'Leadership Skills', courseIcon: , categories: [ { name: 'Team', color: 'blue', additionalCount: 4 }, { name: 'Communication', color: 'purple', additionalCount: 4 }, ], duration: '3 weeks', instructor: { name: 'Horizon Shift', avatar: 'https://alignui.com/images/logo/horizon.svg', }, rating: 4.5, }, { id: '2', courseName: 'Data Science Fundamentals', courseIcon: , categories: [ { name: 'Data', color: 'orange' }, { name: 'Analytics', color: 'red', additionalCount: 2 }, ], duration: '6 weeks', instructor: { name: 'Orandis', avatar: 'https://alignui.com/images/logo/orandis.svg', }, rating: 4, }, { id: '3', courseName: 'Web Development Basics', courseIcon: , categories: [ { name: 'Programming', color: 'pink' }, { name: 'Wen', color: 'blue', additionalCount: 2 }, ], duration: '8 weeks', instructor: { name: 'Phoenix', avatar: 'https://alignui.com/images/logo/phoenix.svg', }, rating: 5, }, { id: '4', courseName: 'Digital Marketing', courseIcon: , categories: [ { name: 'Marketing', color: 'green' }, { name: 'Social Media', color: 'purple', additionalCount: 2 }, ], duration: '2 weeks', instructor: { name: 'Catalyst', avatar: 'https://alignui.com/images/logo/catalyst.svg', }, rating: 3, }, { id: '5', courseName: 'Graphic Design Mastery', courseIcon: , categories: [ { name: 'Design', color: 'yellow' }, { name: 'Creativity', color: 'green', additionalCount: 4 }, ], duration: '12 weeks', instructor: { name: 'Aurora', avatar: 'https://alignui.com/images/logo/aurora.svg', }, rating: 4.5, }, { id: '6', courseName: 'Cybersecurity Basics', courseIcon: , categories: [ { name: 'Security', color: 'sky' }, { name: 'Programming', color: 'pink' }, { name: 'IT', color: 'purple' }, ], duration: '4 weeks', instructor: { name: 'Orandis', avatar: 'https://alignui.com/images/logo/orandis.svg', }, rating: 4, }, { id: '7', courseName: 'Artificial Intelligence', courseIcon: , categories: [ { name: 'AI', color: 'purple' }, { name: 'Machine Learning', color: 'orange', additionalCount: 4 }, ], duration: '6 weeks', instructor: { name: 'Apex', avatar: 'https://alignui.com/images/logo/apex.svg', }, rating: 5, }, ]; const getCategoryBadges = ( categories: { name: string; color: | 'blue' | 'purple' | 'green' | 'yellow' | 'orange' | 'red' | 'pink' | 'gray' | 'sky' | 'teal'; additionalCount?: number; }[], ) => { // Get the additionalCount from first category with this property const additionalCount = categories.find( (cat) => cat.additionalCount !== undefined, )?.additionalCount; return (
{categories.map((category, index) => ( {category.name} ))} {additionalCount && ( +{additionalCount} )}
); }; export default function CourseCatalogTable() { const [sorting, setSorting] = React.useState([]); const [filter, setFilter] = React.useState('all'); const [rowSelection, setRowSelection] = React.useState({}); const filteredData = React.useMemo(() => { if (filter === 'all') return data; if (filter === 'in-progress') { return data.filter((course) => course.rating < 5); } if (filter === 'completed') { return data.filter((course) => course.rating === 5); } return data; }, [filter]); const columns: ColumnDef[] = [ { id: 'select', header: ({ table }) => ( table.toggleAllPageRowsSelected(!!value)} aria-label='Select all' /> ), cell: () => ( row.toggleSelected(!!value)} aria-label='Select row' /> ), }, { id: 'courseName', accessorKey: 'courseName', header: ({ column }) => ( column.toggleSorting(column.getIsSorted() === 'asc')} > Course Name ), cell: () => (
{row.original.courseIcon}
{row.original.courseName}
), }, { id: 'instructor', accessorKey: 'instructor.name', header: ({ column }) => ( column.toggleSorting(column.getIsSorted() === 'asc')} > Instructor ), cell: () => (
{row.original.instructor.name}
), }, { id: 'category', accessorKey: 'categories', header: ({ column }) => ( column.toggleSorting(column.getIsSorted() === 'asc')} > Category ), cell: ({ row }) => getCategoryBadges(row.original.categories), }, { id: 'rating', accessorKey: 'rating', header: ({ column }) => ( column.toggleSorting(column.getIsSorted() === 'asc')} > Course Rating ), cell: ({ row }) => , }, { id: 'duration', accessorKey: 'duration', header: ({ column }) => ( column.toggleSorting(column.getIsSorted() === 'asc')} > Duration ), cell: ({ row }) => ( {row.original.duration} ), }, { id: 'actions', enableHiding: false, cell: () => ( ), }, ]; const table = useReactTable({ data: filteredData, columns, onSortingChange: setSorting, getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), onRowSelectionChange: setRowSelection, state: { sorting, rowSelection, }, }); return (
All In Progress Completed
1
Filter Sort by
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => { const customClass = header.id === 'select' ? 'pr-0' : ''; return ( {header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext(), )} ); })} ))} {table.getRowModel().rows?.length > 0 && table.getRowModel().rows.map((row, i, arr) => ( {row.getVisibleCells().map((cell) => { const customCellClass = cell.column.id === 'select' ? 'pr-0' : ''; return ( {flexRender( cell.column.columnDef.cell, cell.getContext(), )} ); })} {i < arr.length - 1 && } ))}
); }