import { useEffect, useMemo, useState, useTransition } from 'react'; import { msg } from '@lingui/core/macro'; import { useLingui } from '@lingui/react'; import { ChevronDownIcon, ChevronUpIcon, ChevronsUpDown, Loader } from 'lucide-react'; import { useDebouncedValue } from '@documenso/lib/client-only/hooks/use-debounced-value'; import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table'; import { DataTable } from '@documenso/ui/primitives/data-table'; import { DataTablePagination } from '@documenso/ui/primitives/data-table-pagination'; import { Input } from '@documenso/ui/primitives/input'; export type OrganisationOverview = { id: string; name: string; signingVolume: number; createdAt: Date; planId: string; subscriptionStatus?: string; isActive?: boolean; teamCount?: number; memberCount?: number; }; type OrganisationOverviewTableProps = { organisations: OrganisationOverview[]; totalPages: number; perPage: number; page: number; sortBy: 'name' | 'createdAt' | 'signingVolume'; sortOrder: 'asc' | 'desc'; }; export const AdminOrganisationOverviewTable = ({ organisations, totalPages, perPage, page, sortBy, sortOrder, }: OrganisationOverviewTableProps) => { const { _, i18n } = useLingui(); const [isPending, startTransition] = useTransition(); const updateSearchParams = useUpdateSearchParams(); const [searchString, setSearchString] = useState(''); const debouncedSearchString = useDebouncedValue(searchString, 1000); const columns = useMemo(() => { return [ { header: () => (
handleColumnSort('name')} > {_(msg`Name`)} {sortBy === 'name' ? ( sortOrder === 'asc' ? ( ) : ( ) ) : ( )}
), accessorKey: 'name', cell: ({ row }) => { return (
{row.getValue('name')}
); }, size: 200, }, { header: () => (
handleColumnSort('signingVolume')} > {_(msg`Document Volume`)} {sortBy === 'signingVolume' ? ( sortOrder === 'asc' ? ( ) : ( ) ) : ( )}
), accessorKey: 'signingVolume', cell: ({ row }) =>
{Number(row.getValue('signingVolume'))}
, size: 120, }, { header: () => { return
{_(msg`Status`)}
; }, accessorKey: 'subscriptionStatus', cell: ({ row }) => { const status = row.original.subscriptionStatus; return (
{status || 'Free'}
); }, size: 100, }, { header: () => { return
{_(msg`Teams`)}
; }, accessorKey: 'teamCount', cell: ({ row }) =>
{Number(row.original.teamCount) || 0}
, size: 80, }, { header: () => { return
{_(msg`Members`)}
; }, accessorKey: 'memberCount', cell: ({ row }) =>
{Number(row.original.memberCount) || 0}
, size: 80, }, { header: () => { return (
handleColumnSort('createdAt')} > {_(msg`Created`)} {sortBy === 'createdAt' ? ( sortOrder === 'asc' ? ( ) : ( ) ) : ( )}
); }, accessorKey: 'createdAt', cell: ({ row }) => i18n.date(row.original.createdAt), size: 120, }, ] satisfies DataTableColumnDef[]; }, [sortOrder, sortBy]); useEffect(() => { startTransition(() => { updateSearchParams({ search: debouncedSearchString, page: 1, perPage, sortBy, sortOrder, }); }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [debouncedSearchString]); const onPaginationChange = (page: number, perPage: number) => { startTransition(() => { updateSearchParams({ page, perPage, }); }); }; const handleChange = (e: React.ChangeEvent) => { setSearchString(e.target.value); }; const handleColumnSort = (column: 'name' | 'createdAt' | 'signingVolume') => { startTransition(() => { updateSearchParams({ search: debouncedSearchString, page, perPage, sortBy: column, sortOrder: sortBy === column && sortOrder === 'asc' ? 'desc' : 'asc', }); }); }; return (
{(table) => } {isPending && (
)}
); };