- Fix heading/titleClass references in FDAlternateHeroBlock, FDDataTableBlock, FDLocationsGridBlock, FDPartnersLogosBlock, FDServiceChooserBlock, FDStatisticsBlock - Fix service.title in FDServiceChooserBlock nested type - Remove hero field references from [slug]/page.tsx - Fix PopupAnnouncement adminOnly import path - Add Page type import to [slug]/page.tsx
117 lines
4.2 KiB
TypeScript
117 lines
4.2 KiB
TypeScript
'use client'
|
|
import React, { useState, useRef } from 'react'
|
|
import type { FDServiceChooserBlock as Props } from '@/payload-types'
|
|
|
|
export const FDServiceChooserBlockComponent: React.FC<Props> = ({
|
|
heading,
|
|
description,
|
|
categories = [],
|
|
sectionBackground = 'gray',
|
|
}) => {
|
|
const [activeIndex, setActiveIndex] = useState(0)
|
|
const [animating, setAnimating] = useState(false)
|
|
const prevIndex = useRef(0)
|
|
|
|
const isDark = sectionBackground === 'navy'
|
|
const bgClass = isDark ? 'bg-fd-navy' : sectionBackground === 'gray' ? 'bg-fd-surface-alt' : 'bg-white'
|
|
const titleClass = isDark ? 'text-fd-yellow' : 'text-fd-navy'
|
|
const bodyClass = isDark ? 'text-white' : 'text-fd-navy'
|
|
const cardBg = isDark ? 'bg-white/10 border border-white/10' : 'bg-white border border-fd-navy/10'
|
|
|
|
const handleTabChange = (i: number) => {
|
|
if (i === activeIndex) return
|
|
setAnimating(true)
|
|
prevIndex.current = activeIndex
|
|
setTimeout(() => {
|
|
setActiveIndex(i)
|
|
setAnimating(false)
|
|
}, 200)
|
|
}
|
|
|
|
const activeCategory = (categories ?? [])[activeIndex]
|
|
|
|
return (
|
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${bgClass}`}>
|
|
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
|
|
|
<div className="text-center mb-10 md:mb-12">
|
|
{heading && (
|
|
<h2 className={`font-joey-heavy text-fd-h1 mb-4 ${titleClass}`}>
|
|
{heading}
|
|
</h2>
|
|
)}
|
|
{description && (
|
|
<p className={`font-joey text-fd-body-lg max-w-[600px] mx-auto ${bodyClass}`}>
|
|
{description}
|
|
</p>
|
|
)}
|
|
</div>
|
|
|
|
<div className="flex flex-wrap justify-center gap-2 md:gap-3 mb-10 md:mb-12">
|
|
{(categories ?? []).map((cat, i) => (
|
|
<button
|
|
key={i}
|
|
onClick={() => handleTabChange(i)}
|
|
className={`px-5 py-2 rounded-full font-joey-medium text-fd-body transition-all duration-200 border-2 ${
|
|
activeIndex === i
|
|
? 'bg-fd-yellow border-fd-yellow text-fd-navy shadow-sm'
|
|
: isDark
|
|
? 'border-white/30 text-white hover:border-fd-yellow hover:text-fd-yellow'
|
|
: 'border-fd-navy/20 text-fd-navy hover:border-fd-yellow hover:bg-fd-yellow/10'
|
|
}`}
|
|
>
|
|
{cat.label}
|
|
</button>
|
|
))}
|
|
</div>
|
|
|
|
<div
|
|
className={`transition-all duration-200 ${animating ? 'opacity-0 translate-y-2' : 'opacity-100 translate-y-0'}`}
|
|
style={{ minHeight: '200px' }}
|
|
>
|
|
{activeCategory?.intro && (
|
|
<p className={`text-center font-joey text-fd-body mb-6 opacity-70 ${bodyClass}`}>
|
|
{activeCategory.intro}
|
|
</p>
|
|
)}
|
|
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 md:gap-6">
|
|
{activeCategory?.services?.map((service, i) => (
|
|
<div
|
|
key={i}
|
|
className={`rounded-[30px] md:rounded-[40px] p-8 md:p-10 flex flex-col gap-4 ${cardBg}`}
|
|
style={{
|
|
transition: 'opacity 0.3s, transform 0.3s',
|
|
transitionDelay: `${i * 60}ms`,
|
|
opacity: animating ? 0 : 1,
|
|
transform: animating ? 'translateY(8px)' : 'translateY(0)',
|
|
}}
|
|
>
|
|
<h3 className={`font-joey-bold text-fd-h3 ${isDark ? 'text-fd-yellow' : 'text-fd-navy'}`}>
|
|
{service.title}
|
|
</h3>
|
|
{service.description && (
|
|
<p className={`font-joey text-fd-body opacity-80 flex-1 ${bodyClass}`}>
|
|
{service.description}
|
|
</p>
|
|
)}
|
|
{service.ctaText && (
|
|
<div className="mt-auto pt-2">
|
|
<a
|
|
href={service.ctaLink || '/kontakt'}
|
|
className={isDark ? 'fd-btn-secondary-dark' : 'fd-btn-secondary'}
|
|
>
|
|
{service.ctaText}
|
|
</a>
|
|
</div>
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</section>
|
|
)
|
|
}
|