Added accounts table page in Admin
This commit is contained in:
@@ -1,13 +1,70 @@
|
|||||||
|
import { ServerDataLoader } from '@makerkit/data-loader-supabase-nextjs';
|
||||||
|
|
||||||
|
import { AccountsTable } from '@kit/admin/components/accounts-table';
|
||||||
import { AdminGuard } from '@kit/admin/components/admin-guard';
|
import { AdminGuard } from '@kit/admin/components/admin-guard';
|
||||||
|
import { getSupabaseServerComponentClient } from '@kit/supabase/server-component-client';
|
||||||
import { PageBody, PageHeader } from '@kit/ui/page';
|
import { PageBody, PageHeader } from '@kit/ui/page';
|
||||||
|
|
||||||
function AccountsPage() {
|
interface SearchParams {
|
||||||
|
page?: string;
|
||||||
|
account_type?: 'all' | 'team' | 'personal';
|
||||||
|
}
|
||||||
|
|
||||||
|
function AccountsPage({ searchParams }: { searchParams: SearchParams }) {
|
||||||
|
const client = getSupabaseServerComponentClient({
|
||||||
|
admin: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const page = searchParams.page ? parseInt(searchParams.page) : 1;
|
||||||
|
const filters = getFilters(searchParams);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHeader title={'Accounts'} />
|
<PageHeader
|
||||||
<PageBody></PageBody>;
|
title={'Accounts'}
|
||||||
|
description={`Manage your accounts, view their details, and more.`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<PageBody>
|
||||||
|
<ServerDataLoader
|
||||||
|
table={'accounts'}
|
||||||
|
client={client}
|
||||||
|
page={page}
|
||||||
|
where={filters}
|
||||||
|
>
|
||||||
|
{({ data, page, pageSize, pageCount }) => {
|
||||||
|
return (
|
||||||
|
<AccountsTable
|
||||||
|
page={page}
|
||||||
|
pageSize={pageSize}
|
||||||
|
pageCount={pageCount}
|
||||||
|
data={data}
|
||||||
|
filters={{
|
||||||
|
type: searchParams.account_type ?? 'all',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</ServerDataLoader>
|
||||||
|
</PageBody>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getFilters(params: SearchParams) {
|
||||||
|
const filters: {
|
||||||
|
[key: string]: {
|
||||||
|
eq: boolean;
|
||||||
|
};
|
||||||
|
} = {};
|
||||||
|
|
||||||
|
if (params.account_type && params.account_type !== 'all') {
|
||||||
|
filters.is_personal_account = {
|
||||||
|
eq: params.account_type === 'personal',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return filters;
|
||||||
|
}
|
||||||
|
|
||||||
export default AdminGuard(AccountsPage);
|
export default AdminGuard(AccountsPage);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ const INTERNAL_PACKAGES = [
|
|||||||
'@kit/ui',
|
'@kit/ui',
|
||||||
'@kit/auth',
|
'@kit/auth',
|
||||||
'@kit/accounts',
|
'@kit/accounts',
|
||||||
|
'@kit/admin',
|
||||||
'@kit/team-accounts',
|
'@kit/team-accounts',
|
||||||
'@kit/shared',
|
'@kit/shared',
|
||||||
'@kit/supabase',
|
'@kit/supabase',
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"analyze": "ANALYZE=true pnpm run build",
|
"analyze": "ANALYZE=true pnpm run build",
|
||||||
"build": "pnpm with-env next build",
|
"build": "pnpm with-env next build",
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
"skip": "Skip",
|
"skip": "Skip",
|
||||||
"signedInAs": "Signed in as",
|
"signedInAs": "Signed in as",
|
||||||
"pageOfPages": "Page {{page}} of {{total}}",
|
"pageOfPages": "Page {{page}} of {{total}}",
|
||||||
|
"noData": "No data available",
|
||||||
"roles": {
|
"roles": {
|
||||||
"owner": {
|
"owner": {
|
||||||
"label": "Owner",
|
"label": "Owner",
|
||||||
|
|||||||
@@ -32,9 +32,9 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@manypkg/cli": "^0.21.3",
|
"@manypkg/cli": "^0.21.3",
|
||||||
"@turbo/gen": "^1.13.0",
|
"@turbo/gen": "^1.13.2",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"pnpm": "^8.15.5",
|
"pnpm": "^8.15.6",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"turbo": "^1.13.2",
|
"turbo": "^1.13.2",
|
||||||
"yarn": "^1.22.22"
|
"yarn": "^1.22.22"
|
||||||
|
|||||||
@@ -10,11 +10,17 @@
|
|||||||
},
|
},
|
||||||
"prettier": "@kit/prettier-config",
|
"prettier": "@kit/prettier-config",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@kit/ui": "0.1.0",
|
"@hookform/resolvers": "^3.3.4",
|
||||||
|
"@kit/supabase": "workspace:*",
|
||||||
|
"@kit/ui": "workspace:*",
|
||||||
"@makerkit/data-loader-supabase-core": "0.0.5",
|
"@makerkit/data-loader-supabase-core": "0.0.5",
|
||||||
"@makerkit/data-loader-supabase-nextjs": "^0.0.7"
|
"@makerkit/data-loader-supabase-nextjs": "^0.0.7",
|
||||||
|
"lucide-react": "^0.363.0",
|
||||||
|
"react-hook-form": "^7.51.2",
|
||||||
|
"zod": "^3.22.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@hookform/resolvers": "^3.3.4",
|
||||||
"@kit/eslint-config": "workspace:*",
|
"@kit/eslint-config": "workspace:*",
|
||||||
"@kit/prettier-config": "workspace:*",
|
"@kit/prettier-config": "workspace:*",
|
||||||
"@kit/supabase": "workspace:^",
|
"@kit/supabase": "workspace:^",
|
||||||
@@ -24,11 +30,13 @@
|
|||||||
"@makerkit/data-loader-supabase-core": "0.0.5",
|
"@makerkit/data-loader-supabase-core": "0.0.5",
|
||||||
"@makerkit/data-loader-supabase-nextjs": "^0.0.7",
|
"@makerkit/data-loader-supabase-nextjs": "^0.0.7",
|
||||||
"@supabase/supabase-js": "^2.42.0",
|
"@supabase/supabase-js": "^2.42.0",
|
||||||
"lucide-react": "^0.363.0"
|
"lucide-react": "^0.363.0",
|
||||||
|
"react-hook-form": "^7.51.2",
|
||||||
|
"zod": "^3.22.4"
|
||||||
},
|
},
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts",
|
".": "./src/index.ts",
|
||||||
"./components/*": "./src/components/*"
|
"./components/*": "./src/components/*.tsx"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"root": true,
|
"root": true,
|
||||||
|
|||||||
178
packages/features/admin/src/components/accounts-table.tsx
Normal file
178
packages/features/admin/src/components/accounts-table.tsx
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { usePathname, useRouter } from 'next/navigation';
|
||||||
|
|
||||||
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
|
import { ColumnDef } from '@tanstack/react-table';
|
||||||
|
import { EllipsisVertical } from 'lucide-react';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
import { Database } from '@kit/supabase/database';
|
||||||
|
import { Button } from '@kit/ui/button';
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuGroup,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuLabel,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from '@kit/ui/dropdown-menu';
|
||||||
|
import { DataTable } from '@kit/ui/enhanced-data-table';
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
} from '@kit/ui/select';
|
||||||
|
|
||||||
|
type Account = Database['public']['Tables']['accounts']['Row'];
|
||||||
|
|
||||||
|
const FiltersSchema = z.object({
|
||||||
|
type: z.enum(['all', 'team', 'personal']),
|
||||||
|
});
|
||||||
|
|
||||||
|
export function AccountsTable(
|
||||||
|
props: React.PropsWithChildren<{
|
||||||
|
data: Account[];
|
||||||
|
pageCount: number;
|
||||||
|
pageSize: number;
|
||||||
|
page: number;
|
||||||
|
filters: {
|
||||||
|
type: 'all' | 'team' | 'personal';
|
||||||
|
};
|
||||||
|
}>,
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<div className={'flex flex-col space-y-4'}>
|
||||||
|
<AccountsTableFilters filters={props.filters} />
|
||||||
|
|
||||||
|
<DataTable
|
||||||
|
pageSize={props.pageSize}
|
||||||
|
pageIndex={props.page - 1}
|
||||||
|
pageCount={props.pageCount}
|
||||||
|
data={props.data}
|
||||||
|
columns={getColumns()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function AccountsTableFilters(props: {
|
||||||
|
filters: z.infer<typeof FiltersSchema>;
|
||||||
|
}) {
|
||||||
|
const form = useForm({
|
||||||
|
resolver: zodResolver(FiltersSchema),
|
||||||
|
defaultValues: {
|
||||||
|
type: props.filters?.type ?? 'all',
|
||||||
|
},
|
||||||
|
mode: 'onChange',
|
||||||
|
reValidateMode: 'onChange',
|
||||||
|
});
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const pathName = usePathname();
|
||||||
|
|
||||||
|
const onSubmit = ({ type }: z.infer<typeof FiltersSchema>) => {
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
account_type: type,
|
||||||
|
});
|
||||||
|
|
||||||
|
const url = `${pathName}?${params.toString()}`;
|
||||||
|
|
||||||
|
router.push(url);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={'flex space-x-4'}>
|
||||||
|
<form onSubmit={form.handleSubmit((data) => onSubmit(data))}>
|
||||||
|
<Select
|
||||||
|
value={form.watch('type')}
|
||||||
|
onValueChange={(value) => {
|
||||||
|
form.setValue(
|
||||||
|
'type',
|
||||||
|
value as z.infer<typeof FiltersSchema>['type'],
|
||||||
|
{
|
||||||
|
shouldValidate: true,
|
||||||
|
shouldDirty: true,
|
||||||
|
shouldTouch: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return onSubmit(form.getValues());
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<span>Account Type</span>
|
||||||
|
</SelectTrigger>
|
||||||
|
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value={'all'}>All</SelectItem>
|
||||||
|
<SelectItem value={'team'}>Team</SelectItem>
|
||||||
|
<SelectItem value={'personal'}>Personal</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getColumns(): ColumnDef<Account>[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
id: 'name',
|
||||||
|
header: 'Name',
|
||||||
|
accessorKey: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'email',
|
||||||
|
header: 'Email',
|
||||||
|
accessorKey: 'email',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'type',
|
||||||
|
header: 'Type',
|
||||||
|
cell: ({ row }) => {
|
||||||
|
return row.original.is_personal_account ? 'Personal' : 'Team';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'created_at',
|
||||||
|
header: 'Created At',
|
||||||
|
accessorKey: 'created_at',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'updated_at',
|
||||||
|
header: 'Updated At',
|
||||||
|
accessorKey: 'updated_at',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'actions',
|
||||||
|
header: '',
|
||||||
|
cell: ({ row }) => {
|
||||||
|
return (
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger asChild>
|
||||||
|
<Button variant={'ghost'}>
|
||||||
|
<EllipsisVertical className={'h-4'} />
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
|
||||||
|
<DropdownMenuContent align={'end'}>
|
||||||
|
<DropdownMenuGroup>
|
||||||
|
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
||||||
|
|
||||||
|
<DropdownMenuItem>
|
||||||
|
<Link href={`/accounts/${row.original.id}`}>View</Link>
|
||||||
|
</DropdownMenuItem>
|
||||||
|
|
||||||
|
<DropdownMenuItem>Delete</DropdownMenuItem>
|
||||||
|
</DropdownMenuGroup>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -120,7 +120,8 @@
|
|||||||
"./loading-overlay": "./src/makerkit/loading-overlay.tsx",
|
"./loading-overlay": "./src/makerkit/loading-overlay.tsx",
|
||||||
"./profile-avatar": "./src/makerkit/profile-avatar.tsx",
|
"./profile-avatar": "./src/makerkit/profile-avatar.tsx",
|
||||||
"./mdx-components": "./src/makerkit/mdx-components.tsx",
|
"./mdx-components": "./src/makerkit/mdx-components.tsx",
|
||||||
"./mode-toggle": "./src/makerkit/mode-toggle.tsx"
|
"./mode-toggle": "./src/makerkit/mode-toggle.tsx",
|
||||||
|
"./enhanced-data-table": "./src/makerkit/data-table.tsx"
|
||||||
},
|
},
|
||||||
"typesVersions": {
|
"typesVersions": {
|
||||||
"*": {
|
"*": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Fragment, useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
|
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
|
|
||||||
@@ -35,7 +35,6 @@ import {
|
|||||||
TableHeader,
|
TableHeader,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from '../shadcn/table';
|
} from '../shadcn/table';
|
||||||
import { cn } from '../utils';
|
|
||||||
import { Trans } from './trans';
|
import { Trans } from './trans';
|
||||||
|
|
||||||
interface ReactTableProps<T extends object> {
|
interface ReactTableProps<T extends object> {
|
||||||
@@ -53,7 +52,6 @@ interface ReactTableProps<T extends object> {
|
|||||||
export function DataTable<T extends object>({
|
export function DataTable<T extends object>({
|
||||||
data,
|
data,
|
||||||
columns,
|
columns,
|
||||||
renderSubComponent,
|
|
||||||
pageIndex,
|
pageIndex,
|
||||||
pageSize,
|
pageSize,
|
||||||
pageCount,
|
pageCount,
|
||||||
@@ -117,9 +115,7 @@ export function DataTable<T extends object>({
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={'rounded-lg border'}>
|
||||||
className={'dark:border-dark-800 rounded-md border border-gray-50 p-1'}
|
|
||||||
>
|
|
||||||
<Table {...tableProps}>
|
<Table {...tableProps}>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
{table.getHeaderGroups().map((headerGroup) => (
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
@@ -145,38 +141,29 @@ export function DataTable<T extends object>({
|
|||||||
</TableHeader>
|
</TableHeader>
|
||||||
|
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{table.getRowModel().rows.map((row) => (
|
{table.getRowModel().rows?.length ? (
|
||||||
<Fragment key={row.id}>
|
table.getRowModel().rows.map((row) => (
|
||||||
<TableRow
|
<TableRow
|
||||||
className={cn({
|
key={row.id}
|
||||||
'border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted':
|
data-state={row.getIsSelected() && 'selected'}
|
||||||
row.getIsExpanded(),
|
|
||||||
})}
|
|
||||||
>
|
>
|
||||||
{row.getVisibleCells().map((cell) => (
|
{row.getVisibleCells().map((cell) => (
|
||||||
<TableCell
|
<TableCell key={cell.id}>
|
||||||
style={{
|
|
||||||
width: cell.column.getSize(),
|
|
||||||
}}
|
|
||||||
key={cell.id}
|
|
||||||
>
|
|
||||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
))}
|
))}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
))
|
||||||
{renderSubComponent ? (
|
) : (
|
||||||
<TableRow key={row.id + '-expanded'}>
|
<TableRow>
|
||||||
<TableCell colSpan={columns.length}>
|
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||||
{renderSubComponent({ row })}
|
<Trans i18nKey={'common:noData'} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
) : null}
|
)}
|
||||||
</Fragment>
|
|
||||||
))}
|
|
||||||
</TableBody>
|
</TableBody>
|
||||||
|
|
||||||
<TableFooter>
|
<TableFooter className={'bg-background'}>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell colSpan={columns.length}>
|
<TableCell colSpan={columns.length}>
|
||||||
<Pagination table={table} />
|
<Pagination table={table} />
|
||||||
@@ -194,39 +181,7 @@ function Pagination<T>({
|
|||||||
table: ReactTable<T>;
|
table: ReactTable<T>;
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<div className="flex w-full items-center gap-2">
|
<div className="flex items-center justify-end space-x-4">
|
||||||
<Button
|
|
||||||
size={'icon'}
|
|
||||||
onClick={() => table.setPageIndex(0)}
|
|
||||||
disabled={!table.getCanPreviousPage()}
|
|
||||||
>
|
|
||||||
<ChevronsLeft className={'h-4'} />
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
size={'icon'}
|
|
||||||
onClick={() => table.previousPage()}
|
|
||||||
disabled={!table.getCanPreviousPage()}
|
|
||||||
>
|
|
||||||
<ChevronLeft className={'h-4'} />
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
size={'icon'}
|
|
||||||
onClick={() => table.nextPage()}
|
|
||||||
disabled={!table.getCanNextPage()}
|
|
||||||
>
|
|
||||||
<ChevronRight className={'h-4'} />
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
size={'icon'}
|
|
||||||
onClick={() => table.setPageIndex(table.getPageCount() - 1)}
|
|
||||||
disabled={!table.getCanNextPage()}
|
|
||||||
>
|
|
||||||
<ChevronsRight className={'h-4'} />
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<span className="flex items-center text-sm">
|
<span className="flex items-center text-sm">
|
||||||
<Trans
|
<Trans
|
||||||
i18nKey={'common:pageOfPages'}
|
i18nKey={'common:pageOfPages'}
|
||||||
@@ -236,6 +191,44 @@ function Pagination<T>({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
<div className="flex items-center justify-end space-x-1">
|
||||||
|
<Button
|
||||||
|
size={'icon'}
|
||||||
|
variant={'ghost'}
|
||||||
|
onClick={() => table.setPageIndex(0)}
|
||||||
|
disabled={!table.getCanPreviousPage()}
|
||||||
|
>
|
||||||
|
<ChevronsLeft className={'h-4'} />
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
size={'icon'}
|
||||||
|
variant={'ghost'}
|
||||||
|
onClick={() => table.previousPage()}
|
||||||
|
disabled={!table.getCanPreviousPage()}
|
||||||
|
>
|
||||||
|
<ChevronLeft className={'h-4'} />
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
size={'icon'}
|
||||||
|
variant={'ghost'}
|
||||||
|
onClick={() => table.nextPage()}
|
||||||
|
disabled={!table.getCanNextPage()}
|
||||||
|
>
|
||||||
|
<ChevronRight className={'h-4'} />
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
size={'icon'}
|
||||||
|
variant={'ghost'}
|
||||||
|
onClick={() => table.setPageIndex(table.getPageCount() - 1)}
|
||||||
|
disabled={!table.getCanNextPage()}
|
||||||
|
>
|
||||||
|
<ChevronsRight className={'h-4'} />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
useReactTable,
|
useReactTable,
|
||||||
} from '@tanstack/react-table';
|
} from '@tanstack/react-table';
|
||||||
|
|
||||||
|
import { Trans } from '../makerkit/trans';
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@@ -52,6 +53,7 @@ export function DataTable<TData, TValue>({
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
|
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{table.getRowModel().rows?.length ? (
|
{table.getRowModel().rows?.length ? (
|
||||||
table.getRowModel().rows.map((row) => (
|
table.getRowModel().rows.map((row) => (
|
||||||
@@ -69,7 +71,7 @@ export function DataTable<TData, TValue>({
|
|||||||
) : (
|
) : (
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||||
No results.
|
<Trans i18nKey={'common:noData'} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
)}
|
)}
|
||||||
|
|||||||
1313
pnpm-lock.yaml
generated
1313
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user