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

320 lines
10 KiB
TypeScript

"use client";
import type { ColumnDef, SortingState } from "@tanstack/react-table";
import {
flexRender,
getCoreRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import * as React from "react";
import {
Table,
TableBody,
TableCell,
TableFooter,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { cn } from "@/lib/utils";
const formatPrice = (value: number) =>
new Intl.NumberFormat("fa-IR", {
style: "currency",
currency: "IRR",
}).format(value);
const formatNumber = (value: number) => value.toLocaleString("fa-IR");
type LineItem = {
id: number;
sku: string;
name: string;
description: string;
quantity: number;
unitPrice: number;
};
type LineItemColumnMeta = {
headerClassName?: string;
cellClassName?: string;
};
const lineItems: LineItem[] = [
{
id: 1,
sku: "RBK-32-MN",
name: "کوله‌پشتی ریج‌وی",
description: "سرمه‌ای تیره · ظرفیت ۳۲ لیتر",
quantity: 2,
unitPrice: 145,
},
{
id: 2,
sku: "EVB-20-SL",
name: "بطری روزمره ۲۰ اونسی",
description: "خاکستری · استیل سه‌لایه",
quantity: 3,
unitPrice: 28,
},
{
id: 3,
sku: "DBH-FT-NV",
name: "هودی پشمی سپیده‌دم",
description: "پارچه فرنچ تری · رنگ شب‌افت",
quantity: 1,
unitPrice: 95,
},
{
id: 4,
sku: "TRV-ORG-SET",
name: "ست نظم‌دهنده سفر",
description: "کیسه‌های مشبک · بسته ۴ عددی",
quantity: 1,
unitPrice: 72,
},
{
id: 5,
sku: "EXP-90-OLV",
name: "کیف دوشی اکسپدیشن ۹۰ لیتر",
description: "ریپ‌استاپ ضدآب · زیتونی",
quantity: 1,
unitPrice: 260,
},
];
const lineTotal = (item: LineItem) => item.quantity * item.unitPrice;
export function DataTable25({ className }: { className?: string }) {
const [sorting, setSorting] = React.useState<SortingState>([]);
const columns = React.useMemo<ColumnDef<LineItem>[]>(
() => [
{
id: "product",
header: "محصول",
cell: ({ row }) => {
const item = row.original;
return (
<div className="text-sm">
<div className="font-medium text-foreground">{item.name}</div>
<div className="mt-1 truncate text-muted-foreground">
{item.description}
</div>
<div className="mt-1 text-xs tracking-wide text-muted-foreground">
کد کالا: {item.sku}
</div>
</div>
);
},
meta: {
headerClassName:
"py-3.5 ps-4 pe-3 text-start text-sm font-semibold text-foreground sm:ps-0 h-auto",
cellClassName:
"max-w-0 py-5 ps-4 pe-3 align-top text-sm sm:ps-0 text-foreground",
},
},
{
accessorKey: "quantity",
header: "تعداد",
cell: ({ row }) => formatNumber(row.original.quantity),
meta: {
headerClassName:
"hidden px-3 py-3.5 text-end text-sm font-semibold text-foreground sm:table-cell",
cellClassName:
"hidden px-3 py-5 text-end text-sm text-muted-foreground sm:table-cell",
},
},
{
accessorKey: "unitPrice",
header: "قیمت واحد",
cell: ({ row }) => formatPrice(row.original.unitPrice),
meta: {
headerClassName:
"hidden px-3 py-3.5 text-end text-sm font-semibold text-foreground sm:table-cell",
cellClassName:
"hidden px-3 py-5 text-end text-sm text-muted-foreground sm:table-cell",
},
},
{
id: "total",
header: "جمع",
cell: ({ row }) => formatPrice(lineTotal(row.original)),
meta: {
headerClassName:
"py-3.5 ps-3 pe-4 text-end text-sm font-semibold text-foreground sm:pe-0 h-auto",
cellClassName:
"py-5 ps-3 pe-4 text-end text-sm text-muted-foreground sm:pe-0",
},
},
],
[],
);
const table = useReactTable({
data: lineItems,
columns,
state: { sorting },
onSortingChange: setSorting,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getRowId: (row) => String(row.id),
});
const subtotalAmount = lineItems.reduce(
(sum, item) => sum + lineTotal(item),
0,
);
const taxAmount = 64.08;
const totalAmount = subtotalAmount + taxAmount;
const subtotal = formatPrice(subtotalAmount);
const tax = formatPrice(taxAmount);
const total = formatPrice(totalAmount);
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>
<div className="overflow-x-auto">
<Table className="min-w-full">
<colgroup>
<col className="w-full sm:w-1/2" />
<col className="sm:w-1/6" />
<col className="sm:w-1/6" />
<col className="sm:w-1/6" />
</colgroup>
<TableHeader className="text-foreground [&_tr]:border-border/60">
{table.getHeaderGroups().map((headerGroup) => (
<TableRow
key={headerGroup.id}
className="border-0 hover:bg-transparent"
>
{headerGroup.headers.map((header) => {
const meta =
(header.column.columnDef.meta as LineItemColumnMeta) ??
{};
return (
<TableHead
key={header.id}
scope="col"
className={cn(
"h-auto bg-transparent text-sm font-semibold",
meta.headerClassName,
)}
>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext(),
)}
</TableHead>
);
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
className="border-border/60 hover:bg-transparent"
>
{row.getVisibleCells().map((cell) => {
const meta =
(cell.column.columnDef.meta as LineItemColumnMeta) ?? {};
return (
<TableCell
key={cell.id}
className={cn(meta.cellClassName)}
>
{flexRender(
cell.column.columnDef.cell,
cell.getContext(),
)}
</TableCell>
);
})}
</TableRow>
))}
</TableBody>
<TableFooter className="!border-0 !bg-transparent !font-normal">
<TableRow className="border-0 hover:bg-transparent">
<TableHead
scope="row"
colSpan={3}
className="hidden h-auto border-0 pt-6 pe-3 ps-4 text-end text-sm font-normal text-muted-foreground sm:table-cell sm:ps-0"
>
جمع جزء
</TableHead>
<TableHead
scope="row"
className="h-auto border-0 pt-6 pe-3 ps-4 text-start text-sm font-normal text-muted-foreground sm:hidden"
>
جمع جزء
</TableHead>
<TableCell className="border-0 pt-6 pe-4 ps-3 text-end text-sm text-muted-foreground sm:pe-0">
{subtotal}
</TableCell>
</TableRow>
<TableRow className="border-0 hover:bg-transparent">
<TableHead
scope="row"
colSpan={3}
className="hidden h-auto border-0 pt-4 pe-3 ps-4 text-end text-sm font-normal text-muted-foreground sm:table-cell sm:ps-0"
>
مالیات
</TableHead>
<TableHead
scope="row"
className="h-auto border-0 pt-4 pe-3 ps-4 text-start text-sm font-normal text-muted-foreground sm:hidden"
>
مالیات
</TableHead>
<TableCell className="border-0 pt-4 pe-4 ps-3 text-end text-sm text-muted-foreground sm:pe-0">
{tax}
</TableCell>
</TableRow>
<TableRow className="border-0 hover:bg-transparent">
<TableHead
scope="row"
colSpan={3}
className="hidden h-auto border-0 pt-4 pe-3 ps-4 text-end text-sm font-semibold text-foreground sm:table-cell sm:ps-0"
>
جمع کل
</TableHead>
<TableHead
scope="row"
className="h-auto border-0 pt-4 pe-3 ps-4 text-start text-sm font-semibold text-foreground sm:hidden"
>
جمع کل
</TableHead>
<TableCell className="border-0 pt-4 pe-4 ps-3 text-end text-sm font-semibold text-foreground sm:pe-0">
{total}
</TableCell>
</TableRow>
</TableFooter>
</Table>
</div>
</div>
</section>
);
}