fix: blog and contact pages and components suspense

This commit is contained in:
RizqiSyahrendra 2025-02-05 22:17:43 +07:00
parent edde697510
commit 5762712c49
8 changed files with 153 additions and 161 deletions

View File

@ -1,7 +1,8 @@
import BlogDetail, { BlogDetailContentSkeleton } from "@/components/Blogs/BlogDetail";
import { fetchBlogDetail } from "@/services/payload/blog"; import { fetchBlogDetail } from "@/services/payload/blog";
import { RichText } from "@payloadcms/richtext-lexical/react";
import { Metadata } from "next"; import { Metadata } from "next";
import Image from "next/image"; import Image from "next/image";
import { Suspense } from "react";
export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise<Metadata> { export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise<Metadata> {
const slug = (await params).slug; const slug = (await params).slug;
@ -14,7 +15,6 @@ export async function generateMetadata({ params }: { params: Promise<{ slug: str
openGraph: { openGraph: {
title: "Cochise Oncology", title: "Cochise Oncology",
description: "Cochise Oncology", description: "Cochise Oncology",
images: [""],
}, },
}; };
} }
@ -27,17 +27,24 @@ export async function generateMetadata({ params }: { params: Promise<{ slug: str
openGraph: { openGraph: {
title: title, title: title,
description: title, description: title,
images: [blog.imgUrl || ""], images: [{ url: blog.imgUrl }],
}, },
}; };
} }
export default async function SingleBlogPage({ params }: { params: Promise<{ slug: string }> }) { export default async function SingleBlogPage({ params }: { params: Promise<{ slug: string }> }) {
const slug = (await params).slug; const slug = (await params).slug;
const data = await fetchBlogDetail(slug);
if (!data) return <></>; return (
<>
<Suspense fallback={<Loading />}>
<BlogDetail slug={slug} />
</Suspense>
</>
);
}
function Loading() {
return ( return (
<> <>
<section className="page-section bg-dark-1 bg-gradient-gray-dark-1 light-content bg-scroll overflow-hidden"> <section className="page-section bg-dark-1 bg-gradient-gray-dark-1 light-content bg-scroll overflow-hidden">
@ -50,19 +57,13 @@ export default async function SingleBlogPage({ params }: { params: Promise<{ slu
<div className="container position-relative pt-sm-40 text-center"> <div className="container position-relative pt-sm-40 text-center">
<div className="row"> <div className="row">
<div className="col-md-10 offset-md-1 col-lg-8 offset-lg-2"> <div className="col-md-10 offset-md-1 col-lg-8 offset-lg-2">
<h1 className="hs-title-10 mb-10 wow fadeInUp">{data.data.title}</h1> <h1 className="hs-title-10 mb-10 wow fadeInUp">...</h1>
{/* Author, Categories, Comments */} {/* Author, Categories, Comments */}
<div className="blog-item-data mb-0 wow fadeIn" data-wow-delay="0.2s"> <div className="blog-item-data mb-0 wow fadeIn" data-wow-delay="0.2s">
<div className="d-inline-block me-3"> <div className="flex justify-center items-center">
<a href="#"> <i className="mi-clock mr-2" />
<i className="mi-clock size-16" /> <a href="#">...</a>
<span className="visually-hidden">Date:</span> {data.createdAt}
</a>
</div> </div>
{/* <div className="d-inline-block me-3">
<i className="mi-folder size-16" />
<span className="visually-hidden">Categories:</span> <a href="#">Design</a>, <a href="#">Branding</a>
</div> */}
</div> </div>
{/* End Author, Categories, Comments */} {/* End Author, Categories, Comments */}
</div> </div>
@ -70,32 +71,9 @@ export default async function SingleBlogPage({ params }: { params: Promise<{ slu
</div> </div>
</section> </section>
<> {/* Section */}
{/* Section */} <BlogDetailContentSkeleton />
<section className="page-section"> {/* End Section */}
<div className="container relative">
<div className="row">
{/* Content */}
<div className="col-md-10 offset-md-1 col-lg-8 offset-lg-2">
{/* Post */}
<div className="blog-item mb-80 mb-xs-40">
<div className="blog-item-body">
<div className="mb-40 mb-xs-30">
<Image src={data.imgUrl} alt="Image Description" width={1350} height={759} className="round" />
</div>
<div>
<RichText data={data.data.content} />
</div>
</div>
</div>
{/* End Post */}
</div>
{/* End Content */}
</div>
</div>
</section>
{/* End Section */}
</>
</> </>
); );
} }

View File

@ -1,15 +1,14 @@
import Contact from "@/components/Contacts/Contact"; import Contact from "@/components/Contacts/Contact";
import { fetchForm } from "@/services/payload/form"; import ContactForm from "@/components/Contacts/ContactForm";
import Image from "next/image"; import Image from "next/image";
import { Suspense } from "react";
export const metadata = { export const metadata = {
title: "Contact - Cochise Oncology", title: "Contact - Cochise Oncology",
description: "Contact - Cochise Oncology", description: "Contact - Cochise Oncology",
}; };
export default async function SlickContactPageDark() { export default async function ContactPage() {
const formRes = await fetchForm(1);
return ( return (
<> <>
<section <section
@ -39,7 +38,11 @@ export default async function SlickContactPageDark() {
</section> </section>
<section className="page-section scrollSpysection" id="contact"> <section className="page-section scrollSpysection" id="contact">
<Contact form={formRes} /> <Contact>
<Suspense fallback={<></>}>
<ContactForm />
</Suspense>
</Contact>
</section> </section>
</> </>
); );

View File

@ -1,74 +0,0 @@
import Contact from "@/components/Contacts/Contact";
import ContactDark from "@/components/ContactDark";
import Faq from "@/components/Faq";
import Image from "next/image";
export const metadata = {
title: "Slick Contacts || Resonance &mdash; One & Multi Page React Nextjs Creative Template",
description: "Resonance &mdash; One & Multi Page React Nextjs Creative Template",
};
const dark = false;
export default function SlickContactPage() {
return (
<>
<section className="page-section bg-gradient-gray-light-1 bg-scroll overflow-hidden" id="home">
{/* <!-- Background Shape --> */}
<div className="bg-shape-1 wow fadeIn">
<Image src="/assets/images/demo-fancy/bg-shape-1.svg" width={1443} height={844} alt="" />
</div>
{/* <!-- End Background Shape --> */}
<div className="container position-relative pt-sm-40 text-center">
<div className="row">
<div className="col-md-10 offset-md-1 col-lg-8 offset-lg-2">
<h1 className="hs-title-10 mb-10 wow fadeInUp">Contact Us</h1>
<p className="section-descr mb-0 wow fadeInUp" data-wow-delay="0.2s">
Crafting immersive digital journeys for brands.
</p>
</div>
</div>
</div>
</section>
<section className={`page-section scrollSpysection ${dark ? "bg-dark-1 light-content" : ""} `} id="contact">
{dark ? <ContactDark /> : <Contact />}
</section>
<hr className={`mt-0 mb-0 ${dark ? "white" : ""} `} />
<section className="page-section z-index-1">
<div className="container position-relative">
{/* Decorative Waves */}
<div className="position-relative">
<div
className="decoration-21 opacity-07 d-none d-lg-block"
data-rellax-y=""
data-rellax-speed="0.7"
data-rellax-percentage="0.35"
>
<Image src="/assets/images/demo-slick/decoration-4.svg" alt="" width={148} height={148} />
</div>
</div>
{/* End Decorative Waves */}
<div className="row position-relative">
<div className="col-md-6 col-lg-5 mb-md-50 mb-sm-30">
<h3 className="section-title mb-30">Frequently Asked Questions</h3>
<p className="text-gray mb-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam pulvinar vitae neque et porttitor. Integer
non dapibus diam, ac eleifend lectus lorem ipsum. In maximus ligula semper metus pellentesque mattis.
Maecenas volutpat, diam enim sagittis quam.
</p>
</div>
<div className="col-md-6 offset-lg-1 pt-10 pt-sm-0">
{/* Accordion */}
<Faq />
{/* End Accordion */}
</div>
</div>
</div>
</section>
</>
);
}

View File

@ -2,6 +2,7 @@ import { blogs9 } from "@/data/blogs";
import React from "react"; import React from "react";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
export default function Blog() { export default function Blog() {
return ( return (
<> <>
@ -10,31 +11,20 @@ export default function Blog() {
<div className="row mb-60 mb-sm-40"> <div className="row mb-60 mb-sm-40">
<div className="col-lg-8 offset-lg-2 text-center mb-md-30"> <div className="col-lg-8 offset-lg-2 text-center mb-md-30">
<h2 className="section-caption-slick mb-30 mb-sm-20">Our Blog</h2> <h2 className="section-caption-slick mb-30 mb-sm-20">Our Blog</h2>
<h3 className="section-title mb-30"> <h3 className="section-title mb-30">Check the latest news about our company in our blog.</h3>
Check the latest news about our company in our blog.
</h3>
<p className="section-descr mb-0"> <p className="section-descr mb-0">
There are three kinds of web developer specialization front-end There are three kinds of web developer specialization front-end developer, back-end developer, and
developer, back-end developer, and full-stack developer. full-stack developer.
</p> </p>
</div> </div>
<div className="col-lg-2 d-flex align-items-end"> <div className="col-lg-2 d-flex align-items-end">
<div className="local-scroll text-center text-lg-end w-100"> <div className="local-scroll text-center text-lg-end w-100">
<Link <Link href={`/slick-blog-dark`} className="link-hover-anim" data-link-animate="y">
href={`/slick-blog-dark`}
className="link-hover-anim"
data-link-animate="y"
>
<span className="link-strong link-strong-unhovered"> <span className="link-strong link-strong-unhovered">
Our blog{" "} Our blog <i className="mi-arrow-right size-24" aria-hidden="true"></i>
<i className="mi-arrow-right size-24" aria-hidden="true"></i>
</span> </span>
<span <span className="link-strong link-strong-hovered" aria-hidden="true">
className="link-strong link-strong-hovered" Our blog <i className="mi-arrow-right size-24" aria-hidden="true"></i>
aria-hidden="true"
>
Our blog{" "}
<i className="mi-arrow-right size-24" aria-hidden="true"></i>
</span> </span>
</Link> </Link>
</div> </div>
@ -44,10 +34,7 @@ export default function Blog() {
<div className="row mt-n30"> <div className="row mt-n30">
{/* Post Item */} {/* Post Item */}
{blogs9.map((elm: any, i: number) => ( {blogs9.map((elm: any, i: number) => (
<div <div key={i} className="post-prev-3 col-12 col-lg-10 offset-lg-1 col-xl-6 offset-xl-0 mt-30">
key={i}
className="post-prev-3 col-12 col-lg-10 offset-lg-1 col-xl-6 offset-xl-0 mt-30"
>
<div className="post-prev-3-container d-block d-sm-flex"> <div className="post-prev-3-container d-block d-sm-flex">
<div className="post-prev-3-img"> <div className="post-prev-3-img">
<Link href={`/slick-blog-single/${elm.id}`}> <Link href={`/slick-blog-single/${elm.id}`}>
@ -62,9 +49,7 @@ export default function Blog() {
</div> </div>
<div className="post-prev-3-intro"> <div className="post-prev-3-intro">
<h4 className="post-prev-3-title"> <h4 className="post-prev-3-title">
<Link href={`/slick-blog-single/${elm.id}`}> <Link href={`/slick-blog-single/${elm.id}`}>{elm.title}</Link>
{elm.title}
</Link>
</h4> </h4>
<div className="post-prev-3-text">{elm.intro}</div> <div className="post-prev-3-text">{elm.intro}</div>
<div className="post-prev-3-info clearfix"> <div className="post-prev-3-info clearfix">

View File

@ -59,7 +59,7 @@ export function BlogCardItem({ data }: BlogCardItemProps) {
export function BlogCardItemSkeleton() { export function BlogCardItemSkeleton() {
return ( return (
<div className="post-prev-3 col-12 col-lg-10 offset-lg-1 col-xl-6 offset-xl-0 mt-50 animate-pulse "> <div className="post-prev-3 col-12 col-lg-10 offset-lg-1 col-xl-6 offset-xl-0 mt-50 animate-pulse">
<div className="post-prev-3-container d-block d-sm-flex"> <div className="post-prev-3-container d-block d-sm-flex">
<div className="post-prev-3-img"> <div className="post-prev-3-img">
<div className="w-56 h-64 bg-gray-300 rounded-l-lg"></div> <div className="w-56 h-64 bg-gray-300 rounded-l-lg"></div>

View File

@ -0,0 +1,94 @@
import { fetchBlogDetail } from "@/services/payload/blog";
import { RichText } from "@payloadcms/richtext-lexical/react";
import Image from "next/image";
export interface BlogDetailProps {
slug: string;
}
export default async function BlogDetail({ slug }: BlogDetailProps) {
const data = await fetchBlogDetail(slug);
if (!data) return <></>;
return (
<>
<section className="page-section bg-dark-1 bg-gradient-gray-dark-1 light-content bg-scroll overflow-hidden">
{/* <!-- Background Shape --> */}
<div className="bg-shape-1 opacity-003">
<Image src="/assets/images/demo-fancy/bg-shape-1.svg" width={1443} height={844} alt="" />
</div>
{/* <!-- End Background Shape --> */}
<div className="container position-relative pt-sm-40 text-center">
<div className="row">
<div className="col-md-10 offset-md-1 col-lg-8 offset-lg-2">
<h1 className="hs-title-10 mb-10 wow fadeInUp">{data.data.title}</h1>
{/* Author, Categories, Comments */}
<div className="blog-item-data mb-0 wow fadeIn" data-wow-delay="0.2s">
<div className="flex justify-center items-center">
<i className="mi-clock mr-2" />
<a href="#">{data.createdAt}</a>
</div>
</div>
{/* End Author, Categories, Comments */}
</div>
</div>
</div>
</section>
{/* Section */}
<section className="page-section">
<div className="container relative">
<div className="row">
{/* Content */}
<div className="col-md-10 offset-md-1 col-lg-8 offset-lg-2">
{/* Post */}
<div className="blog-item mb-80 mb-xs-40">
<div className="blog-item-body">
<div className="mb-40 mb-xs-30">
<Image src={data.imgUrl} alt="Image Description" width={1350} height={759} className="round" />
</div>
<div>
<RichText data={data.data.content} />
</div>
</div>
</div>
{/* End Post */}
</div>
{/* End Content */}
</div>
</div>
</section>
{/* End Section */}
</>
);
}
export function BlogDetailContentSkeleton() {
return (
<section className="page-section animate-pulse">
<div className="container relative">
<div className="row">
{/* Content */}
<div className="col-md-10 offset-md-1 col-lg-8 offset-lg-2">
{/* Post */}
<div className="blog-item mb-80 mb-xs-40">
<div className="blog-item-body">
<div className="mb-40 mb-xs-30">
<div className="w-full h-72 bg-gray-300 rounded-lg"></div>
<div className="h-5 bg-gray-300 rounded w-full mt-3"></div>
<div className="h-5 bg-gray-300 rounded w-3/4 mt-3"></div>
<div className="h-5 bg-gray-300 rounded w-2/3 mt-3"></div>
</div>
<div></div>
</div>
</div>
{/* End Post */}
</div>
{/* End Content */}
</div>
</div>
</section>
);
}

View File

@ -1,15 +1,11 @@
"use client";
import { contactItems } from "@/data/contact"; import { contactItems } from "@/data/contact";
import React from "react"; import React, { ReactNode } from "react";
import { FormBlock } from "../Blocks/Form";
import { Form as FormType } from "@payloadcms/plugin-form-builder/types";
import { Form } from "@/payload-types";
export interface ContactProps { export interface ContactProps {
form?: FormType | Form; children?: ReactNode;
} }
export default function Contact({ form }: ContactProps) { export default function Contact({ children }: ContactProps) {
return ( return (
<div className="container position-relative"> <div className="container position-relative">
<div className="row"> <div className="row">
@ -76,14 +72,7 @@ export default function Contact({ form }: ContactProps) {
{/* End Right Column */} {/* End Right Column */}
</div> </div>
{!!form && ( {children}
<div className="box-shadow bg-white round p-4 p-sm-5 position-relative z-index-1">
<h4 className="h3 mb-40 mb-sm-30">{form?.title ?? ""}</h4>
<div>
<FormBlock enableIntro={true} form={form} />
</div>
</div>
)}
</div> </div>
); );
} }

View File

@ -0,0 +1,17 @@
import { fetchForm } from "@/services/payload/form";
import { FormBlock } from "@/components/Blocks/Form";
export default async function ContactForm() {
const form = await fetchForm(1);
if (!form) return <></>;
return (
<div className="box-shadow bg-white round p-4 p-sm-5 position-relative z-index-1">
<h4 className="h3 mb-40 mb-sm-30">{form?.title ?? ""}</h4>
<div>
<FormBlock enableIntro={true} form={form} />
</div>
</div>
);
}