From 77e25b7081ec53b32b6ac6d7e87b45a750303ac7 Mon Sep 17 00:00:00 2001 From: pro-minhaj Date: Fri, 9 Aug 2024 01:32:24 +0600 Subject: [PATCH] Implement Courses Page Course Pagination using shadcn and mongoose --- .../courses/(courses-page)/@courses/page.js | 22 +- components/globals/Pagination/Pagination.jsx | 72 + components/ui/button.jsx | 2 +- components/ui/pagination.jsx | 104 + package-lock.json | 7315 +++++------------ queries/courses.js | 16 +- 6 files changed, 2428 insertions(+), 5103 deletions(-) create mode 100644 components/globals/Pagination/Pagination.jsx create mode 100644 components/ui/pagination.jsx diff --git a/app/(main)/courses/(courses-page)/@courses/page.js b/app/(main)/courses/(courses-page)/@courses/page.js index e92aed3..262bd35 100644 --- a/app/(main)/courses/(courses-page)/@courses/page.js +++ b/app/(main)/courses/(courses-page)/@courses/page.js @@ -1,23 +1,31 @@ import CourseCard from '@/components/globals/CourseCard/CourseCard'; -import { coursesByFilter } from '@/queries/courses'; +import CoursePagination from '@/components/globals/Pagination/Pagination'; +import { coursesByFilter, getTotalCourse } from '@/queries/courses'; export const dynamic = 'force-dynamic'; -const CoursesSectionPage = async ({ searchParams: { s, categories, price, sort } }) => { +const CoursesSectionPage = async ({ searchParams: { s, categories, price, sort, page } }) => { + const totalCourse = await getTotalCourse(); const courses = await coursesByFilter({ search: s, categories: categories?.split(',') || '', price, - sort: sort === 'price-asc' ? 'asc' : 'desc' + sort: sort === 'price-asc' ? 'asc' : 'desc', + page: parseInt(page) || 1, + perPage: 6 }); + const totalPage = Math.round(totalCourse / 6); return ( <> {courses?.length > 0 ? ( -
- {courses?.map((course) => ( - - ))} +
+
+ {courses?.map((course) => ( + + ))} +
+
) : (
diff --git a/components/globals/Pagination/Pagination.jsx b/components/globals/Pagination/Pagination.jsx new file mode 100644 index 0000000..0ad4722 --- /dev/null +++ b/components/globals/Pagination/Pagination.jsx @@ -0,0 +1,72 @@ +"use client"; +import { usePathname, useRouter, useSearchParams } from 'next/navigation'; +import { + Pagination, + PaginationContent, + PaginationEllipsis, + PaginationItem, + PaginationLink, + PaginationNext, + PaginationPrevious, +} from "@/components/ui/pagination"; +import { useCallback } from 'react'; + +const CoursePagination = ({ currentPage, totalPages }) => { + const router = useRouter(); + const searchParams = useSearchParams(); + const pathname = usePathname(); + + const goToPage = useCallback((page) => { + const params = new URLSearchParams(searchParams); + params.set('page', page); + router.replace(`${pathname}?${params.toString()}`); + }, [searchParams, pathname, router]); + + return ( +
+ + + + goToPage(currentPage - 1)} + disabled={currentPage === 1} + > + Previous + + + + {[...Array(totalPages)].map((_, index) => { + const pageNumber = index + 1; + return ( + + goToPage(pageNumber)} + isActive={pageNumber === currentPage} + > + {pageNumber} + + + ); + })} + + {totalPages > 5 && currentPage < totalPages - 3 && ( + + + + )} + + + goToPage(currentPage + 1)} + disabled={currentPage === totalPages} + > + Next + + + + +
+ ); +}; + +export default CoursePagination; diff --git a/components/ui/button.jsx b/components/ui/button.jsx index 2305d34..87c6ba8 100644 --- a/components/ui/button.jsx +++ b/components/ui/button.jsx @@ -5,7 +5,7 @@ import { cva } from "class-variance-authority"; import { cn } from "@/lib/utils" const buttonVariants = cva( - "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-opacity-50", + "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50", { variants: { variant: { diff --git a/components/ui/pagination.jsx b/components/ui/pagination.jsx new file mode 100644 index 0000000..07fe40e --- /dev/null +++ b/components/ui/pagination.jsx @@ -0,0 +1,104 @@ +import * as React from "react" +import { + ChevronLeftIcon, + ChevronRightIcon, + DotsHorizontalIcon, +} from "@radix-ui/react-icons" + +import { cn } from "@/lib/utils" +import { buttonVariants } from "@/components/ui/button"; + +const Pagination = ({ + className, + ...props +}) => ( +