Files
dmenu-plus-front/src/app/[name]/(Main)/transactions/components/TransactionsTable.tsx
T
2025-12-23 10:45:04 +03:30

240 lines
7.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client'
import * as React from 'react'
import {
ColumnDef,
ColumnFiltersState,
SortingState,
VisibilityState,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable
} from '@tanstack/react-table'
import { Button } from '@/components/ui/button'
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow
} from '@/components/ui/table'
import { ArrowLeft2, ArrowRight2 } from 'iconsax-react'
import { ef } from '@/lib/helpers/utfNumbers'
import { Transaction } from '../types/Types'
import Status from '@/components/utils/Status'
interface TransactionsTableProps {
transactions: Transaction[]
}
const formatDate = (dateString: string): string => {
const date = new Date(dateString);
return date.toLocaleDateString('fa-IR', {
year: 'numeric',
month: '2-digit',
day: '2-digit'
});
};
export const columns: ColumnDef<Transaction>[] = [
{
accessorKey: 'order.orderNumber',
header: () => <div className='text-right pr-6'>شماره سفارش</div>,
cell: ({ row }) => {
const orderNumber = row.original.order?.orderNumber;
return (
<div className='text-right pr-6'>{ef(orderNumber?.toString() || '-')}</div>
)
}
},
{
accessorKey: 'type',
header: () => <div className='text-center'>نوع تراکنش</div>,
cell: ({ row }) => {
const type = row.original.order?.paymentMethod?.description || '-';
return <div className='text-center'>{type}</div>
}
},
{
accessorKey: 'amount',
header: () => <div className='text-center'>مبلغ</div>,
cell: ({ row }) => {
const amount = row.original.amount;
const formatted = Math.abs(amount).toLocaleString('fa-IR');
return <div className='text-center'>{ef(formatted)} ریال</div>
}
},
{
accessorKey: 'createdAt',
header: () => <div className='text-center'>تاریخ</div>,
cell: ({ row }) => {
const date = formatDate(row.original.createdAt);
return <div className='text-center'>{ef(date)}</div>
}
},
{
accessorKey: 'status',
header: () => <div className='text-center'>وضعیت</div>,
cell: ({ row }) => {
const status = row.original.status;
return <Status status={status} className='text-right' />
}
}
]
export function TransactionsTable({ transactions }: TransactionsTableProps) {
const [sorting, setSorting] = React.useState<SortingState>([])
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
)
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({})
const [rowSelection, setRowSelection] = React.useState({})
const table = useReactTable({
data: transactions,
columns,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
onColumnVisibilityChange: setColumnVisibility,
onRowSelectionChange: setRowSelection,
state: {
sorting,
columnFilters,
columnVisibility,
rowSelection
},
initialState: {
pagination: {
pageSize: 8
}
}
})
return (
<div className='w-full'>
<div className='rounded-3xl min-h-[507px] w-full'>
<Table className='w-[727px] md:w-full'>
<TableHeader>
{table.getHeaderGroups().map(headerGroup => (
<TableRow
className='dark:border-neutral-400 border-[#EAEDF5] h-14'
key={headerGroup.id}
>
{headerGroup.headers.map(header => {
return (
<TableHead
key={header.id}
className='font-light text-xs text-disabled-text text-center'
>
{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}
className='text-center w-full border-b-[#EAEDF5] dark:border-b-background text-xs odd:bg-[#E9EBF433] bg-border dark:odd:bg-background/80 even:bg-container border-0 border-b! h-14 border-r-4! border-r-transparent active:border-r-primary dark:active:border-r-foreground'
>
{row.getVisibleCells().map(cell => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className='h-24 text-center'
>
تراکنشی یافت نشد.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
<div className='flex items-center justify-end space-x-2 pt-4 px-7 pb-11 select-none'>
<div className='flex-1 text-sm text-disabled-text'>
نمایش:{' '}
<span className='text-primary dark:text-foreground'>
{ef(table.getRowModel().rows.length)}
</span>{' '}
از {ef(table.getFilteredRowModel().rows.length)}
</div>
<div className='space-x-2 justify-center flex'>
<Button
variant='ghost'
size='sm'
className='size-6'
onClick={() => table.previousPage()}
hidden={!table.getCanPreviousPage()}
>
<ArrowRight2 size={12} className='stroke-[#A8ABBF]' />
</Button>
<Button
variant='secondary'
size='sm'
className='dark:bg-disabled bg-[#EAECF5] text-xs size-6'
onClick={() => table.previousPage()}
hidden={!table.getCanPreviousPage()}
>
{ef(table.getState().pagination.pageIndex)}
</Button>
<Button
variant='default'
className='text-white dark:text-foreground text-xs size-6'
size='sm'
hidden={!table.getCanPreviousPage() && !table.getCanNextPage()}
>
{ef(table.getState().pagination.pageIndex + 1)}
</Button>
<Button
variant='secondary'
size='sm'
className='dark:bg-disabled bg-[#EAECF5] text-xs size-6'
onClick={() => table.nextPage()}
hidden={!table.getCanNextPage()}
>
{ef(table.getState().pagination.pageIndex + 2)}
</Button>
<Button
variant='ghost'
size='sm'
className='size-6'
onClick={() => table.nextPage()}
hidden={!table.getCanNextPage()}
>
<ArrowLeft2 size={12} className='stroke-[#A8ABBF]' />
</Button>
</div>
</div>
</div>
)
}