diff --git a/src/app/(main)/blog/[slug]/loading.tsx b/src/app/(main)/blog/[slug]/loading.tsx new file mode 100644 index 0000000..779bae8 --- /dev/null +++ b/src/app/(main)/blog/[slug]/loading.tsx @@ -0,0 +1,5 @@ +import LoaderFixed from "@/components/loaders/LoaderFixed"; + +export default function Loading() { + return ; +} diff --git a/src/app/(main)/blog/[slug]/page.tsx b/src/app/(main)/blog/[slug]/page.tsx index d4f4ad6..e81e588 100644 --- a/src/app/(main)/blog/[slug]/page.tsx +++ b/src/app/(main)/blog/[slug]/page.tsx @@ -1,7 +1,10 @@ import HeroImage from "@/components/HeroImage"; +import { fetchBlogDetail } from "@/services/payload/blog"; import { getDefaultMetadata } from "@/utils/metadata"; +import { RichText } from "@payloadcms/richtext-lexical/react"; import { Metadata } from "next"; import Image from "next/image"; +import { notFound } from "next/navigation"; const metaDesc = "Explore the latest insights, news, and resources on the Dynamic Realty blog. Read our articles today."; @@ -14,7 +17,12 @@ export async function generateMetadata(): Promise { return metadata; } -export default function BlogDetail() { +export default async function BlogDetail(props: { params: Promise<{ slug: string }> }) { + const params = await props.params; + const blog = await fetchBlogDetail(params.slug); + + if (!blog) return notFound(); + return ( <> @@ -25,10 +33,7 @@ export default function BlogDetail() {
-

- Showcasing a warm, traditional-style exterior and the highest caliber of contemporary European - finishes throughout, towering glass doors open to grand-scale living spaces. -

+
@@ -36,7 +41,7 @@ export default function BlogDetail() {
@@ -116,22 +121,18 @@ export default function BlogDetail() {
-
+
-
- +
diff --git a/src/app/(main)/blog/page.tsx b/src/app/(main)/blog/page.tsx index f1d6f75..8abc1b9 100644 --- a/src/app/(main)/blog/page.tsx +++ b/src/app/(main)/blog/page.tsx @@ -14,8 +14,8 @@ export async function generateMetadata(): Promise { return metadata; } -export default async function Blog({ searchParams }: { searchParams?: Promise<{ s?: string }> }) { - const params = await searchParams; +export default async function Blog(props: { searchParams?: Promise<{ s?: string }> }) { + const searchParams = await props?.searchParams; return ( <> @@ -32,14 +32,14 @@ export default async function Blog({ searchParams }: { searchParams?: Promise<{ type="text" name="s" autoComplete="off" - defaultValue={params?.s} + defaultValue={searchParams?.s} />
- +
diff --git a/src/app/(main)/globals.css b/src/app/(main)/globals.css index b45db09..1f6a236 100644 --- a/src/app/(main)/globals.css +++ b/src/app/(main)/globals.css @@ -32,6 +32,7 @@ --color-colorContactForm: var(--color-colorExt50); --color-colorText1: var(--color-colorExt10); --color-colorText2: var(--color-colorExt20); + --color-colorLoaderBackground: var(--color-colorExt20); } @layer components { diff --git a/src/components/blogs/CardBlog.tsx b/src/components/blogs/CardBlog.tsx index 6d8e299..e7730ce 100644 --- a/src/components/blogs/CardBlog.tsx +++ b/src/components/blogs/CardBlog.tsx @@ -7,11 +7,13 @@ type CardBlogProps = { }; export default function CardBlog({ data }: CardBlogProps) { + const linkDetail = `/blog/${data.slug}`; + return (
- + {data.img?.alt
@@ -27,7 +29,7 @@ export default function CardBlog({ data }: CardBlogProps) {
- {data.posted_at} + {data.posted_at}
diff --git a/src/components/blogs/ListOfBlog.tsx b/src/components/blogs/ListOfBlog.tsx index f979e1d..12a2da8 100644 --- a/src/components/blogs/ListOfBlog.tsx +++ b/src/components/blogs/ListOfBlog.tsx @@ -1,6 +1,6 @@ "use client"; -import Loader from "@/components/Loader"; +import Loader from "@/components/loaders/Loader"; import { useBlogQuery } from "@/services/hooks/blog"; import { useEffect, useRef } from "react"; import CardBlog from "./CardBlog"; diff --git a/src/components/Loader.tsx b/src/components/loaders/Loader.tsx similarity index 100% rename from src/components/Loader.tsx rename to src/components/loaders/Loader.tsx diff --git a/src/components/loaders/LoaderFixed.tsx b/src/components/loaders/LoaderFixed.tsx new file mode 100644 index 0000000..6d3911e --- /dev/null +++ b/src/components/loaders/LoaderFixed.tsx @@ -0,0 +1,9 @@ +import Loader from "./Loader"; + +export default function LoaderFixed() { + return ( +
+ +
+ ); +} diff --git a/src/services/payload/blog.ts b/src/services/payload/blog.ts index bd4696d..77ce6e4 100644 --- a/src/services/payload/blog.ts +++ b/src/services/payload/blog.ts @@ -1,7 +1,9 @@ import payloadConfig from "@/payload.config"; +import { BlogData } from "@/schema/blog"; import { FetchBlogParams } from "@/schema/services/blog"; import { formatDate } from "@/utils/datetime"; import { getRandomNumber } from "@/utils/general"; +import { sanitizeBlogContentIntoStringPreview } from "@/utils/sanitize"; import { getPayload, Where } from "payload"; export async function fetchBlog({ page, search = "", categoryId, tagId }: FetchBlogParams = {}) { @@ -71,11 +73,13 @@ export async function fetchBlogSuggestion() { limit: limitPerPage, }); - 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/utils/datetime.ts b/src/utils/datetime.ts index f48879e..a7599ca 100644 --- a/src/utils/datetime.ts +++ b/src/utils/datetime.ts @@ -1,5 +1,5 @@ import dayjs from "dayjs"; -export function formatDate(iso: string, format: string = "MMM, D YYYY") { +export function formatDate(iso: string, format: string = "MMMM DD, YYYY") { return dayjs(iso).format(format); }