diff --git a/src/app/(gistLayout)/mygist/page-ui.tsx b/src/app/(gistLayout)/mygist/page-ui.tsx index 7dbf497..bc65ef9 100644 --- a/src/app/(gistLayout)/mygist/page-ui.tsx +++ b/src/app/(gistLayout)/mygist/page-ui.tsx @@ -1,9 +1,12 @@ -import { MyGistListFeature } from '@/components/logic/mygist-list-logic' -import { SidebarTrigger } from '@/components/shadcn/sidebar' -import MenuButton from '@/components/ui/menu-button' -import { PaginationComponent } from '@/components/ui/pagination' -import TooltipShortcut, { TooltipShortcutTrigger } from '@/components/ui/tooltip-shortcut' -import { TornadoIcon } from 'lucide-react' +import { PaginationProvider } from "@/components/contexts/pagination"; +import { MyGistListFeature } from "@/components/logic/mygist-list-logic"; +import { SidebarTrigger } from "@/components/shadcn/sidebar"; +import MenuButton from "@/components/ui/menu-button"; +import { PaginationComponent } from "@/components/ui/pagination"; +import TooltipShortcut, { + TooltipShortcutTrigger, +} from "@/components/ui/tooltip-shortcut"; +import { TornadoIcon } from "lucide-react"; interface MyGistPageProps {} @@ -12,24 +15,30 @@ export default function MyGistsPage({}: MyGistPageProps) {
- +
My Gists
- + - } variant={'menu'}> + } + variant={"menu"} + > Sort by
+
- -
-
- -
+ + +
+
+ +
+
- ) + ); } diff --git a/src/components/contexts/pagination.tsx b/src/components/contexts/pagination.tsx new file mode 100644 index 0000000..20166cf --- /dev/null +++ b/src/components/contexts/pagination.tsx @@ -0,0 +1,95 @@ +"use client"; +import { usePathname, useRouter, useSearchParams } from "next/navigation"; +import { + createContext, + ReactNode, + useCallback, + useEffect, + useState, +} from "react"; + +interface PaginationContextContent { + offset: number; + limit: number; + nb_pages?: number; + setOffset: (offset: number) => void; + setLimit: (limit: number) => void; + setNbPages: (nb_pages: number) => void; +} + +const PaginationInitialState = { + offset: 0, + limit: 9, + nb_pages: 0, + setOffset: (offset: number) => {}, + setLimit: (limit: number) => {}, + setNbPages: (nb_pages: number) => {}, +}; + +export const PaginationContext = createContext( + PaginationInitialState, +); + +export function PaginationProvider({ + children, + fromUrl, +}: { + children: ReactNode; + fromUrl: boolean; +}) { + const [offset, setOffset] = useState(PaginationInitialState.offset); + const [limit, setLimit] = useState(PaginationInitialState.limit); + const [nb_pages, setNbPages] = useState(PaginationInitialState.nb_pages); + const searchParams = useSearchParams(); + const pathname = usePathname(); + const router = useRouter(); + + const checkOffset = useCallback( + (offset: number) => { + if (offset >= 0 && offset <= nb_pages * limit) { + return true; + } + return false; + }, + [nb_pages, limit], + ); + + const setOffsetHandler = useCallback( + (offset: number) => { + if (checkOffset(offset)) { + if (fromUrl) { + const page = Math.floor(offset / limit) + 1; + router.push(`${pathname}?page=${page}`); + } + setOffset(offset); + } + }, + [checkOffset, fromUrl, limit, pathname, router], + ); + + useEffect(() => { + if (!fromUrl) return; + if (searchParams.has("page")) { + const page = parseInt(searchParams.get("page") as string); + const offset = (page - 1) * limit; + console.log("offset", offset); + if (!checkOffset(offset)) return; + setOffset(offset); + } + }, [searchParams, fromUrl, setOffset, limit, setOffsetHandler, checkOffset]); + + return ( + + {children} + + ); +} diff --git a/src/components/logic/mygist-list-logic.tsx b/src/components/logic/mygist-list-logic.tsx index 1576e26..03871e9 100644 --- a/src/components/logic/mygist-list-logic.tsx +++ b/src/components/logic/mygist-list-logic.tsx @@ -1,15 +1,27 @@ "use client"; +import { useContext, useEffect } from "react"; import MyGistList from "../ui/mygist-list"; import { useDeleteGist, useGists } from "@/lib/queries/gists.queries"; +import { PaginationContext } from "../contexts/pagination"; export function MyGistListFeature() { - const { data } = useGists(); + const { offset, limit, setNbPages } = useContext(PaginationContext); + const { data, nb_pages } = useGists({ + limit, + offset, + }); + + useEffect(() => { + setNbPages(nb_pages || 0); + }, [nb_pages, setNbPages]); + const { mutate: deleteGist } = useDeleteGist({ onSuccess: (id) => { console.log(`Deleting gist with ID: ${id}`); }, }); + const handleDeleteGist = (id: string) => { deleteGist(id); }; diff --git a/src/components/shadcn/button.tsx b/src/components/shadcn/button.tsx index b6f1a96..48c9cce 100644 --- a/src/components/shadcn/button.tsx +++ b/src/components/shadcn/button.tsx @@ -1,48 +1,63 @@ -import * as React from 'react' -import { Slot } from '@radix-ui/react-slot' -import { cva, type VariantProps } from 'class-variance-authority' +import * as React from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from '@/lib/utils' +import { cn } from "@/lib/utils"; const buttonVariants = cva( - 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50', + "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", { variants: { variant: { - default: 'bg-primary text-primary-foreground hover:bg-primary/90', - destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90', - outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground', - secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80', - ghost: 'hover:bg-light-background hover:text-foreground', - link: 'text-primary text-base underline-offset-4 hover:underline', - icon: 'text-foreground bg-icon hover:bg-icon/80', - menu: 'text-primary-foreground hover:bg-primary hover:text-primary-foreground', - header: 'hover:bg-primary hover:text-foreground', + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border border-input bg-background hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-light-background hover:text-foreground", + disabled: + "hover:bg-light-background hover:text-foreground opacity-50 cursor-not-allowed", + link: "text-primary text-base underline-offset-4 hover:underline", + icon: "text-foreground bg-icon hover:bg-icon/80", + menu: "text-primary-foreground hover:bg-primary hover:text-primary-foreground", + header: "hover:bg-primary hover:text-foreground", }, size: { - default: 'h-10 px-6 py-3', - 'no-padding': 'h-10', - sm: 'h-9 rounded-md px-3', - lg: 'h-11 rounded-md px-8', - menu: 'h-10 py-2 px-3', - icon: 'h-10 w-10', + default: "h-10 px-6 py-3", + "no-padding": "h-10", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + menu: "h-10 py-2 px-3", + icon: "h-10 w-10", }, }, defaultVariants: { - variant: 'default', - size: 'default', + variant: "default", + size: "default", }, - } -) + }, +); -export interface ButtonProps extends React.ButtonHTMLAttributes, VariantProps { - asChild?: boolean +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; } -const Button = React.forwardRef(({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : 'button' - return -}) -Button.displayName = 'Button' +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button"; + return ( + + ); + }, +); +Button.displayName = "Button"; -export { Button, buttonVariants } +export { Button, buttonVariants }; diff --git a/src/components/shadcn/pagination.tsx b/src/components/shadcn/pagination.tsx index 61b8438..1f4c286 100644 --- a/src/components/shadcn/pagination.tsx +++ b/src/components/shadcn/pagination.tsx @@ -1,64 +1,120 @@ -import * as React from 'react' -import { ChevronLeft, ChevronRight, MoreHorizontal } from 'lucide-react' +import * as React from "react"; +import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react"; -import { cn } from '@/lib/utils' -import { ButtonProps, buttonVariants } from './button' +import { cn } from "@/lib/utils"; +import { ButtonProps, buttonVariants } from "./button"; -const Pagination = ({ className, ...props }: React.ComponentProps<'nav'>) => ( -