Skip to content

Commit fa3d3e1

Browse files
committed
style: change style
1 parent a5fe17c commit fa3d3e1

File tree

1 file changed

+158
-80
lines changed

1 file changed

+158
-80
lines changed
Lines changed: 158 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,137 @@
1-
// --- НАЧАЛО ИСПРАВЛЕННОГО КОДА ---
2-
import { Badge, Container, Flex, Heading, Table } from "@chakra-ui/react"
3-
import { useQuery, useQueryClient } from "@tanstack/react-query"
1+
/**
2+
* @file Defines the Admin page component for managing users.
3+
* @description Renders a page with a paginated table of users, providing functionality to add users and perform actions on existing users.
4+
* @module Admin
5+
*/
6+
7+
import { Badge, Container, EmptyState, Flex, Heading, Table, VStack } from "@chakra-ui/react"
8+
import { type UseQueryResult, useQuery } from "@tanstack/react-query"
49
import { createFileRoute, useNavigate } from "@tanstack/react-router"
10+
import type React from "react"
11+
import type { FC } from "react"
12+
import { useCallback, useEffect } from "react"
13+
import { FiUsers } from "react-icons/fi"
514
import { z } from "zod"
615

7-
import {
8-
// ИМПОРТИРУЕМ ТОЧНУЮ ФУНКЦИЮ И ТИП
9-
type UserPublic,
10-
usersUsersRouterReadUsers,
11-
} from "@/client"
16+
import { type CancelablePromise, type UserPublic, type UsersPublic, usersUsersRouterReadUsers } from "@/client"
1217
import AddUser from "@/components/Admin/AddUser"
1318
import { UserActionsMenu } from "@/components/Common/UserActionsMenu"
14-
import PendingUsers from "@/components/Pending/PendingUsers"
1519
import {
1620
PaginationItems,
1721
PaginationNextTrigger,
1822
PaginationPrevTrigger,
1923
PaginationRoot,
20-
} from "@/components/ui/pagination.tsx"
24+
} from "@/components/ui/pagination"
25+
import useAuth from "@/hooks/useAuth"
26+
27+
// region Type Aliases
28+
29+
/**
30+
* Type alias for the search parameters schema.
31+
* @type {SearchParams}
32+
*/
33+
type SearchParams = { page: number }
34+
35+
/**
36+
* Type alias for the Admin component.
37+
* @type {AdminComponent}
38+
*/
39+
type AdminComponent = FC
40+
41+
/**
42+
* Type alias for the UsersTable component.
43+
* @type {UsersTableComponent}
44+
*/
45+
type UsersTableComponent = FC
46+
47+
// endregion
2148

49+
// region Main Code
50+
51+
/**
52+
* Schema for validating search parameters for users pagination.
53+
* @constant {z.ZodObject}
54+
*/
2255
const usersSearchSchema = z.object({
23-
page: z.number().catch(1),
56+
/** The current page number. */
57+
page: z.number().int().min(1).catch(1),
2458
})
2559

26-
const PER_PAGE = 5
27-
28-
function getUsersQueryOptions({ page }: { page: number }) {
29-
return {
30-
// ВЫЗЫВАЕМ ФУНКЦИЮ НАПРЯМУЮ
31-
queryFn: () =>
32-
usersUsersRouterReadUsers({
33-
skip: (page - 1) * PER_PAGE,
34-
limit: PER_PAGE,
35-
}),
36-
queryKey: ["users", { page }],
37-
}
60+
/**
61+
* Number of users per page.
62+
* @constant {number}
63+
*/
64+
const PER_PAGE: number = 5
65+
66+
/**
67+
* Main Admin page component for managing users.
68+
* @returns {React.ReactElement} The rendered Admin component.
69+
*/
70+
const Admin: AdminComponent = (): React.ReactElement => {
71+
return (
72+
<main>
73+
<Container maxW="full">
74+
<Heading size="lg" pt={12}>
75+
Users Management
76+
</Heading>
77+
<AddUser />
78+
<UsersTable />
79+
</Container>
80+
</main>
81+
)
3882
}
3983

40-
export const Route = createFileRoute("/_layout/admin")({
41-
component: Admin,
42-
validateSearch: (search) => usersSearchSchema.parse(search),
43-
})
84+
/**
85+
* Component for rendering a paginated table of users with actions.
86+
* @returns {React.ReactElement} The rendered UsersTable component.
87+
*/
88+
const UsersTable: UsersTableComponent = (): React.ReactElement => {
89+
const { user: currentUser } = useAuth()
90+
const navigate: ReturnType<typeof useNavigate> = useNavigate({ from: Route.fullPath })
91+
const { page }: SearchParams = Route.useSearch()
4492

45-
function UsersTable() {
46-
const queryClient = useQueryClient()
47-
const currentUser = queryClient.getQueryData<UserPublic>(["currentUser"])
48-
const navigate = useNavigate({ from: Route.fullPath })
49-
const { page } = Route.useSearch()
93+
const usersQueryKey: [string, { page: number }] = ["users", { page }]
5094

51-
const { data, isLoading, isPlaceholderData } = useQuery({
52-
...getUsersQueryOptions({ page }),
53-
placeholderData: (prevData) => prevData,
95+
const { data, isPlaceholderData }: UseQueryResult<UsersPublic, Error> = useQuery({
96+
queryFn: (): CancelablePromise<UsersPublic> =>
97+
usersUsersRouterReadUsers({ skip: (page - 1) * PER_PAGE, limit: PER_PAGE }),
98+
queryKey: usersQueryKey,
99+
placeholderData: (prevData: UsersPublic | undefined): UsersPublic | undefined => prevData,
100+
staleTime: 1000 * 10,
54101
})
55102

56-
const setPage = (page: number) =>
57-
// Добавляем 'void'
58-
void navigate({
59-
search: (prev: { [key: string]: string }) => ({ ...prev, page }),
60-
})
103+
const setPage: (page: number) => void = useCallback(
104+
(newPage: number): void => {
105+
void navigate({
106+
search: (prev: SearchParams): { page: number } => ({ ...prev, page: newPage }),
107+
})
108+
},
109+
[navigate],
110+
)
111+
112+
useEffect((): void => {
113+
if (data && data.data.length === 0 && data.count > 0 && page > 1) {
114+
setPage(page - 1)
115+
}
116+
}, [data, page, setPage])
61117

62-
const users = data?.data.slice(0, PER_PAGE) ?? []
63-
const count = data?.count ?? 0
118+
const users: UserPublic[] = data?.data ?? []
119+
const count: number = data?.count ?? 0
64120

65-
if (isLoading) {
66-
return <PendingUsers />
121+
if (users.length === 0) {
122+
return (
123+
<EmptyState.Root>
124+
<EmptyState.Content>
125+
<EmptyState.Indicator>
126+
<FiUsers />
127+
</EmptyState.Indicator>
128+
<VStack textAlign="center">
129+
<EmptyState.Title>No users found</EmptyState.Title>
130+
<EmptyState.Description>Add a new user to get started</EmptyState.Description>
131+
</VStack>
132+
</EmptyState.Content>
133+
</EmptyState.Root>
134+
)
67135
}
68136

69137
return (
@@ -79,51 +147,61 @@ function UsersTable() {
79147
</Table.Row>
80148
</Table.Header>
81149
<Table.Body>
82-
{users?.map((user) => (
83-
<Table.Row key={user.id} opacity={isPlaceholderData ? 0.5 : 1}>
84-
<Table.Cell color={!user.full_name ? "gray" : "inherit"}>
85-
{user.full_name || "N/A"}
86-
{currentUser?.id === user.id && (
87-
<Badge ml="1" colorScheme="teal">
88-
You
89-
</Badge>
90-
)}
91-
</Table.Cell>
92-
<Table.Cell truncate maxW="sm">
93-
{user.email}
94-
</Table.Cell>
95-
<Table.Cell>{user.is_superuser ? "Superuser" : "User"}</Table.Cell>
96-
<Table.Cell>{user.is_active ? "Active" : "Inactive"}</Table.Cell>
97-
<Table.Cell>
98-
<UserActionsMenu user={user} disabled={currentUser?.id === user.id} />
99-
</Table.Cell>
100-
</Table.Row>
101-
))}
150+
{users.map(
151+
(user: UserPublic): React.ReactElement => (
152+
<Table.Row key={user.id} opacity={isPlaceholderData ? 0.5 : 1}>
153+
<Table.Cell color={!user.full_name ? "gray" : "inherit"}>
154+
{user.full_name || "N/A"}
155+
{currentUser?.id === user.id && (
156+
<Badge ml="1" colorScheme="teal">
157+
You
158+
</Badge>
159+
)}
160+
</Table.Cell>
161+
<Table.Cell truncate maxW="sm">
162+
{user.email}
163+
</Table.Cell>
164+
<Table.Cell>{user.is_superuser ? "Superuser" : "User"}</Table.Cell>
165+
<Table.Cell>{user.is_active ? "Active" : "Inactive"}</Table.Cell>
166+
<Table.Cell>
167+
<UserActionsMenu user={user} disabled={currentUser?.id === user.id} />
168+
</Table.Cell>
169+
</Table.Row>
170+
),
171+
)}
102172
</Table.Body>
103173
</Table.Root>
104174
<Flex justifyContent="flex-end" mt={4}>
105-
<PaginationRoot count={count} pageSize={PER_PAGE} onPageChange={({ page }) => setPage(page)}>
175+
<PaginationRoot
176+
count={count}
177+
pageSize={PER_PAGE}
178+
page={page}
179+
onPageChange={({ page: newPage }) => setPage(newPage)}
180+
>
106181
<Flex>
107-
<PaginationPrevTrigger />
182+
<PaginationPrevTrigger aria-label="Previous page" />
108183
<PaginationItems />
109-
<PaginationNextTrigger />
184+
<PaginationNextTrigger aria-label="Next page" />
110185
</Flex>
111186
</PaginationRoot>
112187
</Flex>
113188
</>
114189
)
115190
}
116191

117-
function Admin() {
118-
return (
119-
<Container maxW="full">
120-
<Heading size="lg" pt={12}>
121-
Users Management
122-
</Heading>
123-
124-
<AddUser />
125-
<UsersTable />
126-
</Container>
127-
)
128-
}
129-
// --- КОНЕЦ ИСПРАВЛЕННОГО КОДА ---
192+
// endregion
193+
194+
// region Optional Declarations
195+
196+
Admin.displayName = "Admin"
197+
UsersTable.displayName = "UsersTable"
198+
199+
export const Route = createFileRoute("/_layout/admin")({
200+
component: Admin,
201+
validateSearch: (search: Record<string, unknown>): SearchParams => usersSearchSchema.parse(search),
202+
})
203+
204+
// endregion
205+
206+
// noinspection JSUnusedGlobalSymbols
207+
export default Admin

0 commit comments

Comments
 (0)