Files
nextplacement/apps/admin/app/(main)/students/data-table.tsx
2025-07-05 21:08:14 +05:30

133 lines
4.1 KiB
TypeScript

'use client';
import { useState } from 'react';
import {
flexRender,
getCoreRowModel,
getPaginationRowModel,
useReactTable,
} from '@tanstack/react-table';
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@workspace/ui/components/table';
import { Student } from './columns';
import { StudentDetailsModal } from './student-details-modal.tsx';
import { columns } from './columns';
interface DataTableProps {
data: Student[];
markoutAction: (id: number, state: boolean) => void;
}
export function DataTable({ data, markoutAction }: DataTableProps) {
const [selectedStudent, setSelectedStudent] = useState<Student | null>(null);
const [isModalOpen, setIsModalOpen] = useState(false);
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
});
const handleRowClick = (student: Student) => {
setSelectedStudent(student);
setIsModalOpen(true);
};
const handleCloseModal = () => {
setIsModalOpen(false);
setSelectedStudent(null);
};
return (
<>
<div className="rounded-md border bg-white">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id} className="bg-gray-50">
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id} className="font-semibold text-gray-700">
{header.isPlaceholder
? null
: flexRender(header.column.columnDef.header, header.getContext())}
</TableHead>
);
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && 'selected'}
className="cursor-pointer hover:bg-gray-50 transition-colors duration-150"
onClick={() => handleRowClick(row.original as Student)}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id} className="py-4">
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan={columns.length} className="h-24 text-center text-gray-500">
No students found.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
{/* Pagination */}
<div className="flex items-center justify-between space-x-2 py-4">
<div className="flex-1 text-sm text-gray-700">
Showing {table.getFilteredRowModel().rows.length} of{' '}
{table.getFilteredRowModel().rows.length} results
</div>
<div className="space-x-2">
<button
className="px-3 py-1 text-sm border border-gray-300 rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed"
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
>
Previous
</button>
<button
className="px-3 py-1 text-sm border border-gray-300 rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed"
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
>
Next
</button>
</div>
</div>
{/* Student Details Modal */}
{selectedStudent && (
<StudentDetailsModal
student={selectedStudent}
isOpen={isModalOpen}
onClose={handleCloseModal}
markoutAction={(state: boolean) => {
markoutAction(selectedStudent.id, state);
}}
/>
)}
</>
);
}