add: transaction history & its datatable
This commit is contained in:
Generated
+167
@@ -9,12 +9,15 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-dialog": "^1.1.14",
|
"@radix-ui/react-dialog": "^1.1.14",
|
||||||
|
"@radix-ui/react-dropdown-menu": "^2.1.15",
|
||||||
"@radix-ui/react-popover": "^1.1.14",
|
"@radix-ui/react-popover": "^1.1.14",
|
||||||
|
"@radix-ui/react-scroll-area": "^1.2.9",
|
||||||
"@radix-ui/react-slider": "^1.3.5",
|
"@radix-ui/react-slider": "^1.3.5",
|
||||||
"@radix-ui/react-slot": "^1.2.3",
|
"@radix-ui/react-slot": "^1.2.3",
|
||||||
"@radix-ui/react-switch": "^1.2.5",
|
"@radix-ui/react-switch": "^1.2.5",
|
||||||
"@tanstack/react-query": "^5.81.5",
|
"@tanstack/react-query": "^5.81.5",
|
||||||
"@tanstack/react-query-devtools": "^5.81.5",
|
"@tanstack/react-query-devtools": "^5.81.5",
|
||||||
|
"@tanstack/react-table": "^8.21.3",
|
||||||
"axios": "^1.10.0",
|
"axios": "^1.10.0",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
@@ -1201,6 +1204,35 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-dropdown-menu": {
|
||||||
|
"version": "2.1.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.15.tgz",
|
||||||
|
"integrity": "sha512-mIBnOjgwo9AH3FyKaSWoSu/dYj6VdhJ7frEPiGTeXCdUFHjl9h3mFh2wwhEtINOmYXWhdpf1rY2minFsmaNgVQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/primitive": "1.1.2",
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.2",
|
||||||
|
"@radix-ui/react-context": "1.1.2",
|
||||||
|
"@radix-ui/react-id": "1.1.1",
|
||||||
|
"@radix-ui/react-menu": "2.1.15",
|
||||||
|
"@radix-ui/react-primitive": "2.1.3",
|
||||||
|
"@radix-ui/react-use-controllable-state": "1.2.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-focus-guards": {
|
"node_modules/@radix-ui/react-focus-guards": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.2.tgz",
|
||||||
@@ -1259,6 +1291,46 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-menu": {
|
||||||
|
"version": "2.1.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.15.tgz",
|
||||||
|
"integrity": "sha512-tVlmA3Vb9n8SZSd+YSbuFR66l87Wiy4du+YE+0hzKQEANA+7cWKH1WgqcEX4pXqxUFQKrWQGHdvEfw00TjFiew==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/primitive": "1.1.2",
|
||||||
|
"@radix-ui/react-collection": "1.1.7",
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.2",
|
||||||
|
"@radix-ui/react-context": "1.1.2",
|
||||||
|
"@radix-ui/react-direction": "1.1.1",
|
||||||
|
"@radix-ui/react-dismissable-layer": "1.1.10",
|
||||||
|
"@radix-ui/react-focus-guards": "1.1.2",
|
||||||
|
"@radix-ui/react-focus-scope": "1.1.7",
|
||||||
|
"@radix-ui/react-id": "1.1.1",
|
||||||
|
"@radix-ui/react-popper": "1.2.7",
|
||||||
|
"@radix-ui/react-portal": "1.1.9",
|
||||||
|
"@radix-ui/react-presence": "1.1.4",
|
||||||
|
"@radix-ui/react-primitive": "2.1.3",
|
||||||
|
"@radix-ui/react-roving-focus": "1.1.10",
|
||||||
|
"@radix-ui/react-slot": "1.2.3",
|
||||||
|
"@radix-ui/react-use-callback-ref": "1.1.1",
|
||||||
|
"aria-hidden": "^1.2.4",
|
||||||
|
"react-remove-scroll": "^2.6.3"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-popover": {
|
"node_modules/@radix-ui/react-popover": {
|
||||||
"version": "1.1.14",
|
"version": "1.1.14",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.14.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.14.tgz",
|
||||||
@@ -1399,6 +1471,68 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-roving-focus": {
|
||||||
|
"version": "1.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.10.tgz",
|
||||||
|
"integrity": "sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/primitive": "1.1.2",
|
||||||
|
"@radix-ui/react-collection": "1.1.7",
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.2",
|
||||||
|
"@radix-ui/react-context": "1.1.2",
|
||||||
|
"@radix-ui/react-direction": "1.1.1",
|
||||||
|
"@radix-ui/react-id": "1.1.1",
|
||||||
|
"@radix-ui/react-primitive": "2.1.3",
|
||||||
|
"@radix-ui/react-use-callback-ref": "1.1.1",
|
||||||
|
"@radix-ui/react-use-controllable-state": "1.2.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-scroll-area": {
|
||||||
|
"version": "1.2.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.9.tgz",
|
||||||
|
"integrity": "sha512-YSjEfBXnhUELsO2VzjdtYYD4CfQjvao+lhhrX5XsHD7/cyUNzljF1FHEbgTPN7LH2MClfwRMIsYlqTYpKTTe2A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/number": "1.1.1",
|
||||||
|
"@radix-ui/primitive": "1.1.2",
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.2",
|
||||||
|
"@radix-ui/react-context": "1.1.2",
|
||||||
|
"@radix-ui/react-direction": "1.1.1",
|
||||||
|
"@radix-ui/react-presence": "1.1.4",
|
||||||
|
"@radix-ui/react-primitive": "2.1.3",
|
||||||
|
"@radix-ui/react-use-callback-ref": "1.1.1",
|
||||||
|
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-slider": {
|
"node_modules/@radix-ui/react-slider": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.5.tgz",
|
||||||
@@ -1979,6 +2113,39 @@
|
|||||||
"react": "^18 || ^19"
|
"react": "^18 || ^19"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tanstack/react-table": {
|
||||||
|
"version": "8.21.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.3.tgz",
|
||||||
|
"integrity": "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@tanstack/table-core": "8.21.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/tannerlinsley"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.8",
|
||||||
|
"react-dom": ">=16.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tanstack/table-core": {
|
||||||
|
"version": "8.21.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz",
|
||||||
|
"integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/tannerlinsley"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@tybys/wasm-util": {
|
"node_modules/@tybys/wasm-util": {
|
||||||
"version": "0.9.0",
|
"version": "0.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz",
|
||||||
|
|||||||
@@ -10,12 +10,15 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-dialog": "^1.1.14",
|
"@radix-ui/react-dialog": "^1.1.14",
|
||||||
|
"@radix-ui/react-dropdown-menu": "^2.1.15",
|
||||||
"@radix-ui/react-popover": "^1.1.14",
|
"@radix-ui/react-popover": "^1.1.14",
|
||||||
|
"@radix-ui/react-scroll-area": "^1.2.9",
|
||||||
"@radix-ui/react-slider": "^1.3.5",
|
"@radix-ui/react-slider": "^1.3.5",
|
||||||
"@radix-ui/react-slot": "^1.2.3",
|
"@radix-ui/react-slot": "^1.2.3",
|
||||||
"@radix-ui/react-switch": "^1.2.5",
|
"@radix-ui/react-switch": "^1.2.5",
|
||||||
"@tanstack/react-query": "^5.81.5",
|
"@tanstack/react-query": "^5.81.5",
|
||||||
"@tanstack/react-query-devtools": "^5.81.5",
|
"@tanstack/react-query-devtools": "^5.81.5",
|
||||||
|
"@tanstack/react-table": "^8.21.3",
|
||||||
"axios": "^1.10.0",
|
"axios": "^1.10.0",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import { DataTableDemo } from '@/components/ui/datatable'
|
||||||
|
import { MoneyRecive, MoneySend, Wallet } from 'iconsax-react'
|
||||||
|
import { ArrowDownLeft, ArrowUpRight } from 'lucide-react'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
function TransactionsReviewIndex() {
|
||||||
|
return (
|
||||||
|
<section className='flex flex-col h-svh pb-10 pt-6 gap-4'>
|
||||||
|
<h1 className="font-medium text-base">لیست تراکنش ها</h1>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-3 gap-2 h-28">
|
||||||
|
<div className="w-full h-full flex flex-col items-center justify-center p-2.5 text-center bg-container rounded-xl">
|
||||||
|
<div className="size-8 bg-background rounded-full grid items-center">
|
||||||
|
<MoneySend className='stroke-primary justify-self-center' size={20} />
|
||||||
|
</div>
|
||||||
|
<span className='text-xs2 pt-1'>مجموع واریز ها</span>
|
||||||
|
<span className='text-xs font-medium mt-1'>140,000,000 ریال</span>
|
||||||
|
<span className='text-xs2 text-green-60mt-0.5 0 bg-green-100 w-min px-1 py-px items-center justify-between rounded-md flex'>
|
||||||
|
<ArrowUpRight size={10} className='stroke-green-600' />
|
||||||
|
<div className="mt-0.5">30%</div>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="w-full h-full flex flex-col items-center justify-between p-2.5 text-center bg-container rounded-xl">
|
||||||
|
<div className="size-8 bg-background rounded-full grid items-center">
|
||||||
|
<MoneyRecive className='stroke-primary justify-self-center' size={20} />
|
||||||
|
</div>
|
||||||
|
<span className='text-xs2 pt-1'>مجموع برداشت ها</span>
|
||||||
|
<span className='text-xs font-medium mt-1'>140,000,000 ریال</span>
|
||||||
|
<span className='text-xs2 text-green-60mt-0.5 0 bg-green-100 w-min px-1 py-px items-center justify-between rounded-md flex'>
|
||||||
|
<ArrowUpRight size={10} className='stroke-green-600' />
|
||||||
|
<div className="mt-0.5">30%</div>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="w-full h-full flex flex-col items-center justify-between p-2.5 text-center bg-container rounded-xl">
|
||||||
|
<div className="size-8 bg-background rounded-full grid items-center">
|
||||||
|
<Wallet className='stroke-primary justify-self-center' size={20} />
|
||||||
|
</div>
|
||||||
|
<span className='text-xs2 pt-1'>موجودی کیف پول</span>
|
||||||
|
<span className='text-xs font-medium mt-1'>140,000,000 ریال</span>
|
||||||
|
<span className='text-xs2 text-red-600 mt-0.5 bg-red-100 w-min px-1 py-px items-center justify-between rounded-md flex'>
|
||||||
|
<ArrowDownLeft size={10} className='stroke-red-600' />
|
||||||
|
<div className="mt-0.5">30%</div>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='w-full h-full bg-white rounded-3xl mt-0'>
|
||||||
|
<DataTableDemo />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TransactionsReviewIndex
|
||||||
@@ -0,0 +1,501 @@
|
|||||||
|
"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 clsx from "clsx"
|
||||||
|
import { EyeToggleIcon } from "../icons/EyeToggleIcon"
|
||||||
|
import { ArrowLeft2, ArrowRight2 } from "iconsax-react"
|
||||||
|
|
||||||
|
const data: Payment[] = [
|
||||||
|
{
|
||||||
|
id: "m5gr84i9",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3u1reuv4",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "derv1ws0",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: false,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "5kma53ae",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "bhqecj4p",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "m5gr84i9",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3u1reuv4",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "derv1ws0",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: false,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "5kma53ae",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "bhqecj4p",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "m5gr84i9",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3u1reuv4",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "derv1ws0",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: false,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "5kma53ae",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "bhqecj4p",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "m5gr84i9",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3u1reuv4",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "derv1ws0",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: false,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "5kma53ae",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "bhqecj4p",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "m5gr84i9",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3u1reuv4",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "derv1ws0",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: false,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "5kma53ae",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "bhqecj4p",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "m5gr84i9",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3u1reuv4",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "derv1ws0",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: false,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "5kma53ae",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "bhqecj4p",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "m5gr84i9",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3u1reuv4",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "derv1ws0",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: false,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "5kma53ae",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "bhqecj4p",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "m5gr84i9",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3u1reuv4",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "derv1ws0",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: false,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "5kma53ae",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "bhqecj4p",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "m5gr84i9",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3u1reuv4",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "derv1ws0",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: false,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "5kma53ae",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "bhqecj4p",
|
||||||
|
type: 'تایپ',
|
||||||
|
status: true,
|
||||||
|
date: 14040401,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export type Payment = {
|
||||||
|
id: string
|
||||||
|
type: string
|
||||||
|
// status: "pending" | "processing" | "success" | "failed"
|
||||||
|
status: boolean
|
||||||
|
date: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export const columns: ColumnDef<Payment>[] = [
|
||||||
|
{
|
||||||
|
accessorKey: "id",
|
||||||
|
header: "شماره",
|
||||||
|
cell: ({ row }) => (
|
||||||
|
<div className="capitalize">{row.getValue("id")}</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "type",
|
||||||
|
header: () => "نوع تراکنش",
|
||||||
|
cell: ({ row }) => <div className="capitalize">{row.getValue("type")}</div>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "date",
|
||||||
|
header: () => <div className="text-right">تاریخ</div>,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const date = parseFloat(row.getValue("date"))
|
||||||
|
|
||||||
|
// Format the amount as a dollar amount
|
||||||
|
// const formatted = new Intl.NumberFormat("en-US", {
|
||||||
|
// style: "currency",
|
||||||
|
// currency: "USD",
|
||||||
|
// }).format(amount)
|
||||||
|
// TODO: convert to jalali
|
||||||
|
|
||||||
|
return <div className="text-right">{date}</div>
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "status",
|
||||||
|
header: () => <div className="text-right">وضعیت</div>,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const status = Boolean(row.getValue("status"))
|
||||||
|
|
||||||
|
const str = status ? 'پاسخ داده شده' : 'پاسخ داده نشده';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='text-right flex items-center justify-center gap-x-2'>
|
||||||
|
<span className={clsx('size-2 rounded-full', status ? 'bg-[#00BA4B]' : 'bg-transparent border border-primary')}></span>
|
||||||
|
{str}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "actions",
|
||||||
|
enableHiding: false,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const status = Boolean(row.getValue("status"))
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<EyeToggleIcon slash={status} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export function DataTableDemo() {
|
||||||
|
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,
|
||||||
|
columns,
|
||||||
|
onSortingChange: setSorting,
|
||||||
|
onColumnFiltersChange: setColumnFilters,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
onColumnVisibilityChange: setColumnVisibility,
|
||||||
|
onRowSelectionChange: setRowSelection,
|
||||||
|
state: {
|
||||||
|
sorting,
|
||||||
|
columnFilters,
|
||||||
|
columnVisibility,
|
||||||
|
rowSelection,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-full">
|
||||||
|
<div className="rounded-3xl w-full">
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
|
<TableRow 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}
|
||||||
|
data-state={row.getIsSelected() && "selected"}
|
||||||
|
className="text-center w-full text-xs odd:bg-[#E9EBF433] even:bg-container border-0 border-b h-14 border-r-4 border-r-transparent active:border-r-primary"
|
||||||
|
>
|
||||||
|
{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"
|
||||||
|
>
|
||||||
|
No results.
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-end space-x-2 py-4 px-7">
|
||||||
|
<div className="flex-1 text-sm text-disabled-text">
|
||||||
|
نمایش: <span className="text-primary">{table.getRowModel().rows.length}</span> از {table.getFilteredRowModel().rows.length}
|
||||||
|
</div>
|
||||||
|
<div className="space-x-2 justify-center flex">
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => table.previousPage()}
|
||||||
|
hidden={!table.getCanPreviousPage()}
|
||||||
|
>
|
||||||
|
<ArrowRight2 size={12} className="stroke-[#A8ABBF]" />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant='secondary'
|
||||||
|
size="sm"
|
||||||
|
onClick={() => table.previousPage()}
|
||||||
|
hidden={!table.getCanPreviousPage()}
|
||||||
|
>
|
||||||
|
{table.getState().pagination.pageIndex}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant='default'
|
||||||
|
size="sm"
|
||||||
|
hidden={!table.getCanPreviousPage() && !table.getCanNextPage()}
|
||||||
|
>
|
||||||
|
{table.getState().pagination.pageIndex + 1}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant='secondary'
|
||||||
|
size="sm"
|
||||||
|
onClick={() => table.nextPage()}
|
||||||
|
hidden={!table.getCanNextPage()}
|
||||||
|
>
|
||||||
|
{table.getState().pagination.pageIndex + 2}
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => table.nextPage()}
|
||||||
|
hidden={!table.getCanNextPage()}
|
||||||
|
>
|
||||||
|
<ArrowLeft2 size={12} className="stroke-[#A8ABBF]" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,201 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import * as React from "react"
|
||||||
|
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
|
||||||
|
import { Check, ChevronRight, Circle } from "lucide-react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
const DropdownMenu = DropdownMenuPrimitive.Root
|
||||||
|
|
||||||
|
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
|
||||||
|
|
||||||
|
const DropdownMenuGroup = DropdownMenuPrimitive.Group
|
||||||
|
|
||||||
|
const DropdownMenuPortal = DropdownMenuPrimitive.Portal
|
||||||
|
|
||||||
|
const DropdownMenuSub = DropdownMenuPrimitive.Sub
|
||||||
|
|
||||||
|
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
|
||||||
|
|
||||||
|
const DropdownMenuSubTrigger = React.forwardRef<
|
||||||
|
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
|
||||||
|
inset?: boolean
|
||||||
|
}
|
||||||
|
>(({ className, inset, children, ...props }, ref) => (
|
||||||
|
<DropdownMenuPrimitive.SubTrigger
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||||
|
inset && "pl-8",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<ChevronRight className="ml-auto" />
|
||||||
|
</DropdownMenuPrimitive.SubTrigger>
|
||||||
|
))
|
||||||
|
DropdownMenuSubTrigger.displayName =
|
||||||
|
DropdownMenuPrimitive.SubTrigger.displayName
|
||||||
|
|
||||||
|
const DropdownMenuSubContent = React.forwardRef<
|
||||||
|
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<DropdownMenuPrimitive.SubContent
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-dropdown-menu-content-transform-origin]",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
DropdownMenuSubContent.displayName =
|
||||||
|
DropdownMenuPrimitive.SubContent.displayName
|
||||||
|
|
||||||
|
const DropdownMenuContent = React.forwardRef<
|
||||||
|
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
|
||||||
|
>(({ className, sideOffset = 4, ...props }, ref) => (
|
||||||
|
<DropdownMenuPrimitive.Portal>
|
||||||
|
<DropdownMenuPrimitive.Content
|
||||||
|
ref={ref}
|
||||||
|
sideOffset={sideOffset}
|
||||||
|
className={cn(
|
||||||
|
"z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
|
||||||
|
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-dropdown-menu-content-transform-origin]",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</DropdownMenuPrimitive.Portal>
|
||||||
|
))
|
||||||
|
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
|
||||||
|
|
||||||
|
const DropdownMenuItem = React.forwardRef<
|
||||||
|
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
|
||||||
|
inset?: boolean
|
||||||
|
}
|
||||||
|
>(({ className, inset, ...props }, ref) => (
|
||||||
|
<DropdownMenuPrimitive.Item
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
|
||||||
|
inset && "pl-8",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
|
||||||
|
|
||||||
|
const DropdownMenuCheckboxItem = React.forwardRef<
|
||||||
|
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
|
||||||
|
>(({ className, children, checked, ...props }, ref) => (
|
||||||
|
<DropdownMenuPrimitive.CheckboxItem
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
checked={checked}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||||
|
<DropdownMenuPrimitive.ItemIndicator>
|
||||||
|
<Check className="h-4 w-4" />
|
||||||
|
</DropdownMenuPrimitive.ItemIndicator>
|
||||||
|
</span>
|
||||||
|
{children}
|
||||||
|
</DropdownMenuPrimitive.CheckboxItem>
|
||||||
|
))
|
||||||
|
DropdownMenuCheckboxItem.displayName =
|
||||||
|
DropdownMenuPrimitive.CheckboxItem.displayName
|
||||||
|
|
||||||
|
const DropdownMenuRadioItem = React.forwardRef<
|
||||||
|
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
|
||||||
|
>(({ className, children, ...props }, ref) => (
|
||||||
|
<DropdownMenuPrimitive.RadioItem
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||||
|
<DropdownMenuPrimitive.ItemIndicator>
|
||||||
|
<Circle className="h-2 w-2 fill-current" />
|
||||||
|
</DropdownMenuPrimitive.ItemIndicator>
|
||||||
|
</span>
|
||||||
|
{children}
|
||||||
|
</DropdownMenuPrimitive.RadioItem>
|
||||||
|
))
|
||||||
|
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
|
||||||
|
|
||||||
|
const DropdownMenuLabel = React.forwardRef<
|
||||||
|
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
|
||||||
|
inset?: boolean
|
||||||
|
}
|
||||||
|
>(({ className, inset, ...props }, ref) => (
|
||||||
|
<DropdownMenuPrimitive.Label
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"px-2 py-1.5 text-sm font-semibold",
|
||||||
|
inset && "pl-8",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
|
||||||
|
|
||||||
|
const DropdownMenuSeparator = React.forwardRef<
|
||||||
|
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<DropdownMenuPrimitive.Separator
|
||||||
|
ref={ref}
|
||||||
|
className={cn("-mx-1 my-1 h-px bg-muted", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
|
||||||
|
|
||||||
|
const DropdownMenuShortcut = ({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
|
||||||
|
|
||||||
|
export {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuCheckboxItem,
|
||||||
|
DropdownMenuRadioItem,
|
||||||
|
DropdownMenuLabel,
|
||||||
|
DropdownMenuSeparator,
|
||||||
|
DropdownMenuShortcut,
|
||||||
|
DropdownMenuGroup,
|
||||||
|
DropdownMenuPortal,
|
||||||
|
DropdownMenuSub,
|
||||||
|
DropdownMenuSubContent,
|
||||||
|
DropdownMenuSubTrigger,
|
||||||
|
DropdownMenuRadioGroup,
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
|
||||||
|
({ className, type, ...props }, ref) => {
|
||||||
|
return (
|
||||||
|
<input
|
||||||
|
type={type}
|
||||||
|
className={cn(
|
||||||
|
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
ref={ref}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Input.displayName = "Input"
|
||||||
|
|
||||||
|
export { Input }
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import * as React from "react"
|
||||||
|
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
const ScrollArea = React.forwardRef<
|
||||||
|
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
|
||||||
|
>(({ className, children, ...props }, ref) => (
|
||||||
|
<ScrollAreaPrimitive.Root
|
||||||
|
ref={ref}
|
||||||
|
className={cn("relative overflow-hidden", className)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
|
||||||
|
{children}
|
||||||
|
</ScrollAreaPrimitive.Viewport>
|
||||||
|
<ScrollBar />
|
||||||
|
<ScrollAreaPrimitive.Corner />
|
||||||
|
</ScrollAreaPrimitive.Root>
|
||||||
|
))
|
||||||
|
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
|
||||||
|
|
||||||
|
const ScrollBar = React.forwardRef<
|
||||||
|
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
|
||||||
|
>(({ className, orientation = "vertical", ...props }, ref) => (
|
||||||
|
<ScrollAreaPrimitive.ScrollAreaScrollbar
|
||||||
|
ref={ref}
|
||||||
|
orientation={orientation}
|
||||||
|
className={cn(
|
||||||
|
"flex touch-none select-none transition-colors",
|
||||||
|
orientation === "vertical" &&
|
||||||
|
"h-full w-2.5 border-l border-l-transparent p-[1px]",
|
||||||
|
orientation === "horizontal" &&
|
||||||
|
"h-2.5 flex-col border-t border-t-transparent p-[1px]",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
|
||||||
|
</ScrollAreaPrimitive.ScrollAreaScrollbar>
|
||||||
|
))
|
||||||
|
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
|
||||||
|
|
||||||
|
export { ScrollArea, ScrollBar }
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
const Table = React.forwardRef<
|
||||||
|
HTMLTableElement,
|
||||||
|
React.HTMLAttributes<HTMLTableElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<div className="relative w-full overflow-auto">
|
||||||
|
<table
|
||||||
|
ref={ref}
|
||||||
|
className={cn("w-full caption-bottom text-sm", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
Table.displayName = "Table"
|
||||||
|
|
||||||
|
const TableHeader = React.forwardRef<
|
||||||
|
HTMLTableSectionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableSectionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
|
||||||
|
))
|
||||||
|
TableHeader.displayName = "TableHeader"
|
||||||
|
|
||||||
|
const TableBody = React.forwardRef<
|
||||||
|
HTMLTableSectionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableSectionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<tbody
|
||||||
|
ref={ref}
|
||||||
|
className={cn("[&_tr:last-child]:border-0", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TableBody.displayName = "TableBody"
|
||||||
|
|
||||||
|
const TableFooter = React.forwardRef<
|
||||||
|
HTMLTableSectionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableSectionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<tfoot
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TableFooter.displayName = "TableFooter"
|
||||||
|
|
||||||
|
const TableRow = React.forwardRef<
|
||||||
|
HTMLTableRowElement,
|
||||||
|
React.HTMLAttributes<HTMLTableRowElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<tr
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TableRow.displayName = "TableRow"
|
||||||
|
|
||||||
|
const TableHead = React.forwardRef<
|
||||||
|
HTMLTableCellElement,
|
||||||
|
React.ThHTMLAttributes<HTMLTableCellElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<th
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TableHead.displayName = "TableHead"
|
||||||
|
|
||||||
|
const TableCell = React.forwardRef<
|
||||||
|
HTMLTableCellElement,
|
||||||
|
React.TdHTMLAttributes<HTMLTableCellElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<td
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TableCell.displayName = "TableCell"
|
||||||
|
|
||||||
|
const TableCaption = React.forwardRef<
|
||||||
|
HTMLTableCaptionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableCaptionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<caption
|
||||||
|
ref={ref}
|
||||||
|
className={cn("mt-4 text-sm text-muted-foreground", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TableCaption.displayName = "TableCaption"
|
||||||
|
|
||||||
|
export {
|
||||||
|
Table,
|
||||||
|
TableHeader,
|
||||||
|
TableBody,
|
||||||
|
TableFooter,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
TableCell,
|
||||||
|
TableCaption,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user