diff --git a/src/app/(main)/blog/[slug]/page.tsx b/src/app/(main)/blog/[slug]/page.tsx
index 204a1f0..8287882 100644
--- a/src/app/(main)/blog/[slug]/page.tsx
+++ b/src/app/(main)/blog/[slug]/page.tsx
@@ -1,3 +1,4 @@
+import ListOfRecentBlog from "@/components/blogs/ListOfRecentBlog";
import HeroImage from "@/components/HeroImage";
import { fetchBlogDetail } from "@/services/payload/blog";
import { getDefaultMetadata } from "@/utils/metadata";
@@ -110,65 +111,31 @@ export default async function BlogDetail(props: { params: Promise<{ slug: string
Share this post
{blogQuery.isFetching &&
}
- {blogQuery.hasNext && (
+ {!blogQuery.isFetching && blogQuery.hasNext && (
diff --git a/src/components/blogs/ListOfRecentBlog.tsx b/src/components/blogs/ListOfRecentBlog.tsx
new file mode 100644
index 0000000..591c1e5
--- /dev/null
+++ b/src/components/blogs/ListOfRecentBlog.tsx
@@ -0,0 +1,48 @@
+"use client";
+
+import Loader from "@/components/loaders/Loader";
+import { useRecentBlogQuery } from "@/services/hooks/blog";
+import { useEffect } from "react";
+import CardBlog from "./CardBlog";
+
+type ListOfRecentBlogProps = {
+ currentBlogId?: number;
+};
+
+export default function ListOfRecentBlog({ currentBlogId }: ListOfRecentBlogProps) {
+ const recentBlogQuery = useRecentBlogQuery();
+
+ useEffect(() => {
+ if (!!currentBlogId) {
+ recentBlogQuery._fetch({
+ currentBlogId,
+ });
+ }
+ }, [currentBlogId]);
+
+ if (recentBlogQuery.isFetching) {
+ return (
+
+
+
+ );
+ }
+
+ if (recentBlogQuery.data.length <= 0) return <>>;
+
+ return (
+ <>
+
+
+
Recent Posts
+
+
+
+ {recentBlogQuery.data.map((blog) => (
+
+ ))}
+
+
+ >
+ );
+}
diff --git a/src/payload.config.ts b/src/payload.config.ts
index c53d1fc..83618ec 100644
--- a/src/payload.config.ts
+++ b/src/payload.config.ts
@@ -18,8 +18,6 @@ const filename = fileURLToPath(import.meta.url);
const dirname = path.dirname(filename);
export default buildConfig({
- cors: [process.env.SITE_URL || ""],
- csrf: [process.env.SITE_URL || ""],
admin: {
user: Users.slug,
importMap: {
diff --git a/src/schema/blog.ts b/src/schema/blog.ts
index 6349fc2..ea26548 100644
--- a/src/schema/blog.ts
+++ b/src/schema/blog.ts
@@ -1,7 +1,7 @@
export type BlogData = {
slug?: string | null;
title: string;
- description: string;
+ description?: string;
img?: { url: string; alt?: string };
posted_at: string;
};
diff --git a/src/schema/services/blog.ts b/src/schema/services/blog.ts
index ab91539..16e2b5d 100644
--- a/src/schema/services/blog.ts
+++ b/src/schema/services/blog.ts
@@ -4,3 +4,7 @@ export type FetchBlogParams = {
categoryId?: number;
tagId?: number;
};
+
+export type FetchRecentBlogParams = {
+ currentBlogId: number;
+};
diff --git a/src/services/hooks/blog.ts b/src/services/hooks/blog.ts
index ba9f31e..dc8a757 100644
--- a/src/services/hooks/blog.ts
+++ b/src/services/hooks/blog.ts
@@ -1,7 +1,7 @@
import { BlogData } from "@/schema/blog";
-import { FetchBlogParams } from "@/schema/services/blog";
+import { FetchBlogParams, FetchRecentBlogParams } from "@/schema/services/blog";
import { useState } from "react";
-import { fetchBlogREST } from "../rest/blog";
+import { fetchBlogREST, fetchRecentBlogREST } from "../rest/blog";
export function useBlogQuery() {
const [data, setData] = useState
([]);
@@ -14,7 +14,13 @@ export function useBlogQuery() {
setFetching(false);
if (Array.isArray(res?.formattedData)) {
- setData(res.formattedData);
+ if (!!params.page && params.page > 1) {
+ setData((currentData) => {
+ return [...currentData, ...res.formattedData];
+ });
+ } else {
+ setData(res.formattedData);
+ }
}
setHasNext(res?.hasNextPage ?? false);
}
@@ -26,3 +32,24 @@ export function useBlogQuery() {
hasNext,
};
}
+
+export function useRecentBlogQuery() {
+ const [data, setData] = useState([]);
+ const [isFetching, setFetching] = useState(false);
+
+ async function _fetch(params: FetchRecentBlogParams) {
+ setFetching(true);
+ const res = await fetchRecentBlogREST(params);
+ setFetching(false);
+
+ if (Array.isArray(res?.formattedData)) {
+ setData(res.formattedData);
+ }
+ }
+
+ return {
+ _fetch,
+ data,
+ isFetching,
+ };
+}
diff --git a/src/services/payload/blog.ts b/src/services/payload/blog.ts
index 4e57278..de75adb 100644
--- a/src/services/payload/blog.ts
+++ b/src/services/payload/blog.ts
@@ -37,11 +37,13 @@ export async function fetchBlog({ page, search = "", categoryId, tagId }: FetchB
where: queryCondition,
});
- const formattedData = blogDataQuery.docs.map((item) => {
+ const formattedData: BlogData[] = blogDataQuery.docs.map((item) => {
return {
- ...item,
- imgFormatted: typeof item.img !== "number" ? { url: item?.img?.url ?? "", alt: item.img.alt } : undefined,
- createdAtFormatted: formatDate(item.createdAt),
+ slug: item.slug,
+ title: item.title,
+ description: sanitizeBlogContentIntoStringPreview(item.content),
+ img: typeof item.img !== "number" ? { url: item?.img?.url ?? "", alt: item.img.alt } : undefined,
+ posted_at: formatDate(item.createdAt),
};
});
diff --git a/src/services/rest/blog.ts b/src/services/rest/blog.ts
index 1ea4527..19d5b76 100644
--- a/src/services/rest/blog.ts
+++ b/src/services/rest/blog.ts
@@ -1,6 +1,6 @@
import { Blog } from "@/payload-types";
import { BlogData } from "@/schema/blog";
-import { FetchBlogParams } from "@/schema/services/blog";
+import { FetchBlogParams, FetchRecentBlogParams } from "@/schema/services/blog";
import { formatDate } from "@/utils/datetime";
import { sanitizeBlogContentIntoStringPreview } from "@/utils/sanitize";
import { PaginatedDocs, Where } from "payload";
@@ -59,3 +59,43 @@ export async function fetchBlogREST({ page, search = "", categoryId, tagId }: Fe
return null;
}
}
+
+export async function fetchRecentBlogREST({ currentBlogId }: FetchRecentBlogParams) {
+ const queryCondition: Where = {
+ _status: { equals: "published" },
+ id: {
+ not_equals: currentBlogId,
+ },
+ };
+
+ const queryParams = stringify(
+ {
+ pagination: true,
+ limit: 2,
+ where: queryCondition,
+ },
+ { addQueryPrefix: true }
+ );
+
+ const blogRequest = await fetch(`/api/blogs${queryParams}`);
+
+ if (blogRequest.ok) {
+ const resData = (await blogRequest.json()) as PaginatedDocs;
+ const formattedData: BlogData[] = resData.docs.map((item) => {
+ return {
+ slug: item.slug,
+ title: item.title,
+ description: sanitizeBlogContentIntoStringPreview(item.content),
+ img: typeof item.img !== "number" ? { url: item?.img?.url ?? "", alt: item.img.alt } : undefined,
+ posted_at: formatDate(item.createdAt),
+ };
+ });
+
+ return {
+ ...resData,
+ formattedData,
+ };
+ } else {
+ return null;
+ }
+}