🚸 Use useSuspenseQuery to fetch members and show skeleton (#1174)

This commit is contained in:
Patrick Arminio
2024-04-16 16:56:59 +02:00
committed by GitHub
parent fb361b1bf6
commit 472e0f254b

View File

@@ -4,7 +4,7 @@ import {
Container, Container,
Flex, Flex,
Heading, Heading,
Spinner, SkeletonText,
Table, Table,
TableContainer, TableContainer,
Tbody, Tbody,
@@ -13,106 +13,103 @@ 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 (
<> <Tbody>
{isLoading ? ( {users.data.map((user) => (
// TODO: Add skeleton <Tr key={user.id}>
<Flex justify="center" align="center" height="100vh" width="full"> <Td color={!user.full_name ? "ui.dim" : "inherit"}>
<Spinner size="xl" color="ui.main" /> {user.full_name || "N/A"}
</Flex> {currentUser?.id === user.id && (
) : ( <Badge ml="1" colorScheme="teal">
users && ( You
<Container maxW="full"> </Badge>
<Heading )}
size="lg" </Td>
textAlign={{ base: "center", md: "left" }} <Td>{user.email}</Td>
pt={12} <Td>{user.is_superuser ? "Superuser" : "User"}</Td>
> <Td>
User Management <Flex gap={2}>
</Heading> <Box
<Navbar type={"User"} /> w="2"
<TableContainer> h="2"
<Table fontSize="md" size={{ base: "sm", md: "md" }}> borderRadius="50%"
<Thead> bg={user.is_active ? "ui.success" : "ui.danger"}
<Tr> alignSelf="center"
<Th>Full name</Th> />
<Th>Email</Th> {user.is_active ? "Active" : "Inactive"}
<Th>Role</Th> </Flex>
<Th>Status</Th> </Td>
<Th>Actions</Th> <Td>
</Tr> <ActionsMenu
</Thead> type="User"
<Tbody> value={user}
{users.data.map((user) => ( disabled={currentUser?.id === user.id ? true : false}
<Tr key={user.id}> />
<Td color={!user.full_name ? "ui.dim" : "inherit"}> </Td>
{user.full_name || "N/A"} </Tr>
{currentUser?.id === user.id && ( ))}
<Badge ml="1" colorScheme="teal"> </Tbody>
You )
</Badge> }
)}
</Td> const MembersBodySkeleton = () => {
<Td>{user.email}</Td> return (
<Td>{user.is_superuser ? "Superuser" : "User"}</Td> <Tbody>
<Td> <Tr>
<Flex gap={2}> {new Array(5).fill(null).map((_, index) => (
<Box <Td key={index}>
w="2" <SkeletonText noOfLines={1} paddingBlock="16px" />
h="2" </Td>
borderRadius="50%" ))}
bg={user.is_active ? "ui.success" : "ui.danger"} </Tr>
alignSelf="center" </Tbody>
/> )
{user.is_active ? "Active" : "Inactive"} }
</Flex>
</Td> function Admin() {
<Td> return (
<ActionsMenu <Container maxW="full">
type="User" <Heading size="lg" textAlign={{ base: "center", md: "left" }} pt={12}>
value={user} User Management
disabled={currentUser?.id === user.id ? true : false} </Heading>
/> <Navbar type={"User"} />
</Td> <TableContainer>
</Tr> <Table fontSize="md" size={{ base: "sm", md: "md" }}>
))} <Thead>
</Tbody> <Tr>
</Table> <Th width="20%">Full name</Th>
</TableContainer> <Th width="50%">Email</Th>
</Container> <Th width="10%">Role</Th>
) <Th width="10%">Status</Th>
)} <Th width="10%">Actions</Th>
</> </Tr>
</Thead>
<Suspense fallback={<MembersBodySkeleton />}>
<MembersTableBody />
</Suspense>
</Table>
</TableContainer>
</Container>
) )
} }