Initial import of 1407 block sources under blocks/
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,357 @@
|
||||
"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";
|
||||
|
||||
const formatPrice = (value: number) =>
|
||||
new Intl.NumberFormat("fa-IR", {
|
||||
style: "currency",
|
||||
currency: "IRR",
|
||||
}).format(value);
|
||||
|
||||
type ColumnMeta = {
|
||||
cellClassName?: string;
|
||||
};
|
||||
|
||||
type Transaction = {
|
||||
id: number;
|
||||
invoiceNumber: string;
|
||||
href: string;
|
||||
amount: number;
|
||||
tax?: number;
|
||||
client: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
type DayGroup = {
|
||||
date: string;
|
||||
dateTime: string;
|
||||
transactions: Transaction[];
|
||||
};
|
||||
|
||||
const days: DayGroup[] = [
|
||||
{
|
||||
date: "امروز",
|
||||
dateTime: "2024-05-20",
|
||||
transactions: [
|
||||
{
|
||||
id: 101,
|
||||
invoiceNumber: "ORD-48392",
|
||||
href: "/orders/ORD-48392",
|
||||
amount: 1248.5,
|
||||
tax: 98.5,
|
||||
client: "خانه آرورا",
|
||||
description: "۳ ست ملحفه کتان + بستهبندی هدیه",
|
||||
},
|
||||
{
|
||||
id: 102,
|
||||
invoiceNumber: "PAYOUT-2298",
|
||||
href: "/payouts/PAYOUT-2298",
|
||||
amount: 4830,
|
||||
client: "بازارچه مسیرهای وحشی",
|
||||
description: "پرداخت هفتگی فروشنده",
|
||||
},
|
||||
{
|
||||
id: 103,
|
||||
invoiceNumber: "ORD-48310",
|
||||
href: "/orders/ORD-48310",
|
||||
amount: 312,
|
||||
tax: 23.8,
|
||||
client: "نیلا گرین",
|
||||
description: "بازپرداخت در حال بررسی",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
date: "دیروز",
|
||||
dateTime: "2024-05-19",
|
||||
transactions: [
|
||||
{
|
||||
id: 104,
|
||||
invoiceNumber: "ORD-48277",
|
||||
href: "/orders/ORD-48277",
|
||||
amount: 2940,
|
||||
tax: 201.3,
|
||||
client: "شرکت ترک شهری",
|
||||
description: "۱۲ عدد عصای کوهنوردی کربنی",
|
||||
},
|
||||
{
|
||||
id: 105,
|
||||
invoiceNumber: "ORD-48261",
|
||||
href: "/orders/ORD-48261",
|
||||
amount: 864,
|
||||
client: "مایا پاتل",
|
||||
description: "پیشسفارش کفش اسپرت نسخه محدود",
|
||||
},
|
||||
{
|
||||
id: 106,
|
||||
invoiceNumber: "PAYOUT-2297",
|
||||
href: "/payouts/PAYOUT-2297",
|
||||
amount: 1980,
|
||||
client: "لوازم خانگی لومن",
|
||||
description: "درخواست پرداخت فوری",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
date: "یکشنبه",
|
||||
dateTime: "2024-05-18",
|
||||
transactions: [
|
||||
{
|
||||
id: 107,
|
||||
invoiceNumber: "ORD-48190",
|
||||
href: "/orders/ORD-48190",
|
||||
amount: 490,
|
||||
tax: 34.3,
|
||||
client: "تأمین اطلس",
|
||||
description: "سفارش نمونه فروش سازمانی",
|
||||
},
|
||||
{
|
||||
id: 108,
|
||||
invoiceNumber: "ORD-48175",
|
||||
href: "/orders/ORD-48175",
|
||||
amount: 156,
|
||||
client: "جیمی لی",
|
||||
description: "پرداخت تقسیمی انجام نشده",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
type FlatTransaction = Transaction & { dayDate: string; dayDateTime: string };
|
||||
|
||||
function flattenDays(src: DayGroup[]): FlatTransaction[] {
|
||||
const out: FlatTransaction[] = [];
|
||||
for (const d of src) {
|
||||
for (const t of d.transactions) {
|
||||
out.push({ ...t, dayDate: d.date, dayDateTime: d.dateTime });
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export function DataTable24({ className }: { className?: string }) {
|
||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||
const data = React.useMemo(() => flattenDays(days), []);
|
||||
|
||||
const columns = React.useMemo<ColumnDef<FlatTransaction>[]>(
|
||||
() => [
|
||||
{
|
||||
id: "invoice",
|
||||
header: "فاکتور",
|
||||
cell: ({ row }) => {
|
||||
const t = row.original;
|
||||
return (
|
||||
<div className="flex flex-col gap-1">
|
||||
<a href={t.href} className="text-sm font-semibold">
|
||||
{t.invoiceNumber}
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
meta: {
|
||||
cellClassName: "py-5 pe-6",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "amount-status",
|
||||
header: "مبلغ",
|
||||
cell: ({ row }) => {
|
||||
const t = row.original;
|
||||
return (
|
||||
<>
|
||||
<div className="flex gap-6">
|
||||
<div className="flex-auto">
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="text-sm/6 font-medium text-foreground">
|
||||
{formatPrice(t.amount)}
|
||||
</div>
|
||||
{t.tax ? (
|
||||
<div className="mt-1 text-xs/5 text-muted-foreground">
|
||||
+ {formatPrice(t.tax)} مالیات
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="absolute end-full bottom-0 h-px w-screen bg-border" />
|
||||
<div className="absolute bottom-0 start-0 h-px w-screen bg-border" />
|
||||
</>
|
||||
);
|
||||
},
|
||||
meta: {
|
||||
cellClassName: "relative py-5 pe-6",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "client-desc",
|
||||
header: "مشتری",
|
||||
cell: ({ row }) => {
|
||||
const t = row.original;
|
||||
return (
|
||||
<>
|
||||
<div className="text-sm/6 text-foreground">{t.client}</div>
|
||||
</>
|
||||
);
|
||||
},
|
||||
meta: {
|
||||
cellClassName: "hidden py-5 pe-6 sm:table-cell",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "description",
|
||||
header: "توضیحات",
|
||||
cell: ({ row }) => {
|
||||
const t = row.original;
|
||||
return <div className="text-sm text-foreground">{t.description}</div>;
|
||||
},
|
||||
meta: {
|
||||
cellClassName: "py-5 pe-6",
|
||||
},
|
||||
},
|
||||
],
|
||||
[],
|
||||
);
|
||||
|
||||
const table = useReactTable({
|
||||
data,
|
||||
columns,
|
||||
state: { sorting },
|
||||
onSortingChange: setSorting,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getRowId: (r) => String(r.id),
|
||||
});
|
||||
|
||||
const rowModelRows = table.getRowModel().rows;
|
||||
|
||||
const grouped = React.useMemo(() => {
|
||||
const byDay = new Map<
|
||||
string,
|
||||
{ date: string; dateTime: string; rows: Row<FlatTransaction>[] }
|
||||
>();
|
||||
for (const r of rowModelRows) {
|
||||
const key = r.original.dayDateTime;
|
||||
if (!byDay.has(key)) {
|
||||
byDay.set(key, {
|
||||
date: r.original.dayDate,
|
||||
dateTime: r.original.dayDateTime,
|
||||
rows: [],
|
||||
});
|
||||
}
|
||||
byDay.get(key)!.rows.push(r);
|
||||
}
|
||||
return days.map((d) => byDay.get(d.dateTime)).filter(Boolean) as Array<{
|
||||
date: string;
|
||||
dateTime: string;
|
||||
rows: Row<FlatTransaction>[];
|
||||
}>;
|
||||
}, [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="overflow-hidden border-t border-border">
|
||||
<div className="mx-auto max-w-2xl lg:mx-0 lg:max-w-none">
|
||||
<div className="[&>div]:overflow-visible">
|
||||
<Table className="w-full text-start text-sm">
|
||||
<TableHeader className="sr-only [&_*]:border-0 [&_tr]:border-0">
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id} className="border-0">
|
||||
{headerGroup.headers.map((header) => (
|
||||
<TableHead
|
||||
key={header.id}
|
||||
scope="col"
|
||||
className="p-0 text-start"
|
||||
>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext(),
|
||||
)}
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableHeader>
|
||||
|
||||
<TableBody>
|
||||
{grouped.map((group) => (
|
||||
<React.Fragment key={group.dateTime}>
|
||||
<TableRow className="text-sm/6 text-foreground">
|
||||
<TableHead
|
||||
scope="colgroup"
|
||||
colSpan={columnCount}
|
||||
className="relative isolate border-0 py-2 text-start font-semibold text-foreground"
|
||||
>
|
||||
<time dateTime={group.dateTime}>{group.date}</time>
|
||||
<div className="absolute inset-y-0 end-full -z-10 w-screen border-b border-border bg-muted" />
|
||||
<div className="absolute inset-y-0 start-0 -z-10 w-screen border-b border-border bg-muted" />
|
||||
</TableHead>
|
||||
</TableRow>
|
||||
|
||||
{group.rows.map((row) => (
|
||||
<TableRow key={row.id} className="border-0">
|
||||
{row.getVisibleCells().map((cell) => {
|
||||
const meta =
|
||||
(cell.column.columnDef.meta as ColumnMeta) ??
|
||||
{};
|
||||
return (
|
||||
<TableCell
|
||||
key={cell.id}
|
||||
className={cn(
|
||||
"border-0 p-0 text-start align-top",
|
||||
meta.cellClassName,
|
||||
)}
|
||||
>
|
||||
{flexRender(
|
||||
cell.column.columnDef.cell,
|
||||
cell.getContext(),
|
||||
)}
|
||||
</TableCell>
|
||||
);
|
||||
})}
|
||||
</TableRow>
|
||||
))}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user