Files
reui-blocks/blocks/data-table23.tsx
T

344 lines
9.3 KiB
TypeScript

"use client";
import type { ColumnDef, Row, SortingState } from "@tanstack/react-table";
import {
flexRender,
getCoreRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import * as React from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { cn } from "@/lib/utils";
type Person = {
name: string;
title: string;
email: string;
role: string;
};
type EmploymentGroup = {
type: string;
people: Person[];
};
type FlattenedPerson = Person & {
employmentType: string;
};
type ColumnMeta = {
headerClassName?: string;
cellClassName?: string;
};
const employmentGroups: EmploymentGroup[] = [
{
type: "تمام‌وقت",
people: [
{
name: "امیلیا هاکینز",
title: "مدیر ارشد محصول",
email: "amelia.hawkins@example.com",
role: "مالک",
},
{
name: "الیاس پاتل",
title: "معمار نرم‌افزار",
email: "elias.patel@example.com",
role: "مدیر",
},
{
name: "مژگان رید",
title: "سرپرست موفقیت مشتری",
email: "morgan.reed@example.com",
role: "عضو",
},
],
},
{
type: "قراردادی",
people: [
{
name: "ایلا بنت",
title: "استراتژیست برند",
email: "isla.bennett@example.com",
role: "مدیر",
},
{
name: "نوح کیم",
title: "مشاور امنیت",
email: "noah.kim@example.com",
role: "عضو",
},
],
},
{
type: "کارآموزی",
people: [
{
name: "نیلوفر Sharma",
title: "کارآموز طراحی محصول",
email: "priya.sharma@example.com",
role: "کارآموز",
},
{
name: "دانیال Brooks",
title: "کارآموز بازاریابی",
email: "caleb.brooks@example.com",
role: "کارآموز",
},
],
},
{
type: "پاره‌وقت",
people: [
{
name: "لیلا Alvarez",
title: "نویسنده فنی",
email: "sofia.alvarez@example.com",
role: "عضو",
},
],
},
];
export function DataTable23({ className }: { className?: string }) {
const [sorting, setSorting] = React.useState<SortingState>([]);
const flatData = React.useMemo(() => {
const result: FlattenedPerson[] = [];
employmentGroups.forEach((group) => {
group.people.forEach((person) =>
result.push({
...person,
employmentType: group.type,
}),
);
});
return result;
}, []);
const columns = React.useMemo<ColumnDef<FlattenedPerson>[]>(
() => [
{
accessorKey: "name",
header: "نام مخاطب",
cell: ({ row }) => (
<div className="text-sm font-semibold text-foreground">
{row.original.name}
</div>
),
meta: {
headerClassName: "ps-6 pe-3 text-start text-sm sm:ps-4",
cellClassName: "py-4 ps-6 pe-3 text-start sm:ps-4",
},
},
{
accessorKey: "title",
header: "سمت",
cell: ({ row }) => (
<span className="text-sm text-muted-foreground">
{row.original.title}
</span>
),
meta: {
headerClassName: "px-3 text-start text-sm",
cellClassName: "px-3 py-4",
},
},
{
accessorKey: "email",
header: "ایمیل",
cell: ({ row }) => (
<span className="text-sm text-muted-foreground">
{row.original.email}
</span>
),
meta: {
headerClassName: "px-3 text-start text-sm",
cellClassName: "px-3 py-4",
},
},
{
accessorKey: "role",
header: "نقش",
cell: ({ row }) => (
<span className="text-sm text-muted-foreground">
{row.original.role}
</span>
),
meta: {
headerClassName: "px-3 text-start text-sm",
cellClassName: "px-3 py-4",
},
},
],
[],
);
const table = useReactTable({
data: flatData,
columns,
state: {
sorting,
},
onSortingChange: setSorting,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getRowId: (row) => row.email,
});
const rowModelRows = table.getRowModel().rows;
const groupedRows = React.useMemo(() => {
if (!rowModelRows.length) {
return [];
}
const groups: Array<{
employmentType: string;
rows: Row<FlattenedPerson>[];
}> = [];
let currentEmploymentType = "";
let currentGroup: Row<FlattenedPerson>[] = [];
rowModelRows.forEach((row) => {
if (row.original.employmentType !== currentEmploymentType) {
if (currentGroup.length > 0) {
groups.push({
employmentType: currentEmploymentType,
rows: currentGroup,
});
}
currentEmploymentType = row.original.employmentType;
currentGroup = [row];
} else {
currentGroup.push(row);
}
});
if (currentGroup.length > 0) {
groups.push({
employmentType: currentEmploymentType,
rows: currentGroup,
});
}
return groups;
}, [rowModelRows]);
const columnCount = columns.length;
return (
<section dir="rtl" lang="fa" className={cn("py-32", className)}>
<div className="container">
<div className="w-full">
<div className="mb-8 text-start">
<h2 className="text-xl font-bold tracking-tight">
جدول با رکورد‌های گروه‌بندی‌شده
</h2>
<p className="mt-2 text-muted-foreground">
جدول داده با رکورد‌های گروه‌بندی‌شده برای تفکیک انواع مختلف
همکاری در یک جدول.
</p>
</div>
<div className="rounded-md bg-background">
<Table>
<TableHeader className="">
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
const meta = header.column.columnDef.meta as
| ColumnMeta
| undefined;
return (
<TableHead
key={header.id}
className={cn(
"py-3.5 text-start text-sm font-semibold text-muted-foreground",
meta?.headerClassName,
)}
>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext(),
)}
</TableHead>
);
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{groupedRows.length ? (
groupedRows.map((group) => (
<React.Fragment key={group.employmentType}>
<TableRow className="bg-muted/30 hover:bg-muted/30">
<TableCell
colSpan={columnCount}
className="text-xs font-semibold tracking-wide text-muted-foreground"
>
{group.employmentType}
</TableCell>
</TableRow>
{group.rows.map((row) => (
<TableRow key={row.id}>
{row.getVisibleCells().map((cell) => {
const meta =
(cell.column.columnDef.meta as ColumnMeta) ?? {};
return (
<TableCell
key={cell.id}
className={cn(
"align-middle text-sm text-muted-foreground",
meta.cellClassName,
)}
>
{flexRender(
cell.column.columnDef.cell,
cell.getContext(),
)}
</TableCell>
);
})}
</TableRow>
))}
</React.Fragment>
))
) : (
<TableRow>
<TableCell
colSpan={columnCount}
className="h-24 text-center text-sm text-muted-foreground"
>
نتیجه‌ای یافت نشد
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
</div>
</div>
</section>
);
}