From 8ef5545f93d671bee8ef13fcc0d4a50013f376d1 Mon Sep 17 00:00:00 2001 From: RizqiSyahrendra Date: Mon, 10 Mar 2025 22:27:56 +0700 Subject: [PATCH] fix: category page and blog card styling --- src/app/(main)/category/[...path]/page.tsx | 74 ++++++++++++++++++++++ src/app/globals.css | 4 ++ src/components/Blogs/Blog.tsx | 2 +- src/components/Blogs/BlogCardItem.tsx | 2 +- src/components/Blogs/Blogs.tsx | 6 +- src/components/Pagination.tsx | 20 ++++-- src/services/payload/blog.ts | 33 +++++++--- 7 files changed, 123 insertions(+), 18 deletions(-) create mode 100644 src/app/(main)/category/[...path]/page.tsx diff --git a/src/app/(main)/category/[...path]/page.tsx b/src/app/(main)/category/[...path]/page.tsx new file mode 100644 index 0000000..c87299f --- /dev/null +++ b/src/app/(main)/category/[...path]/page.tsx @@ -0,0 +1,74 @@ +import { BeforeFooterBlock } from "@/components/Blocks/BeforeFooter"; +import { BlogCardItemSkeleton } from "@/components/Blogs/BlogCardItem"; +import Blogs from "@/components/Blogs/Blogs"; +import HeroOther from "@/components/HeroOther"; +import { getDefaultMetadata } from "@/utils/metadata"; +import { sanitizePageNumber } from "@/utils/sanitize"; +import { Metadata } from "next"; +import { headers } from "next/headers"; +import { Suspense } from "react"; + +export async function generateMetadata(): Promise { + const metadata = await getDefaultMetadata(); + return metadata; +} + +export default async function CategoryPage({ + params, + searchParams, +}: { + params?: Promise<{ path: string[] }>; + searchParams?: Promise<{ page?: string; s?: string }>; +}) { + const path = (await params)?.path; + const headersList = await headers(); + const paramsCategory = path?.[0] ?? ""; + const paramsPage = path?.[2] ?? ""; + const paramsSearch = (await searchParams)?.s; + const page = sanitizePageNumber(paramsPage); + + return ( + <> + + +
+
+
+
+ +
+ +
+
+
+
+ + }> + + +
+ + + + ); +} + +function Loading() { + return ( +
+
+ + + +
+
+ ); +} diff --git a/src/app/globals.css b/src/app/globals.css index 5e849e2..861b538 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -59,6 +59,10 @@ body { .ext-btn-shadow-sm-primary4 { @apply bg-extColorPrimary4 text-white hover:text-white hover:bg-extColorPrimary6 transition-colors; } + + .ext-btn-shadow-sm-primary8 { + @apply bg-extColorPrimary8 text-white hover:text-white hover:bg-extColorPrimary6 transition-colors; + } } .bg-gradient { diff --git a/src/components/Blogs/Blog.tsx b/src/components/Blogs/Blog.tsx index ff63cea..e7f36cb 100644 --- a/src/components/Blogs/Blog.tsx +++ b/src/components/Blogs/Blog.tsx @@ -5,7 +5,7 @@ import { fetchBlog } from "@/services/payload/blog"; import { sanitizeBlogContentIntoStringPreview } from "@/utils/sanitize"; export default async function Blog() { - const data = await fetchBlog(undefined); + const data = await fetchBlog(); if (!data?.totalDocs) return <>; return ( diff --git a/src/components/Blogs/BlogCardItem.tsx b/src/components/Blogs/BlogCardItem.tsx index 9ff7edf..d9faa0b 100644 --- a/src/components/Blogs/BlogCardItem.tsx +++ b/src/components/Blogs/BlogCardItem.tsx @@ -31,7 +31,7 @@ export function BlogCardItem({ data }: BlogCardItemProps) { {data.title}
- + Continue Reading
diff --git a/src/components/Blogs/Blogs.tsx b/src/components/Blogs/Blogs.tsx index 91dab1b..e92fdb9 100644 --- a/src/components/Blogs/Blogs.tsx +++ b/src/components/Blogs/Blogs.tsx @@ -4,12 +4,13 @@ import { BlogCardItem } from "./BlogCardItem"; import { sanitizeBlogContentIntoStringPreview } from "@/utils/sanitize"; export interface BlogsProps { + preset?: "blogs" | "categories"; page: number; search?: string; } -export default async function Blogs({ page, search }: BlogsProps) { - const data = await fetchBlog(page, search); +export default async function Blogs({ page, search, preset = "blogs" }: BlogsProps) { + const data = await fetchBlog({ page, search }); if (!data?.totalDocs) return <>; @@ -41,6 +42,7 @@ export default async function Blogs({ page, search }: BlogsProps) { hasNextPage={data.hasNextPage} hasPreviousPage={data.hasPrevPage} totalPages={data.totalPages} + usePathParams={preset === "blogs" ? false : true} /> )} diff --git a/src/components/Pagination.tsx b/src/components/Pagination.tsx index 5264712..08f23b4 100644 --- a/src/components/Pagination.tsx +++ b/src/components/Pagination.tsx @@ -7,9 +7,16 @@ interface PaginationProps { hasPreviousPage: boolean; hasNextPage: boolean; totalPages: number; + usePathParams?: boolean; } -export default function Pagination({ page, hasPreviousPage, hasNextPage, totalPages }: PaginationProps) { +export default function Pagination({ + page, + hasPreviousPage, + hasNextPage, + totalPages, + usePathParams = false, +}: PaginationProps) { const activePage = page; const pathName = usePathname(); @@ -17,11 +24,16 @@ export default function Pagination({ page, hasPreviousPage, hasNextPage, totalPa const handlePageChange = (page: string | number) => { if (typeof page === "string") return; if (typeof window === "undefined") return; - const url = new URL(window.location.href); const searchParams = new URLSearchParams(url.search); - searchParams.set("page", `${page}`); - window.location.href = `${pathName}/?${searchParams}`; + + if (usePathParams) { + searchParams.set("page", `${page}`); + window.location.href = `${pathName}/page/${page}/?${searchParams}`; + } else { + searchParams.set("page", `${page}`); + window.location.href = `${pathName}/?${searchParams}`; + } }; const getPageNumbers = () => { diff --git a/src/services/payload/blog.ts b/src/services/payload/blog.ts index dfb1d37..efce41e 100644 --- a/src/services/payload/blog.ts +++ b/src/services/payload/blog.ts @@ -1,21 +1,34 @@ import payloadConfig from "@/payload.config"; import { formatDate } from "@/utils/datetime"; -import { getPayload } from "payload"; +import { getPayload, Where } from "payload"; -export async function fetchBlog(page: number | undefined, search: string = "") { +type FetchBlogParams = { + page?: number; + search?: string; + categorySlug?: string; +}; + +export async function fetchBlog({ page, search = "", categorySlug = "" }: FetchBlogParams = {}) { const payload = await getPayload({ config: payloadConfig }); + + const queryCondition: Where = {}; + if (!!search) { + queryCondition["title"] = { + contains: search, + }; + } + if (!!categorySlug) { + queryCondition["categories"] = { + equals: 9, + }; + } + const blogDataQuery = await payload.find({ collection: "blogs", page, pagination: true, - limit: 6, - where: !search - ? undefined - : { - title: { - contains: search, - }, - }, + limit: 9, + where: queryCondition, }); const formattedData = blogDataQuery.docs.map((item) => {