From 39589e1b9acd3f794246c73c73d595710a76bede Mon Sep 17 00:00:00 2001 From: Black Hat Date: Thu, 3 Jul 2025 14:25:41 +0000 Subject: [PATCH] feat: blog home pagination and routing --- src/app/[locale]/blog/page.tsx | 40 ++++++++++++ src/components/features/blog/BlogPosts.tsx | 63 +++++++++++++++++++ src/components/features/blog/index.ts | 1 + src/lib/__generated/sdk.ts | 8 ++- src/lib/fetchpost.ts | 30 +++++++++ .../graphql/pageBlogPostCollection.graphql | 4 +- 6 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 src/app/[locale]/blog/page.tsx create mode 100644 src/components/features/blog/BlogPosts.tsx create mode 100644 src/components/features/blog/index.ts create mode 100644 src/lib/fetchpost.ts diff --git a/src/app/[locale]/blog/page.tsx b/src/app/[locale]/blog/page.tsx new file mode 100644 index 00000000..4c3b3174 --- /dev/null +++ b/src/app/[locale]/blog/page.tsx @@ -0,0 +1,40 @@ +import { BlogPosts } from '@src/components/features/blog'; +import { fetchPosts } from '@src/lib/fetchpost'; + +interface ContentFullBlogProps { + params: { locale: string }; + searchParams: { + page?: string; + preview?: string; + }; +} + +export default async function ContentFullBlog({ params, searchParams }: ContentFullBlogProps) { + const raw = searchParams?.page; + const parsedPage = parseInt(raw ?? '1', 10); + const page = isNaN(parsedPage) || parsedPage < 1 ? 1 : parsedPage; + + const preview = searchParams.preview === 'true'; + const locale = params.locale; + + const postsPerPage = 6; + const posts = await fetchPosts(page, postsPerPage, preview); + + const totalPosts = posts.totalPosts; + const totalPages = Math.ceil(totalPosts / postsPerPage); + + return ( +
+
+ +
+
+ ); +} diff --git a/src/components/features/blog/BlogPosts.tsx b/src/components/features/blog/BlogPosts.tsx new file mode 100644 index 00000000..73018bc6 --- /dev/null +++ b/src/components/features/blog/BlogPosts.tsx @@ -0,0 +1,63 @@ +'use client'; + +import { useRouter } from 'next/navigation'; + +import { ArticleTileGrid } from '@src/components/features/article'; +import { Container } from '@src/components/shared/container'; + +export const BlogPosts = ({ + posts, + currentPage, + totalPages, +}: { + posts: any[]; + totalPosts: number; + currentPage: number; + totalPages: number; + locale: string; + preview: boolean; +}) => { + const router = useRouter(); + + const handlePageChange = (page: number) => { + // Change the URL to include the new page number, which will trigger a new server-side request + router.push(`?page=${page}/#blogs`); + }; + + return ( + +
+

+ 🗞️ Blogs +

+ + +
+ + + {Array.from({ length: totalPages }).map((_, index) => ( + + ))} + + +
+
+ ); +}; diff --git a/src/components/features/blog/index.ts b/src/components/features/blog/index.ts new file mode 100644 index 00000000..5c82020b --- /dev/null +++ b/src/components/features/blog/index.ts @@ -0,0 +1 @@ +export * from './BlogPosts'; diff --git a/src/lib/__generated/sdk.ts b/src/lib/__generated/sdk.ts index 39702e1b..f62cc90e 100644 --- a/src/lib/__generated/sdk.ts +++ b/src/lib/__generated/sdk.ts @@ -1595,17 +1595,17 @@ export type PageBlogPostQuery = { __typename?: 'Query', pageBlogPostCollection?: export type PageBlogPostCollectionQueryVariables = Exact<{ locale?: InputMaybe; + skip?: InputMaybe; preview?: InputMaybe; limit?: InputMaybe; order?: InputMaybe> | InputMaybe>; where?: InputMaybe; }>; - export type PageBlogPostCollectionQuery = { __typename?: 'Query', pageBlogPostCollection?: { __typename?: 'PageBlogPostCollection', items: Array<( { __typename?: 'PageBlogPost' } & PageBlogPostFieldsFragment - ) | null> } | null }; + ) | null>, total: any } | null }; export type PageLandingFieldsFragment = { __typename: 'PageLanding', internalName?: string | null, sys: { __typename?: 'Sys', id: string, spaceId: string }, seoFields?: ( { __typename?: 'ComponentSeo' } @@ -1826,9 +1826,10 @@ ${AuthorFieldsFragmentDoc} ${RichImageFieldsFragmentDoc} ${ReferencePageBlogPostFieldsFragmentDoc}`; export const PageBlogPostCollectionDocument = gql` - query pageBlogPostCollection($locale: String, $preview: Boolean, $limit: Int, $order: [PageBlogPostOrder], $where: PageBlogPostFilter) { + query pageBlogPostCollection($locale: String, $skip: Int, $preview: Boolean, $limit: Int, $order: [PageBlogPostOrder], $where: PageBlogPostFilter) { pageBlogPostCollection( limit: $limit + skip: $skip locale: $locale preview: $preview order: $order @@ -1837,6 +1838,7 @@ export const PageBlogPostCollectionDocument = gql` items { ...PageBlogPostFields } + total } } ${PageBlogPostFieldsFragmentDoc} diff --git a/src/lib/fetchpost.ts b/src/lib/fetchpost.ts new file mode 100644 index 00000000..c20faf8e --- /dev/null +++ b/src/lib/fetchpost.ts @@ -0,0 +1,30 @@ +// lib/fetchPosts.ts + +import { PageBlogPostOrder } from './__generated/sdk'; + +import { client, previewClient } from '@src/lib/client'; // The GraphQL client for fetching data + +export const fetchPosts = async (page: number, postsPerPage: number, preview: boolean) => { + const skip = (page - 1) * postsPerPage; + const gqlClient = preview ? previewClient : client; + + try { + const data = await gqlClient.pageBlogPostCollection({ + limit: postsPerPage, + skip, + order: PageBlogPostOrder.PublishedDateDesc, + preview: false, + }); + + return { + items: data.pageBlogPostCollection?.items || [], + totalPosts: data.pageBlogPostCollection?.total || 0, + }; + } catch (error) { + console.error('Error fetching posts:', error); + return { + items: [], + totalPosts: 0, + }; + } +}; diff --git a/src/lib/graphql/pageBlogPostCollection.graphql b/src/lib/graphql/pageBlogPostCollection.graphql index 30d42617..be4fd1e9 100644 --- a/src/lib/graphql/pageBlogPostCollection.graphql +++ b/src/lib/graphql/pageBlogPostCollection.graphql @@ -2,12 +2,14 @@ query pageBlogPostCollection( $locale: String $preview: Boolean $limit: Int + $skip: Int $order: [PageBlogPostOrder] $where: PageBlogPostFilter ) { - pageBlogPostCollection(limit: $limit, locale: $locale, preview: $preview, order: $order where: $where) { + pageBlogPostCollection(limit: $limit, skip: $skip, locale: $locale, preview: $preview, order: $order where: $where) { items { ...PageBlogPostFields } + total } }