143 lines
6.7 KiB
TypeScript
143 lines
6.7 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; company: string }> = {
|
|
gray: { section: 'bg-[#e5e5e5]', card: 'bg-white', quote: 'text-fd-navy', meta: 'text-fd-navy/60', name: 'text-fd-navy', company: 'text-fd-navy/50' },
|
|
white: { section: 'bg-white', card: 'bg-[#e5e5e5]', quote: 'text-fd-navy', meta: 'text-fd-navy/60', name: 'text-fd-navy', company: 'text-fd-navy/50' },
|
|
navy: { section: 'bg-fd-navy', card: 'bg-white/10', quote: 'text-white', meta: 'text-white/60', name: 'text-white', company: 'text-white/50' },
|
|
}
|
|
|
|
export const FDTestimonialBlockComponent: React.FC<FDTestimonialBlockProps> = ({
|
|
heading,
|
|
testimonials,
|
|
layout = 'grid',
|
|
sectionBackground = 'gray',
|
|
}) => {
|
|
const theme = bgMap[sectionBackground] || bgMap.gray
|
|
const isFeatured = layout === 'featured'
|
|
|
|
return (
|
|
<section 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-3xl md:text-4xl lg:text-5xl leading-tight mb-10 md:mb-14 ${sectionBackground === 'navy' ? 'text-fd-yellow' : 'text-fd-navy'}`}>
|
|
{heading}
|
|
</h2>
|
|
)}
|
|
|
|
{isFeatured && testimonials && testimonials.length > 0 ? (
|
|
// ── Featured layout: first testimonial large, rest below ──────
|
|
<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} rounded-[70px] px-10 md:px-16 py-12 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}`}>
|
|
“{t.quote}”
|
|
</p>
|
|
<div className="flex items-center gap-4">
|
|
{avatar?.url && (
|
|
<div className="w-14 h-14 rounded-full overflow-hidden flex-shrink-0">
|
|
<FDImage
|
|
src={avatar.url}
|
|
alt={avatar.alt || t.authorName}
|
|
width={56}
|
|
height={56}
|
|
className="w-full h-full object-cover"
|
|
/>
|
|
</div>
|
|
)}
|
|
<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>
|
|
)
|
|
})()}
|
|
|
|
{/* Remaining testimonials — smaller grid */}
|
|
{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} rounded-[70px] 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}`}>
|
|
“{t.quote}”
|
|
</p>
|
|
<div className="flex items-center gap-3">
|
|
{avatar?.url && (
|
|
<div className="w-10 h-10 rounded-full overflow-hidden flex-shrink-0">
|
|
<FDImage
|
|
src={avatar.url}
|
|
alt={avatar.alt || t.authorName}
|
|
width={40}
|
|
height={40}
|
|
className="w-full h-full object-cover"
|
|
/>
|
|
</div>
|
|
)}
|
|
<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>
|
|
) : (
|
|
// ── Grid layout ───────────────────────────────────────────────
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
{testimonials?.map((t, i) => {
|
|
const avatar = t.avatar as Media | undefined
|
|
return (
|
|
<div key={i} className={`${theme.card} rounded-[70px] px-8 md:px-10 py-10 md:py-12 flex flex-col gap-6`}>
|
|
{/* Quote mark */}
|
|
<span className={`font-joey-heavy text-5xl leading-none ${sectionBackground === 'navy' ? 'text-fd-yellow' : 'text-fd-navy'} opacity-30`}>
|
|
“
|
|
</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?.url && (
|
|
<div className="w-10 h-10 rounded-full overflow-hidden flex-shrink-0">
|
|
<FDImage
|
|
src={avatar.url}
|
|
alt={avatar.alt || t.authorName}
|
|
width={40}
|
|
height={40}
|
|
className="w-full h-full object-cover"
|
|
/>
|
|
</div>
|
|
)}
|
|
<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>
|
|
)
|
|
}
|