'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
{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 && }
))}
);
}