fetch sections from cms

This commit is contained in:
Zotov Ivan Yuryevich
2026-04-08 23:19:36 +03:00
parent d0ff2907cb
commit 6973e8baea
18 changed files with 518 additions and 356 deletions

View File

@@ -1,63 +1,50 @@
import { Cloud, Shield, Cpu, Database, Server, Settings } from 'lucide-react'
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'
const services = [
{
icon: Cloud,
title: 'Облачные решения',
description: 'Миграция и управление инфраструктурой на базе Яндекс.Облако и VK Cloud',
gradient: 'from-blue-50 to-cyan-50',
iconColor: 'text-blue-600',
},
{
icon: Shield,
title: 'Кибербезопасность',
description: 'Комплексная защита периметра и данных с решениями Kaspersky',
gradient: 'from-violet-50 to-purple-50',
iconColor: 'text-violet-600',
},
{
icon: Cpu,
title: 'Цифровая трансформация',
description: 'Автоматизация процессов на платформах 1С и Галактика',
gradient: 'from-emerald-50 to-teal-50',
iconColor: 'text-emerald-600',
},
{
icon: Database,
title: 'Управление данными',
description: 'Развертывание и поддержка СУБД Postgres Pro',
gradient: 'from-orange-50 to-amber-50',
iconColor: 'text-orange-600',
},
{
icon: Server,
title: 'Серверная инфраструктура',
description: 'Поставка и настройка оборудования Kraftway',
gradient: 'from-pink-50 to-rose-50',
iconColor: 'text-pink-600',
},
{
icon: Settings,
title: 'Системная интеграция',
description: 'Построение корпоративной ИТ-архитектуры на Astra Linux',
gradient: 'from-indigo-50 to-blue-50',
iconColor: 'text-indigo-600',
},
]
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
}
export function Services() {
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>
<h2 className="text-4xl lg:text-5xl text-gray-900 mb-6">Комплексные IT-решения для вашего бизнеса</h2>
<p className="text-xl text-gray-600">Полный цикл: от стратегии до технической поддержки</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">
{services.map((service, index) => {
const Icon = service.icon
{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',
@@ -67,31 +54,44 @@ export function Services() {
'animate-float-delay-5',
]
const floatClass = floatClasses[index % 6]
const slug = service.category?.slug
return (
<div
key={index}
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 ${service.gradient} flex items-center justify-center`}
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 ${service.iconColor}`} />
<Icon className={`w-10 h-10 ${iconColor}`} />
</div>
</div>
<div className="p-6">
<h3 className="text-xl text-gray-900 mb-3">{service.title}</h3>
{service.title ? <h3 className="text-xl text-gray-900 mb-3">{service.title}</h3> : null}
<p className="text-gray-600 mb-4 leading-relaxed">{service.description}</p>
{service.description ? (
<p className="text-gray-600 mb-4 leading-relaxed">{service.description}</p>
) : null}
<button className="text-blue-600 hover:text-blue-700 transition-colors inline-flex items-center gap-2">
Подробнее
<span className="transition-all">&rarr;</span>
</button>
{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>
)