|
@ -4,7 +4,7 @@ import { |
|
|
Container, |
|
|
Container, |
|
|
Flex, |
|
|
Flex, |
|
|
Heading, |
|
|
Heading, |
|
|
Spinner, |
|
|
SkeletonText, |
|
|
Table, |
|
|
Table, |
|
|
TableContainer, |
|
|
TableContainer, |
|
|
Tbody, |
|
|
Tbody, |
|
@ -13,66 +13,28 @@ import { |
|
|
Thead, |
|
|
Thead, |
|
|
Tr, |
|
|
Tr, |
|
|
} from "@chakra-ui/react" |
|
|
} from "@chakra-ui/react" |
|
|
import { useQuery, useQueryClient } from "@tanstack/react-query" |
|
|
import { useQueryClient, useSuspenseQuery } from "@tanstack/react-query" |
|
|
import { createFileRoute } from "@tanstack/react-router" |
|
|
import { createFileRoute } from "@tanstack/react-router" |
|
|
|
|
|
|
|
|
|
|
|
import { Suspense } from "react" |
|
|
import { type UserPublic, UsersService } from "../../client" |
|
|
import { type UserPublic, UsersService } from "../../client" |
|
|
import ActionsMenu from "../../components/Common/ActionsMenu" |
|
|
import ActionsMenu from "../../components/Common/ActionsMenu" |
|
|
import Navbar from "../../components/Common/Navbar" |
|
|
import Navbar from "../../components/Common/Navbar" |
|
|
import useCustomToast from "../../hooks/useCustomToast" |
|
|
|
|
|
|
|
|
|
|
|
export const Route = createFileRoute("/_layout/admin")({ |
|
|
export const Route = createFileRoute("/_layout/admin")({ |
|
|
component: Admin, |
|
|
component: Admin, |
|
|
}) |
|
|
}) |
|
|
|
|
|
|
|
|
function Admin() { |
|
|
const MembersTableBody = () => { |
|
|
const queryClient = useQueryClient() |
|
|
const queryClient = useQueryClient() |
|
|
const showToast = useCustomToast() |
|
|
|
|
|
const currentUser = queryClient.getQueryData<UserPublic>(["currentUser"]) |
|
|
const currentUser = queryClient.getQueryData<UserPublic>(["currentUser"]) |
|
|
const { |
|
|
|
|
|
data: users, |
|
|
const { data: users } = useSuspenseQuery({ |
|
|
isLoading, |
|
|
|
|
|
isError, |
|
|
|
|
|
error, |
|
|
|
|
|
} = useQuery({ |
|
|
|
|
|
queryKey: ["users"], |
|
|
queryKey: ["users"], |
|
|
queryFn: () => UsersService.readUsers({}), |
|
|
queryFn: () => UsersService.readUsers({}), |
|
|
}) |
|
|
}) |
|
|
|
|
|
|
|
|
if (isError) { |
|
|
|
|
|
const errDetail = (error as any).body?.detail |
|
|
|
|
|
showToast("Something went wrong.", `${errDetail}`, "error") |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return ( |
|
|
return ( |
|
|
<> |
|
|
|
|
|
{isLoading ? ( |
|
|
|
|
|
// TODO: Add skeleton
|
|
|
|
|
|
<Flex justify="center" align="center" height="100vh" width="full"> |
|
|
|
|
|
<Spinner size="xl" color="ui.main" /> |
|
|
|
|
|
</Flex> |
|
|
|
|
|
) : ( |
|
|
|
|
|
users && ( |
|
|
|
|
|
<Container maxW="full"> |
|
|
|
|
|
<Heading |
|
|
|
|
|
size="lg" |
|
|
|
|
|
textAlign={{ base: "center", md: "left" }} |
|
|
|
|
|
pt={12} |
|
|
|
|
|
> |
|
|
|
|
|
User Management |
|
|
|
|
|
</Heading> |
|
|
|
|
|
<Navbar type={"User"} /> |
|
|
|
|
|
<TableContainer> |
|
|
|
|
|
<Table fontSize="md" size={{ base: "sm", md: "md" }}> |
|
|
|
|
|
<Thead> |
|
|
|
|
|
<Tr> |
|
|
|
|
|
<Th>Full name</Th> |
|
|
|
|
|
<Th>Email</Th> |
|
|
|
|
|
<Th>Role</Th> |
|
|
|
|
|
<Th>Status</Th> |
|
|
|
|
|
<Th>Actions</Th> |
|
|
|
|
|
</Tr> |
|
|
|
|
|
</Thead> |
|
|
|
|
|
<Tbody> |
|
|
<Tbody> |
|
|
{users.data.map((user) => ( |
|
|
{users.data.map((user) => ( |
|
|
<Tr key={user.id}> |
|
|
<Tr key={user.id}> |
|
@ -108,11 +70,46 @@ function Admin() { |
|
|
</Tr> |
|
|
</Tr> |
|
|
))} |
|
|
))} |
|
|
</Tbody> |
|
|
</Tbody> |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const MembersBodySkeleton = () => { |
|
|
|
|
|
return ( |
|
|
|
|
|
<Tbody> |
|
|
|
|
|
<Tr> |
|
|
|
|
|
{new Array(5).fill(null).map((_, index) => ( |
|
|
|
|
|
<Td key={index}> |
|
|
|
|
|
<SkeletonText noOfLines={1} paddingBlock="16px" /> |
|
|
|
|
|
</Td> |
|
|
|
|
|
))} |
|
|
|
|
|
</Tr> |
|
|
|
|
|
</Tbody> |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function Admin() { |
|
|
|
|
|
return ( |
|
|
|
|
|
<Container maxW="full"> |
|
|
|
|
|
<Heading size="lg" textAlign={{ base: "center", md: "left" }} pt={12}> |
|
|
|
|
|
User Management |
|
|
|
|
|
</Heading> |
|
|
|
|
|
<Navbar type={"User"} /> |
|
|
|
|
|
<TableContainer> |
|
|
|
|
|
<Table fontSize="md" size={{ base: "sm", md: "md" }}> |
|
|
|
|
|
<Thead> |
|
|
|
|
|
<Tr> |
|
|
|
|
|
<Th width="20%">Full name</Th> |
|
|
|
|
|
<Th width="50%">Email</Th> |
|
|
|
|
|
<Th width="10%">Role</Th> |
|
|
|
|
|
<Th width="10%">Status</Th> |
|
|
|
|
|
<Th width="10%">Actions</Th> |
|
|
|
|
|
</Tr> |
|
|
|
|
|
</Thead> |
|
|
|
|
|
<Suspense fallback={<MembersBodySkeleton />}> |
|
|
|
|
|
<MembersTableBody /> |
|
|
|
|
|
</Suspense> |
|
|
</Table> |
|
|
</Table> |
|
|
</TableContainer> |
|
|
</TableContainer> |
|
|
</Container> |
|
|
</Container> |
|
|
) |
|
|
) |
|
|
)} |
|
|
|
|
|
</> |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
} |
|
|