fetch sections from cms
This commit is contained in:
@@ -1,85 +1,89 @@
|
||||
import { ArrowRight, Cloud, Cpu, Shield } from 'lucide-react'
|
||||
import { ArrowRight } from 'lucide-react'
|
||||
import { toComponent } from '../lib/cms/icon'
|
||||
import { toElevatedGradient, toTextColor } from '../lib/cms/color'
|
||||
import type { Enum_Componentsharedcolor_Value, Enum_Componentsharedicon_Value } from '../graphql/graphql'
|
||||
import type { Maybe } from '../lib/types'
|
||||
|
||||
const cases = [
|
||||
{
|
||||
icon: Cloud,
|
||||
category: 'Облако',
|
||||
company: 'Торговая сеть',
|
||||
title: 'Миграция в Яндекс.Облако',
|
||||
description: 'Перенос корпоративной инфраструктуры 500+ серверов с нулевым простоем',
|
||||
results: '−40% TCO',
|
||||
gradient: 'from-blue-100 to-cyan-100',
|
||||
iconBg: 'bg-white',
|
||||
iconColor: 'text-blue-600',
|
||||
},
|
||||
{
|
||||
icon: Cpu,
|
||||
category: 'Автоматизация',
|
||||
company: 'Производственный холдинг',
|
||||
title: 'Внедрение 1С:ERP',
|
||||
description: 'Автоматизация производственного и финансового учета для 15 предприятий',
|
||||
results: '+25% эффективность',
|
||||
gradient: 'from-emerald-100 to-teal-100',
|
||||
iconBg: 'bg-white',
|
||||
iconColor: 'text-emerald-600',
|
||||
},
|
||||
{
|
||||
icon: Shield,
|
||||
category: 'Безопасность',
|
||||
company: 'Финансовая группа',
|
||||
title: 'Защита периметра Kaspersky',
|
||||
description: 'Построение многоуровневой системы защиты критичной инфраструктуры',
|
||||
results: '99.9% uptime',
|
||||
gradient: 'from-violet-100 to-purple-100',
|
||||
iconBg: 'bg-white',
|
||||
iconColor: 'text-violet-600',
|
||||
},
|
||||
]
|
||||
export interface CaseCardCms {
|
||||
id: string
|
||||
title?: Maybe<string>
|
||||
description?: Maybe<string>
|
||||
pretitle?: Maybe<string>
|
||||
badge?: Maybe<string>
|
||||
footnote?: Maybe<string>
|
||||
color?: Maybe<{ value?: Maybe<Enum_Componentsharedcolor_Value> }>
|
||||
icon?: Maybe<{ value?: Maybe<Enum_Componentsharedicon_Value> }>
|
||||
}
|
||||
|
||||
export interface CasesCmsData {
|
||||
title?: Maybe<string>
|
||||
description?: Maybe<string>
|
||||
cards?: Maybe<Array<Maybe<CaseCardCms>>>
|
||||
}
|
||||
|
||||
interface CasesProps {
|
||||
data?: Maybe<CasesCmsData>
|
||||
}
|
||||
|
||||
export function Cases({ data }: CasesProps) {
|
||||
const title = data?.title ?? ''
|
||||
const description = data?.description ?? ''
|
||||
const cards = (data?.cards ?? []).filter((c): c is CaseCardCms => Boolean(c))
|
||||
|
||||
if (!title && !description && cards.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
export function Cases() {
|
||||
return (
|
||||
<section className="py-4 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">Реализованные проекты</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 lg:grid-cols-3 gap-8">
|
||||
{cases.map((caseItem, index) => {
|
||||
const Icon = caseItem.icon
|
||||
{cards.map((caseItem, index) => {
|
||||
const Icon = toComponent(caseItem.icon?.value)
|
||||
const gradient = toElevatedGradient(caseItem.color?.value)
|
||||
const iconColorClass = toTextColor(caseItem.color?.value)
|
||||
const floatClass =
|
||||
index === 0 ? 'animate-float' : index === 1 ? 'animate-float-delay-1' : 'animate-float-delay-2'
|
||||
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
key={caseItem.id}
|
||||
className="group bg-white rounded-2xl overflow-hidden border border-gray-100 hover:border-blue-200 hover:shadow-xl transition-all duration-300 cursor-pointer flex flex-col"
|
||||
>
|
||||
<div
|
||||
className={`relative h-64 overflow-hidden bg-linear-to-br ${caseItem.gradient} flex items-center justify-center`}
|
||||
className={`relative h-64 overflow-hidden bg-linear-to-br ${gradient} flex items-center justify-center`}
|
||||
>
|
||||
<div
|
||||
className={`w-24 h-24 ${caseItem.iconBg} rounded-2xl flex items-center justify-center group-hover:scale-110 transition-transform duration-300 shadow-md ${floatClass}`}
|
||||
className={`w-24 h-24 bg-white rounded-2xl flex items-center justify-center group-hover:scale-110 transition-transform duration-300 shadow-md ${floatClass}`}
|
||||
>
|
||||
<Icon className={`w-12 h-12 ${caseItem.iconColor}`} />
|
||||
</div>
|
||||
<div className="absolute top-4 left-4">
|
||||
<span className="px-3 py-1 bg-white/90 backdrop-blur-sm text-gray-900 rounded-full border border-gray-200 text-sm">
|
||||
{caseItem.category}
|
||||
</span>
|
||||
<Icon className={`w-12 h-12 ${iconColorClass}`} />
|
||||
</div>
|
||||
{caseItem.badge ? (
|
||||
<div className="absolute top-4 left-4">
|
||||
<span className="px-3 py-1 bg-white/90 backdrop-blur-sm text-gray-900 rounded-full border border-gray-200 text-sm">
|
||||
{caseItem.badge}
|
||||
</span>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="p-6 flex flex-col flex-1">
|
||||
<div className="text-sm text-blue-600 mb-2">{caseItem.company}</div>
|
||||
{caseItem.pretitle ? <div className="text-sm text-blue-600 mb-2">{caseItem.pretitle}</div> : null}
|
||||
|
||||
<h3 className="text-xl text-gray-900 mb-3">{caseItem.title}</h3>
|
||||
{caseItem.title ? <h3 className="text-xl text-gray-900 mb-3">{caseItem.title}</h3> : null}
|
||||
|
||||
<p className="text-gray-600 mb-4 leading-relaxed flex-1">{caseItem.description}</p>
|
||||
{caseItem.description ? (
|
||||
<p className="text-gray-600 mb-4 leading-relaxed flex-1">{caseItem.description}</p>
|
||||
) : null}
|
||||
|
||||
<div className="pt-4 border-t border-gray-100 flex items-center justify-between">
|
||||
<span className="text-gray-900">{caseItem.results}</span>
|
||||
<span className="text-gray-900">{caseItem.footnote ?? ''}</span>
|
||||
<ArrowRight className="w-5 h-5 text-gray-400 group-hover:text-blue-600 group-hover:translate-x-1 transition-all" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -89,7 +93,10 @@ export function Cases() {
|
||||
</div>
|
||||
|
||||
<div className="text-center mt-12">
|
||||
<button className="px-8 py-4 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-all shadow-md hover:shadow-lg inline-flex items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
className="px-8 py-4 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-all shadow-md hover:shadow-lg inline-flex items-center gap-2"
|
||||
>
|
||||
Все кейсы
|
||||
<ArrowRight className="w-5 h-5" />
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user