fix: testimonials from dynamic pages #4

Merged
RizqiSyahrendra merged 1 commits from dev into main 2025-02-26 18:18:23 +00:00
10 changed files with 47 additions and 205 deletions
Showing only changes of commit ae24819ce2 - Show all commits

View File

@ -9,6 +9,7 @@
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next lint", "lint": "next lint",
"payload": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload",
"payload:generate:types": "payload generate:types", "payload:generate:types": "payload generate:types",
"tsc": "tsc" "tsc": "tsc"
}, },

View File

@ -16,13 +16,13 @@ export default function NotFound() {
<div className="row"> <div className="row">
<div className="col-sm-10 offset-sm-1 col-md-8 offset-md-2 col-lg-6 offset-lg-3"> <div className="col-sm-10 offset-sm-1 col-md-8 offset-md-2 col-lg-6 offset-lg-3">
<div className="hs-wrap"> <div className="hs-wrap">
<div className="wow fadeInUp" data-wow-delay=".1s"> <div>
<h1 className="hs-title-12 mb-40 mb-sm-30">404</h1> <h1 className="hs-title-12 mb-40 mb-sm-30">404</h1>
</div> </div>
<div className="mb-40 mb-sm-30 wow fadeInUp" data-wow-delay=".2s"> <div className="mb-40 mb-sm-30">
<h2 className="section-descr mb-20">The page you were looking for could not be found.</h2> <h2 className="section-descr mb-20">The page you were looking for could not be found.</h2>
</div> </div>
<div className="local-scroll wow fadeInUp" data-wow-delay=".3s"> <div className="local-scroll">
<Link href={`/`} className="btn btn-mod btn-w btn-round btn-medium btn-hover-anim"> <Link href={`/`} className="btn btn-mod btn-w btn-round btn-medium btn-hover-anim">
<i className="mi-arrow-left align-center mr-5" /> <i className="mi-arrow-left align-center mr-5" />
<span>Back To Home Page</span> <span>Back To Home Page</span>

View File

@ -1,38 +0,0 @@
import { BeforeFooterBlock } from "@/components/Blocks/BeforeFooter";
import { GoogleReviewsBlock } from "@/components/Blocks/GoogleReviews";
import { GoogleReviewsSkeleton } from "@/components/Blocks/GoogleReviews/GoogleReviews";
import Image from "next/image";
import { Suspense } from "react";
export const metadata = {
title: "Testimonials - Cochise Oncology",
description: "Testimonials - Cochise Oncology",
};
export default async function TestimonialsPage() {
return (
<>
<section className="page-section bg-dark-1 bg-gradient-gray-dark-1 light-content bg-scroll overflow-hidden">
{/* <!-- Background Shape --> */}
<div className="absolute top-0 left-0 w-full h-full opacity-20">
<Image src="/assets/images/hero-default.webp" width="0" height="0" sizes="100vw" className="w-full" 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">Testimonials</h1>
</div>
</div>
</div>
</section>
<section className="page-section scrollSpysection" id="testimonials">
<Suspense fallback={<GoogleReviewsSkeleton />}>
<GoogleReviewsBlock />
</Suspense>
</section>
<BeforeFooterBlock />
</>
);
}

View File

@ -0,0 +1,7 @@
import { Block } from "payload";
export const GoogleReviewBlock: Block = {
slug: "googleReviewBlock",
labels: { plural: "Google Reviews", singular: "Google Reviews" },
fields: [],
};

View File

@ -1,6 +1,7 @@
import { BeforeFooterBlock } from "@/blocks/BeforeFooter"; import { BeforeFooterBlock } from "@/blocks/BeforeFooter";
import { BoxMenuGridBlock } from "@/blocks/BoxMenuGrid"; import { BoxMenuGridBlock } from "@/blocks/BoxMenuGrid";
import { ContentBlock } from "@/blocks/Content"; import { ContentBlock } from "@/blocks/Content";
import { GoogleReviewBlock } from "@/blocks/GoogleReview";
import { HorizontalImageContentBlock } from "@/blocks/HorizontalImageContent"; import { HorizontalImageContentBlock } from "@/blocks/HorizontalImageContent";
import { ImageSliderBlock } from "@/blocks/ImageSlider"; import { ImageSliderBlock } from "@/blocks/ImageSlider";
import { OurTeamBlock } from "@/blocks/OurTeam"; import { OurTeamBlock } from "@/blocks/OurTeam";
@ -45,6 +46,7 @@ export const Pages: CollectionConfig = {
HorizontalImageContentBlock, HorizontalImageContentBlock,
ImageSliderBlock, ImageSliderBlock,
BoxMenuGridBlock, BoxMenuGridBlock,
GoogleReviewBlock,
], ],
}, },
{ {

View File

@ -1,51 +1,6 @@
import { fetchGoogleReviews } from "@/services/payload/google-reviews"; import { fetchGoogleReviews } from "@/services/payload/google-reviews";
import { GoogleReviewProps, GoogleReviews } from "./GoogleReviews"; import { GoogleReviewProps, GoogleReviews } from "./GoogleReviews";
// const data: CardStarRatingProps["data"][] = [
// {
// star: 5,
// description:
// "Today i did my cat scan , and met Raymond, he radiates hope and good will, i then met Larry who showed me the hospitality suite, i was overwhelmed by thier kindness, every one i have met so far has been truly amazing.while at physical therapy the doc said i had made a wise",
// },
// {
// star: 5,
// description: "Great and caring service. Completely satisfied.",
// },
// {
// star: 5,
// description: "Sincere and caring attitude...very professional and inspires confidence.",
// },
// {
// star: 5,
// description:
// "I've been going to cochise oncology for many years and everyone is always professional and take the time to explain everything",
// },
// {
// star: 5,
// description: "One fine person\n Very concerning. Glad to see her",
// },
// {
// star: 5,
// description:
// "Barbara was very professional and friendly. She shared all info with me and gave me a copy of my lab results.",
// },
// {
// star: 5,
// description:
// "Barbara is great! She listens and ask questions on other issues outside her area just to be sure youre well taken care of.",
// },
// {
// star: 5,
// description:
// "Today, at Cochise Oncology, I had an appointment with Dr. Reid Culton. He explained in great detail from the medical chart of the blood work and listen to my concerns. Dr. Reid Culton also answered my questions in great detail. Thank you.",
// },
// {
// star: 5,
// description:
// "I absolutely love the people that work at this place. From the front desk to radiation room. Everyone is loving and caring.",
// },
// ];
export async function GoogleReviewsBlock() { export async function GoogleReviewsBlock() {
const data = await fetchGoogleReviews(); const data = await fetchGoogleReviews();
if (!data?.id) return <></>; if (!data?.id) return <></>;

View File

@ -8,7 +8,7 @@ export interface HorizontalImageContentBlockProps {
export function HorizontalImageContentBlock({ img, content }: HorizontalImageContentBlockProps) { export function HorizontalImageContentBlock({ img, content }: HorizontalImageContentBlockProps) {
return ( return (
<div className="container mb-10"> <div className="container">
<div className="grid grid-cols-1 md:grid-cols-2 gap-3 md:gap-5"> <div className="grid grid-cols-1 md:grid-cols-2 gap-3 md:gap-5">
<div> <div>
<Image src={img.url} width={0} height={0} sizes="100vw" className="w-full h-auto" alt={img.alt} /> <Image src={img.url} width={0} height={0} sizes="100vw" className="w-full h-auto" alt={img.alt} />

View File

@ -1,4 +1,4 @@
import React, { Fragment } from "react"; import React, { Fragment, Suspense } from "react";
import type { Page } from "@/payload-types"; import type { Page } from "@/payload-types";
import { ContentBlock } from "./Content"; import { ContentBlock } from "./Content";
@ -7,6 +7,8 @@ import { OurTeamBlock } from "./OurTeam";
import { HorizontalImageContentBlock } from "./HorizontalImageContent"; import { HorizontalImageContentBlock } from "./HorizontalImageContent";
import { ImageSliderBlock } from "./ImageSlider"; import { ImageSliderBlock } from "./ImageSlider";
import { BoxMenuGridBlock } from "./BoxMenuGrid"; import { BoxMenuGridBlock } from "./BoxMenuGrid";
import { GoogleReviewsBlock } from "./GoogleReviews";
import { GoogleReviewsSkeleton } from "./GoogleReviews/GoogleReviews";
const blockComponents = { const blockComponents = {
contentBlock: ContentBlock, contentBlock: ContentBlock,
@ -15,6 +17,7 @@ const blockComponents = {
horizontalImageContentBlock: HorizontalImageContentBlock, horizontalImageContentBlock: HorizontalImageContentBlock,
imageSliderBlock: ImageSliderBlock, imageSliderBlock: ImageSliderBlock,
boxMenuGridBlock: BoxMenuGridBlock, boxMenuGridBlock: BoxMenuGridBlock,
googleReviewBlock: GoogleReviewsBlock,
}; };
export const RenderBlocks: React.FC<{ export const RenderBlocks: React.FC<{
@ -32,10 +35,26 @@ export const RenderBlocks: React.FC<{
if (blockType && blockType in blockComponents) { if (blockType && blockType in blockComponents) {
const Block = blockComponents[blockType]; const Block = blockComponents[blockType];
if (!Block) return null;
if (Block) { if (blockType === "googleReviewBlock") {
return (
<div className="my-16" key={index}>
<Suspense fallback={<GoogleReviewsSkeleton />}>
<GoogleReviewsBlock />
</Suspense>
</div>
);
} else if (blockType === "beforeFooterBlock") {
return ( return (
<div className="mt-16" key={index}> <div className="mt-16" key={index}>
{/* @ts-ignore */}
<BeforeFooterBlock {...block} />
</div>
);
} else {
return (
<div className="my-16" key={index}>
{/* @ts-ignore */} {/* @ts-ignore */}
<Block {...block} disableInnerContainer /> <Block {...block} disableInnerContainer />
</div> </div>

View File

@ -1,115 +0,0 @@
"use client";
import BrandsDark from "./BrandsDark";
import { numberItems4 } from "@/data/facts";
import { testimonials5 } from "@/data/testimonials";
import { useEffect, useRef } from "react";
import Image from "next/image";
export default function TestimonialsDark() {
const isotopContainer = useRef<any | null>(null);
const initIsotop = async () => {
const Isotope = (await import("isotope-layout")).default;
const imagesloaded = (await import("imagesloaded")).default;
// Initialize Isotope in the mounted hook
const isotope = new Isotope(isotopContainer.current, {
itemSelector: ".col-md-6",
layoutMode: "masonry", // or 'fitRows', depending on your layout needs
});
imagesloaded(isotopContainer.current).on(
"progress",
function () {
// Trigger Isotope layout
isotope.layout();
}
);
};
useEffect(() => {
/////////////////////////////////////////////////////
// Magnate Animation
initIsotop();
}, []);
return (
<div className="container position-relative">
<div className="row">
{/* Section Text */}
<div className="col-lg-5 col-xl-5 d-flex align-items-center mb-md-60 mb-sm-40">
<div className="w-100">
<h2 className="section-caption-slick mb-30 mb-sm-20">
Testimonials
</h2>
<h3 className="section-title mb-30">
We&apos;re trusted by leading companies.
</h3>
<p className="section-descr mb-50 mb-sm-30">
A static website stores a unique file for every page of a static
website. Each time that page is requested, the same content is
returned.
</p>
{/* Numbers */}
<div className="row mt-sm-n10">
{numberItems4.map((item: any, index: number) => (
<div key={index} className="col-md-6 mt-sm-10">
<div className="number-3-title">{item.title}</div>
<div className="number-3-descr">{item.description}</div>
</div>
))}
</div>
{/* End Numbers */}
</div>
</div>
{/* End Section Text */}
{/* Testimonials Grid */}
<div className="col-lg-7 col-xl-6 offset-xl-1 d-flex align-items-center">
<div className="w-100 position-relative">
<div
ref={isotopContainer}
className="row masonry mb-n30 wow fadeInUp"
>
{/* Testimonials Item */}
{testimonials5.map((testimonial: any, index: number) => (
<div
key={index}
className={`col-md-6 mb-30 ${!index ? "mt-50 mt-sm-0" : ""} `}
>
<div className="testimonials-4-item">
<div className="testimonials-4-icon">
<i className="icon-quotation-mark" />
</div>
<blockquote className="testimonials-4-text">
<p className="mb-0">{testimonial.text}</p>
<footer className="testimonials-4-author mt-30 clearfix">
<div className="testimonials-4-author-img float-start">
<Image
width={44}
height={44}
src={testimonial.imgSrc}
alt={testimonial.altText}
/>
</div>
<div className="overflow-hidden">
{testimonial.author}
<div className="small">{testimonial.position}</div>
</div>
</footer>
</blockquote>
</div>
</div>
))}
{/* End Testimonials Item */}
</div>
</div>
</div>
{/* Testimonials Grid */}
</div>
{/* Logotypes */}
<div className="page-section pb-0 text-center">
<h3 className="section-title-tiny">Trusted by Leading Companies</h3>
<BrandsDark />
</div>
{/* End Logotypes */}
</div>
);
}

View File

@ -262,6 +262,11 @@ export interface Page {
blockName?: string | null; blockName?: string | null;
blockType: 'boxMenuGridBlock'; blockType: 'boxMenuGridBlock';
} }
| {
id?: string | null;
blockName?: string | null;
blockType: 'googleReviewBlock';
}
)[] )[]
| null; | null;
meta?: { meta?: {
@ -678,6 +683,12 @@ export interface PagesSelect<T extends boolean = true> {
id?: T; id?: T;
blockName?: T; blockName?: T;
}; };
googleReviewBlock?:
| T
| {
id?: T;
blockName?: T;
};
}; };
meta?: meta?:
| T | T