Files
geovektor/pages/CertificatesPage.tsx

285 lines
13 KiB
TypeScript
Raw Normal View History

2026-02-10 16:22:14 +05:00
import React, { useState, useEffect } from 'react';
import PageHeader from '../components/PageHeader';
import { FileText, X, ChevronLeft, ChevronRight } from 'lucide-react';
interface Certificate {
id: number;
image: string;
title: string;
}
interface CertificateSection {
title: string;
certificates: Certificate[];
}
const CertificatesPage: React.FC = () => {
const [selectedImageIndex, setSelectedImageIndex] = useState<number | null>(null);
const sections: CertificateSection[] = [
{
title: 'ПРОГРАММНЫЕ ПРОДУКТЫ КРЕДО',
certificates: [
{ id: 1, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Сертификат' }
]
},
{
title: 'ВЫПИСКА ИЗ СРО ПО СТРОИТЕЛЬСТВУ',
certificates: [
{ id: 2, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 1' },
{ id: 3, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 2' },
{ id: 4, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 3' },
{ id: 5, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 4' }
]
},
{
title: 'ВЫПИСКА ИЗ СРО ПО ПРОЕКТИРОВАНИЮ',
certificates: [
{ id: 6, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 1' },
{ id: 7, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 2' }
]
},
{
title: 'ВЫПИСКА ИЗ СРО ПО ИЗЫСКАНИЯМ',
certificates: [
{ id: 8, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 1' },
{ id: 9, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 2' }
]
},
{
title: 'ВЫПИСКА ИЗ РЕЕСТРА ЧЛЕНОВ САМОРЕГУЛИРУЕМОЙ ОРГАНИЗАЦИИ, ОСНОВАННОЙ НА ЧЛЕНСТВЕ ЛИЦ, ОСУЩЕСТВЛЯЮЩИХ СТРОИТЕЛЬСТВО',
certificates: [
{ id: 10, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 1' },
{ id: 11, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 2' },
{ id: 12, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 3' }
]
},
{
title: 'ВЫПИСКА ИЗ РЕЕСТРА ЧЛЕНОВ САМОРЕГУЛИРУЕМОЙ ОРГАНИЗАЦИИ, ОСНОВАННОЙ НА ЧЛЕНСТВЕ ЛИЦ, ОСУЩЕСТВЛЯЮЩИХ ИНЖЕНЕРНЫЕ ИЗЫСКАНИЯ',
certificates: [
{ id: 13, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 1' },
{ id: 14, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 2' }
]
},
{
title: 'ВЫПИСКА ИЗ РЕЕСТРА ЧЛЕНОВ САМОРЕГУЛИРУЕМОЙ ОРГАНИЗАЦИИ, ОСНОВАННОЙ НА ЧЛЕНСТВЕ ЛИЦ, ОСУЩЕСТВЛЯЮЩИХ ПРОЕКТНЫЕ РАБОТЫ',
certificates: [
{ id: 15, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 1' },
{ id: 16, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 2' }
]
},
{
title: 'СВЕДЕНИЕ НА ОСУЩЕСТВЛЕНИЕ ГЕОДЕЗИЧЕСКОЙ И КАРТОГРАФИЧЕСКОЙ ДЕЯТЕЛЬНОСТИ ФЕДЕРАЛЬНАЯ СЛУЖБА ГОСУДАРСТВА',
certificates: [
{ id: 17, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 1' },
{ id: 18, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 2' }
]
},
{
title: 'СВИДЕТЕЛЬСТВО О ПРОХОЖДЕНИИ ИСПЫТАНИЙ И КОНТРОЛЯ ПО ISO 9001',
certificates: [
{ id: 19, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 1' },
{ id: 20, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 2' },
{ id: 21, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 3' },
{ id: 22, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 4' },
{ id: 23, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 5' },
{ id: 24, image: 'https://placehold.co/400x600/94a3b8/white', title: 'Документ 6' }
]
}
];
// Создаем плоский массив всех изображений для навигации
const allImages = sections.flatMap(section => section.certificates.map(cert => cert.image));
const openModal = (image: string) => {
const index = allImages.indexOf(image);
setSelectedImageIndex(index);
document.body.style.overflow = 'hidden';
};
const closeModal = () => {
setSelectedImageIndex(null);
document.body.style.overflow = 'auto';
};
const nextImage = () => {
if (selectedImageIndex !== null) {
setSelectedImageIndex((selectedImageIndex + 1) % allImages.length);
}
};
const prevImage = () => {
if (selectedImageIndex !== null) {
setSelectedImageIndex((selectedImageIndex - 1 + allImages.length) % allImages.length);
}
};
// Обработка клавиатуры
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (selectedImageIndex === null) return;
if (e.key === 'Escape') {
closeModal();
} else if (e.key === 'ArrowRight') {
nextImage();
} else if (e.key === 'ArrowLeft') {
prevImage();
}
};
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [selectedImageIndex]);
return (
<div className="bg-white pb-20">
<PageHeader
title="Сертификаты"
description="Документы, подтверждающие нашу квалификацию и соответствие стандартам качества"
image="/media/images/headers/header-certificates.png"
/>
<div className="container mx-auto px-6 py-20">
<div className="max-w-7xl mx-auto">
<h2 className="text-3xl font-bold text-gray-900 mb-12 text-center">
СВИДЕТЕЛЬСТВА
</h2>
{/* Секции с сертификатами */}
<div className="space-y-16">
{sections.map((section, sectionIndex) => (
<div key={sectionIndex} className="space-y-6">
{/* Заголовок секции */}
<div className="flex items-center gap-3 mb-8">
<FileText className="text-brand-orange" size={28} />
<h3 className="text-lg font-bold text-gray-900 uppercase leading-tight">
{section.title}
</h3>
</div>
{/* Сетка документов */}
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-6">
{section.certificates.map((cert) => (
<div
key={cert.id}
onClick={() => openModal(cert.image)}
className="group cursor-pointer"
>
<div className="relative aspect-[3/4] rounded-lg overflow-hidden shadow-md hover:shadow-xl transition-all duration-300 bg-gray-100">
<img
src={cert.image}
alt={cert.title}
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-500"
/>
<div className="absolute inset-0 bg-black/0 group-hover:bg-black/10 transition-colors" />
{/* Overlay при наведении */}
<div className="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity">
<div className="bg-brand-orange text-white px-4 py-2 rounded-lg font-semibold text-sm">
Увеличить
</div>
</div>
</div>
</div>
))}
</div>
</div>
))}
</div>
{/* Информационный блок */}
<div className="mt-20 bg-gray-50 rounded-2xl p-8 md:p-12">
<div className="max-w-3xl mx-auto text-center">
<h3 className="text-2xl font-bold text-gray-900 mb-4">
Гарантия качества
</h3>
<p className="text-gray-600 leading-relaxed mb-6">
ООО «ГЕОВЕКТОР» имеет все необходимые лицензии и сертификаты для осуществления
деятельности в области проектирования, строительства и инженерных изысканий.
Наша компания является членом саморегулируемых организаций и соответствует
международным стандартам качества ISO 9001.
</p>
<div className="flex flex-wrap justify-center gap-4 mt-8">
<div className="bg-white px-6 py-3 rounded-lg shadow-sm">
<div className="text-2xl font-bold text-brand-orange mb-1">СРО</div>
<div className="text-sm text-gray-600">Член организации</div>
</div>
<div className="bg-white px-6 py-3 rounded-lg shadow-sm">
<div className="text-2xl font-bold text-brand-orange mb-1">ISO 9001</div>
<div className="text-sm text-gray-600">Сертифицирован</div>
</div>
<div className="bg-white px-6 py-3 rounded-lg shadow-sm">
<div className="text-2xl font-bold text-brand-orange mb-1">10+ лет</div>
<div className="text-sm text-gray-600">На рынке</div>
</div>
</div>
</div>
</div>
</div>
</div>
{/* Модальное окно для просмотра изображения */}
{selectedImageIndex !== null && (
<div
className="fixed inset-0 z-50 flex items-center justify-center bg-black/95 p-4"
onClick={closeModal}
>
{/* Кнопка закрытия */}
<button
onClick={closeModal}
className="absolute top-4 right-4 bg-white/10 hover:bg-white/20 text-white p-3 rounded-full transition-colors z-10"
aria-label="Закрыть"
>
<X size={28} />
</button>
{/* Кнопка "Назад" */}
<button
onClick={(e) => {
e.stopPropagation();
prevImage();
}}
className="absolute left-4 top-1/2 -translate-y-1/2 bg-white/10 hover:bg-white/20 text-white p-3 rounded-full transition-colors z-10"
aria-label="Предыдущее изображение"
>
<ChevronLeft size={32} />
</button>
{/* Кнопка "Вперед" */}
<button
onClick={(e) => {
e.stopPropagation();
nextImage();
}}
className="absolute right-4 top-1/2 -translate-y-1/2 bg-white/10 hover:bg-white/20 text-white p-3 rounded-full transition-colors z-10"
aria-label="Следующее изображение"
>
<ChevronRight size={32} />
</button>
{/* Индикатор */}
<div className="absolute bottom-4 left-1/2 -translate-x-1/2 bg-black/50 text-white px-4 py-2 rounded-full text-sm font-semibold z-10">
{selectedImageIndex + 1} / {allImages.length}
</div>
{/* Изображение */}
<div
className="relative w-full h-full flex items-center justify-center"
onClick={(e) => e.stopPropagation()}
>
<img
src={allImages[selectedImageIndex]}
alt={`Документ ${selectedImageIndex + 1}`}
className="max-w-full max-h-[90vh] object-contain rounded-lg shadow-2xl"
/>
</div>
</div>
)}
</div>
);
};
export default CertificatesPage;