diff --git a/apps/web/src/app/(dashboard)/admin/users/data-table-users.tsx b/apps/web/src/app/(dashboard)/admin/users/data-table-users.tsx index 7c1ec0520..456fda7cd 100644 --- a/apps/web/src/app/(dashboard)/admin/users/data-table-users.tsx +++ b/apps/web/src/app/(dashboard)/admin/users/data-table-users.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useTransition } from 'react'; +import { useEffect, useState, useTransition } from 'react'; import Link from 'next/link'; @@ -11,6 +11,12 @@ import { Document, Role, Subscription } from '@documenso/prisma/client'; import { Button } from '@documenso/ui/primitives/button'; import { DataTable } from '@documenso/ui/primitives/data-table'; import { DataTablePagination } from '@documenso/ui/primitives/data-table-pagination'; +import { Input } from '@documenso/ui/primitives/input'; +import { useToast } from '@documenso/ui/primitives/use-toast'; + +import { useDebouncedValue } from '~/hooks/use-debounced-value'; + +import { search } from './fetch-users.actions'; interface User { id: number; @@ -29,15 +35,19 @@ type SubscriptionLite = Pick< type DocumentLite = Pick; type UsersDataTableProps = { - users: User[]; perPage: number; page: number; - totalPages: number; }; -export const UsersDataTable = ({ users, perPage, page, totalPages }: UsersDataTableProps) => { +export const UsersDataTable = ({ perPage, page }: UsersDataTableProps) => { + const { toast } = useToast(); + const [isPending, startTransition] = useTransition(); const updateSearchParams = useUpdateSearchParams(); + const [data, setData] = useState([]); + const [searchString, setSearchString] = useState(''); + const [totalPages, setTotalPages] = useState(0); + const debouncedSearchString = useDebouncedValue(searchString, 500); const onPaginationChange = (page: number, perPage: number) => { startTransition(() => { @@ -48,8 +58,48 @@ export const UsersDataTable = ({ users, perPage, page, totalPages }: UsersDataTa }); }; + useEffect(() => { + const fetchData = async () => { + try { + const result = await search(debouncedSearchString, page, perPage); + setData(result.users); + setTotalPages(result.totalPages); + + if (result.totalPages < page) { + startTransition(() => { + updateSearchParams({ + page: 1, + perPage, + }); + }); + } + } catch (err) { + throw new Error(err); + } + }; + + fetchData().catch(() => { + toast({ + title: 'Something went wrong', + description: 'Please try again', + variant: 'destructive', + }); + }); + }, [debouncedSearchString, page, perPage]); + + const handleChange = (e: React.ChangeEvent) => { + setSearchString(e.target.value); + }; + return (
+

Manage users

- +
); } diff --git a/apps/web/src/app/(dashboard)/admin/users/users.tsx b/apps/web/src/app/(dashboard)/admin/users/users.tsx deleted file mode 100644 index c27f71472..000000000 --- a/apps/web/src/app/(dashboard)/admin/users/users.tsx +++ /dev/null @@ -1,91 +0,0 @@ -'use client'; - -import { useEffect, useState, useTransition } from 'react'; - -import { Loader } from 'lucide-react'; - -import { Document, Role, Subscription } from '@documenso/prisma/client'; -import { Button } from '@documenso/ui/primitives/button'; -import { Input } from '@documenso/ui/primitives/input'; - -import { useDebouncedValue } from '~/hooks/use-debounced-value'; - -import { UsersDataTable } from './data-table-users'; - -export type SubscriptionLite = Pick< - Subscription, - 'id' | 'status' | 'planId' | 'priceId' | 'createdAt' | 'periodEnd' ->; -export type DocumentLite = Pick; - -export type User = { - id: number; - name: string | null; - email: string; - roles: Role[]; - Subscription: SubscriptionLite[]; - Document: DocumentLite[]; -}; - -export type UsersProps = { - search: (_search: string) => Promise<{ users: User[]; totalPages: number }>; - perPage: number; - page: number; -}; - -export const Users = ({ search, perPage, page }: UsersProps) => { - const [data, setData] = useState([]); - const [totalPages, setTotalPages] = useState(0); - const [isPending, startTransition] = useTransition(); - const [searchString, setSearchString] = useState(''); - const debouncedSearchString = useDebouncedValue(searchString, 500); - - useEffect(() => { - const fetchData = async () => { - try { - const result = await search(debouncedSearchString); - setData(result.users); - setTotalPages(result.totalPages); - } catch (err) { - throw new Error(err); - } - }; - - fetchData(); - }, [debouncedSearchString, search]); - - const onSubmit = (e: React.FormEvent) => { - e.preventDefault(); - startTransition(async () => { - const result = await search(debouncedSearchString); - setData(result.users); - }); - }; - - const handleChange = (e: React.ChangeEvent) => { - setSearchString(e.target.value); - }; - - return ( - <> -
- - -
-
- {data.length === 0 || isPending ? ( -
- -
- ) : ( - - )} -
- - ); -};