Files
softclick-landing/src/sections/Services.tsx
Zotov Ivan Yuryevich 6973e8baea fetch sections from cms
2026-04-08 23:19:36 +03:00

104 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { toComponent } from '../lib/cms/icon'
import { toGradient, toTextColor } from '../lib/cms/color'
import type { Enum_Componentsharedcolor_Value, Enum_Componentsharedicon_Value } from '../graphql/graphql'
import type { Maybe } from '../lib/types'
export interface ServiceCardCms {
id: string
title?: Maybe<string>
description?: Maybe<string>
icon?: Maybe<{ value?: Maybe<Enum_Componentsharedicon_Value> }>
color?: Maybe<{ value?: Maybe<Enum_Componentsharedcolor_Value> }>
category?: Maybe<{ slug: string }>
}
export interface ServicesCmsData {
title?: Maybe<string>
description?: Maybe<string>
cards?: Maybe<Array<Maybe<ServiceCardCms>>>
}
interface ServicesProps {
data?: Maybe<ServicesCmsData>
}
export function Services({ data }: ServicesProps) {
const title = data?.title ?? ''
const description = data?.description ?? ''
const cards = (data?.cards ?? []).filter((c): c is ServiceCardCms => Boolean(c))
if (!title && !description && cards.length === 0) {
return null
}
return (
<section id="services" className="py-24 bg-white">
<div className="max-w-400 mx-auto px-6 xl:px-12 2xl:px-16">
<div className="max-w-3xl mb-16">
<p className="text-sm uppercase tracking-wider text-gray-500 mb-4">Услуги</p>
{title ? <h2 className="text-4xl lg:text-5xl text-gray-900 mb-6">{title}</h2> : null}
{description ? <p className="text-xl text-gray-600">{description}</p> : null}
</div>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{cards.map((service, index) => {
const Icon = toComponent(service.icon?.value)
const gradient = toGradient(service.color?.value)
const iconColor = toTextColor(service.color?.value)
const floatClasses = [
'animate-float',
'animate-float-delay-1',
'animate-float-delay-2',
'animate-float-delay-3',
'animate-float-delay-4',
'animate-float-delay-5',
]
const floatClass = floatClasses[index % 6]
const slug = service.category?.slug
return (
<div
key={service.id}
className="group bg-white rounded-2xl border border-gray-100 hover:border-blue-200 hover:shadow-xl transition-all duration-300 overflow-hidden"
>
<div
className={`relative h-48 overflow-hidden bg-linear-to-br ${gradient} flex items-center justify-center`}
>
<div
className={`w-20 h-20 bg-white rounded-2xl flex items-center justify-center group-hover:scale-110 transition-transform duration-300 shadow-md ${floatClass}`}
>
<Icon className={`w-10 h-10 ${iconColor}`} />
</div>
</div>
<div className="p-6">
{service.title ? <h3 className="text-xl text-gray-900 mb-3">{service.title}</h3> : null}
{service.description ? (
<p className="text-gray-600 mb-4 leading-relaxed">{service.description}</p>
) : null}
{slug ? (
<a
href={`/${slug}`}
className="text-blue-600 hover:text-blue-700 transition-colors inline-flex items-center gap-2"
>
Подробнее
<span className="transition-all">&rarr;</span>
</a>
) : (
<span className="text-blue-600 inline-flex items-center gap-2">
Подробнее
<span className="transition-all">&rarr;</span>
</span>
)}
</div>
</div>
)
})}
</div>
</div>
</section>
)
}