🛂 Migrate frontend to Shadcn (#2010)

* 🔧 Add Tailwind, update dependencies and config files

* ✨ Introduce new Shadcn components and remove old ones

* 🔧 Update dependencies

* Add new components.json file

* 🔥 Remove Chakra UI files

* 🔧 Add ThemeProvider component and integrate it into main

* 🔥 Remove common components

* Update primary color

* ✨ Add new components

* ✨ Add AuthLayout component

* 🔧 Add utility function cn

* 🔧 Refactor devtools integration and update dependencies

* ✨ Add Footer and Error components

* ♻️ Update Footer

* 🔥 Remove utils

* ♻️ Refactor error handling in useAuth

* ♻️ Refactor useCustomToast

* ♻️ Refactor Login component and form handling

* ♻️ Refactor SignUp component and form handling

* 🔧 Update dependencies

* ♻️ Refactor RecoverPassword component and form handling

* ♻️ Refactor ResetPassword and form handling

* ♻️ Add error component to root route

* ♻️ Refactor error handling in utils

* ♻️ Update buttons

* 🍱 Add icons and logos assets

* ♻️ Refactor Sidebar component

* 🎨 Format

* ♻️ Refactor ThemeProvider

* ♻️ Refactor Common components

* 🔥 Remove old Appearance component

* ✨ Add Sidebar components

* ♻️ Refactor DeleteAccount components

* ♻️ Refactor ChangePassword component

* ♻️ Refactor UserSettings

* ✨ Add TanStack table

* ♻️ Update SignUp

* ✨ Add Select component

* 🎨 Format

* ♻️ Update Footer

* ✨ Add useCopyToClipboard hook

* 🎨 Tweak table styles

* 🎨 Tweak styling

* ♻️ Refactor AddUser and AddItem components

* ♻️ Update DeleteConfirmation

* ✅ Update tests

* ✅ Update tests

* ✅ Fix tests

* ✨ Add DataTable for item and admin management

* ♻️ Refactor DeleteUser and DeleteItem components

* ✅ Fix tests

* ♻️ Refactor EditUser and EditItem components

* ♻️ Refactor UserInformation component

* 🎨 Format

* ♻️ Refactor pending components

* 🎨 Format

* ✅ Update tests

* ✅ Update tests

* ✅ Fix test

* ♻️ Minor tweaks

* ♻️ Update social media links
This commit is contained in:
Alejandra
2025-12-07 13:21:13 +01:00
committed by GitHub
parent 61b7cd673a
commit 8c2532a5c3
104 changed files with 8891 additions and 3287 deletions
+35 -119
View File
@@ -1,146 +1,62 @@
import {
Container,
EmptyState,
Flex,
Heading,
Table,
VStack,
} from "@chakra-ui/react"
import { useQuery } from "@tanstack/react-query"
import { createFileRoute, useNavigate } from "@tanstack/react-router"
import { FiSearch } from "react-icons/fi"
import { z } from "zod"
import { useSuspenseQuery } from "@tanstack/react-query"
import { createFileRoute } from "@tanstack/react-router"
import { Search } from "lucide-react"
import { Suspense } from "react"
import { ItemsService } from "@/client"
import { ItemActionsMenu } from "@/components/Common/ItemActionsMenu"
import { DataTable } from "@/components/Common/DataTable"
import AddItem from "@/components/Items/AddItem"
import { columns } from "@/components/Items/columns"
import PendingItems from "@/components/Pending/PendingItems"
import {
PaginationItems,
PaginationNextTrigger,
PaginationPrevTrigger,
PaginationRoot,
} from "@/components/ui/pagination.tsx"
const itemsSearchSchema = z.object({
page: z.number().catch(1),
})
const PER_PAGE = 5
function getItemsQueryOptions({ page }: { page: number }) {
function getItemsQueryOptions() {
return {
queryFn: () =>
ItemsService.readItems({ skip: (page - 1) * PER_PAGE, limit: PER_PAGE }),
queryKey: ["items", { page }],
queryFn: () => ItemsService.readItems({ skip: 0, limit: 100 }),
queryKey: ["items"],
}
}
export const Route = createFileRoute("/_layout/items")({
component: Items,
validateSearch: (search) => itemsSearchSchema.parse(search),
})
function ItemsTable() {
const navigate = useNavigate({ from: Route.fullPath })
const { page } = Route.useSearch()
function ItemsTableContent() {
const { data: items } = useSuspenseQuery(getItemsQueryOptions())
const { data, isLoading, isPlaceholderData } = useQuery({
...getItemsQueryOptions({ page }),
placeholderData: (prevData) => prevData,
})
const setPage = (page: number) => {
navigate({
to: "/items",
search: (prev) => ({ ...prev, page }),
})
}
const items = data?.data.slice(0, PER_PAGE) ?? []
const count = data?.count ?? 0
if (isLoading) {
return <PendingItems />
}
if (items.length === 0) {
if (items.data.length === 0) {
return (
<EmptyState.Root>
<EmptyState.Content>
<EmptyState.Indicator>
<FiSearch />
</EmptyState.Indicator>
<VStack textAlign="center">
<EmptyState.Title>You don't have any items yet</EmptyState.Title>
<EmptyState.Description>
Add a new item to get started
</EmptyState.Description>
</VStack>
</EmptyState.Content>
</EmptyState.Root>
<div className="flex flex-col items-center justify-center text-center py-12">
<div className="rounded-full bg-muted p-4 mb-4">
<Search className="h-8 w-8 text-muted-foreground" />
</div>
<h3 className="text-lg font-semibold">You don't have any items yet</h3>
<p className="text-muted-foreground">Add a new item to get started</p>
</div>
)
}
return <DataTable columns={columns} data={items.data} />
}
function ItemsTable() {
return (
<>
<Table.Root size={{ base: "sm", md: "md" }}>
<Table.Header>
<Table.Row>
<Table.ColumnHeader w="sm">ID</Table.ColumnHeader>
<Table.ColumnHeader w="sm">Title</Table.ColumnHeader>
<Table.ColumnHeader w="sm">Description</Table.ColumnHeader>
<Table.ColumnHeader w="sm">Actions</Table.ColumnHeader>
</Table.Row>
</Table.Header>
<Table.Body>
{items?.map((item) => (
<Table.Row key={item.id} opacity={isPlaceholderData ? 0.5 : 1}>
<Table.Cell truncate maxW="sm">
{item.id}
</Table.Cell>
<Table.Cell truncate maxW="sm">
{item.title}
</Table.Cell>
<Table.Cell
color={!item.description ? "gray" : "inherit"}
truncate
maxW="30%"
>
{item.description || "N/A"}
</Table.Cell>
<Table.Cell>
<ItemActionsMenu item={item} />
</Table.Cell>
</Table.Row>
))}
</Table.Body>
</Table.Root>
<Flex justifyContent="flex-end" mt={4}>
<PaginationRoot
count={count}
pageSize={PER_PAGE}
onPageChange={({ page }) => setPage(page)}
>
<Flex>
<PaginationPrevTrigger />
<PaginationItems />
<PaginationNextTrigger />
</Flex>
</PaginationRoot>
</Flex>
</>
<Suspense fallback={<PendingItems />}>
<ItemsTableContent />
</Suspense>
)
}
function Items() {
return (
<Container maxW="full">
<Heading size="lg" pt={12}>
Items Management
</Heading>
<AddItem />
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div>
<h1 className="text-2xl font-bold tracking-tight">Items</h1>
<p className="text-muted-foreground">Create and manage your items</p>
</div>
<AddItem />
</div>
<ItemsTable />
</Container>
</div>
)
}