wwwlayermeshusa/src/blocks/FDTestimonialBlock/Component.tsx

154 lines
5.8 KiB
TypeScript

import React from 'react'
import type { FDTestimonialBlock as FDTestimonialBlockProps, Media } from '@/payload-types'
import { FDImage } from '@/components/FDImage'
const bgMap: Record<string, {
section: string; card: string
quote: string; meta: string; name: string; accent: string
}> = {
gray: {
section: 'bg-fd-gray-light dark:bg-fd-navy',
card: 'bg-white dark:bg-white/10',
quote: 'text-fd-navy dark:text-white',
meta: 'text-fd-navy/60 dark:text-white/60',
name: 'text-fd-navy dark:text-white',
accent: 'text-fd-navy dark:text-fd-yellow',
},
white: {
section: 'bg-white dark:bg-fd-navy',
card: 'bg-fd-gray-light dark:bg-white/10',
quote: 'text-fd-navy dark:text-white',
meta: 'text-fd-navy/60 dark:text-white/60',
name: 'text-fd-navy dark:text-white',
accent: 'text-fd-navy dark:text-fd-yellow',
},
navy: {
section: 'bg-fd-navy',
card: 'bg-white/10',
quote: 'text-white',
meta: 'text-white/60',
name: 'text-white',
accent: 'text-fd-yellow',
},
}
const cardRadius = 'rounded-[32px] md:rounded-[50px] lg:rounded-[70px]'
const Avatar: React.FC<{ media: Media | undefined; name: string; size: number }> = ({ media, name, size }) => {
if (!media?.url) return null
return (
<div
className="rounded-full overflow-hidden flex-shrink-0"
style={{ width: size, height: size }}
>
<FDImage
media={media}
size="thumbnail"
className="w-full h-full object-cover"
sizes={`${size}px`}
fallbackAlt={name}
/>
</div>
)
}
export const FDTestimonialBlockComponent: React.FC<FDTestimonialBlockProps> = ({
heading,
testimonials,
layout = 'grid',
sectionBackground = 'gray',
anchorId,
}) => {
const theme = bgMap[sectionBackground ?? 'gray'] || bgMap.gray
const isFeatured = layout === 'featured'
return (
<section id={anchorId || undefined} className={`w-full py-16 md:py-20 lg:py-[99px] ${theme.section}`}>
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
{heading && (
<h2 className={`font-joey-heavy text-fd-h1 mb-10 md:mb-14 ${theme.accent}`}>
{heading}
</h2>
)}
{isFeatured && testimonials && testimonials.length > 0 ? (
<div className="flex flex-col gap-6">
{/* First testimonial — large */}
{(() => {
const t = testimonials[0]
const avatar = t.avatar as Media | undefined
return (
<div className={`${theme.card} ${cardRadius} px-8 md:px-16 py-10 md:py-16 flex flex-col gap-8`}>
<p className={`font-joey-medium text-xl md:text-2xl lg:text-3xl leading-relaxed ${theme.quote}`}>
&ldquo;{t.quote}&rdquo;
</p>
<div className="flex items-center gap-4">
<Avatar media={avatar} name={t.authorName} size={56} />
<div>
<p className={`font-joey-bold text-lg ${theme.name}`}>{t.authorName}</p>
<p className={`font-joey text-sm ${theme.meta}`}>
{t.authorRole}{t.authorRole && t.authorCompany ? ' · ' : ''}{t.authorCompany}
</p>
</div>
</div>
</div>
)
})()}
{testimonials.length > 1 && (
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{testimonials.slice(1).map((t, i) => {
const avatar = t.avatar as Media | undefined
return (
<div key={i} className={`${theme.card} ${cardRadius} px-8 md:px-12 py-10 md:py-12 flex flex-col gap-6`}>
<p className={`font-joey-medium text-lg md:text-xl leading-relaxed ${theme.quote}`}>
&ldquo;{t.quote}&rdquo;
</p>
<div className="flex items-center gap-3">
<Avatar media={avatar} name={t.authorName} size={40} />
<div>
<p className={`font-joey-bold text-base ${theme.name}`}>{t.authorName}</p>
<p className={`font-joey text-xs ${theme.meta}`}>
{t.authorRole}{t.authorRole && t.authorCompany ? ' · ' : ''}{t.authorCompany}
</p>
</div>
</div>
</div>
)
})}
</div>
)}
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 min-[820px]:grid-cols-3 gap-6">
{testimonials?.map((t, i) => {
const avatar = t.avatar as Media | undefined
return (
<div key={i} className={`${theme.card} ${cardRadius} px-8 md:px-10 py-10 md:py-12 flex flex-col gap-6`}>
<span className={`font-joey-heavy text-5xl leading-none ${theme.accent} opacity-30`}>
&ldquo;
</span>
<p className={`font-joey-medium text-lg leading-relaxed -mt-4 ${theme.quote}`}>
{t.quote}
</p>
<div className="flex items-center gap-3 mt-auto">
<Avatar media={avatar} name={t.authorName} size={40} />
<div>
<p className={`font-joey-bold text-base ${theme.name}`}>{t.authorName}</p>
<p className={`font-joey text-sm ${theme.meta}`}>
{t.authorRole}{t.authorRole && t.authorCompany ? ' · ' : ''}{t.authorCompany}
</p>
</div>
</div>
</div>
)
})}
</div>
)}
</div>
</section>
)
}