Files
geovektor/components/Projects.tsx
Arsen Akhmetzyanov fde9609f9a feat: simplify navigation and add RU/EN home and contacts
- simplify main navigation and hide extra menu items
- make home page more sales-focused with updated hero, benefits and fleet teaser
- add RU/EN handling for home and contacts, including SEO defaults
- integrate basic Strapi homepage API client (no breaking changes)
- update contacts page with messenger buttons and dynamic footer year

Made-with: Cursor
2026-03-13 19:41:07 +05:00

178 lines
10 KiB
TypeScript
Raw Permalink 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 React, { useState } from 'react';
import { groupProjectsByCategory } from '../constants';
import { MapPin, ChevronDown } from 'lucide-react';
import { Link, useLocation } from 'react-router-dom';
const Projects: React.FC = () => {
const location = useLocation();
const isEnglish = location.pathname.startsWith('/en');
const prefix = isEnglish ? '/en' : '';
const categories = groupProjectsByCategory().slice(0, 3); // Показываем только 3 категории
const [openCategories, setOpenCategories] = useState<{ [key: string]: boolean }>({
[categories[0]?.name]: true // Открываем первую категорию по умолчанию
});
const toggleCategory = (categoryName: string) => {
setOpenCategories(prev => ({
...prev,
[categoryName]: !prev[categoryName]
}));
};
return (
<div className="py-24 bg-white" id="projects">
<div className="container mx-auto px-6">
<div className="flex flex-col md:flex-row justify-between items-start md:items-end mb-16 gap-8">
<h2 className="text-4xl font-bold text-gray-900 max-w-xs leading-tight">
{isEnglish ? 'Our recent projects' : 'Наши недавние проекты'}
</h2>
<p className="text-gray-600 max-w-md text-sm leading-relaxed">
{isEnglish
? 'Our team treats every project with great responsibility. Thank you for your trust.'
: 'Наша команда всегда ответственно относится к проектам, которые вы нам доверили. Спасибо, что вы рядом.'}
</p>
</div>
<div className="space-y-4 mb-8">
{categories.map((category) => {
const categoryName = isEnglish
? (() => {
switch (category.name) {
case 'Нефтегазовая промышленность':
return 'Oil & gas industry';
case 'Коммерческая недвижимость и туризм':
return 'Commercial real estate and tourism';
case 'Прочие объекты':
return 'Other facilities';
default:
return category.name;
}
})()
: category.name;
return (
<div key={category.name} className="border border-gray-200 rounded-xl overflow-hidden">
{/* Заголовок категории */}
<button
onClick={() => toggleCategory(category.name)}
className="w-full flex items-center justify-between p-6 bg-gray-50 hover:bg-gray-100 transition-colors"
>
<div className="flex items-center gap-4">
<div className="flex-shrink-0 w-12 h-12 bg-brand-orange text-white rounded-lg flex items-center justify-center font-bold text-lg">
{category.projects.length}
</div>
<h3 className="text-xl font-bold text-gray-900">{categoryName}</h3>
</div>
<ChevronDown
size={24}
className={`text-brand-orange transition-transform duration-300 ${
openCategories[category.name] ? 'rotate-180' : ''
}`}
/>
</button>
{/* Список проектов (показываем только первые 3) */}
<div
className={`transition-all duration-300 ${
openCategories[category.name]
? 'max-h-[2000px] opacity-100'
: 'max-h-0 opacity-0 overflow-hidden'
}`}
>
<div className="p-4 space-y-3 bg-white">
{category.projects.slice(0, 3).map((project, index) => {
const title = isEnglish
? (() => {
switch (project.title) {
case 'ОАО «Газпромнефть-ОНПЗ»':
return '“GazpromneftONPZ” OJSC';
case 'ООО «Петон»':
return '“Peton” LLC';
case 'ОАО «Гипротрубопровод»':
return '“Giprotuboprovod” OJSC';
default:
return project.title;
}
})()
: project.title;
const description = isEnglish
? (() => {
switch (project.title) {
case 'ОАО «Газпромнефть-ОНПЗ»':
return 'Modernisation of unit 19/3 at GazpromneftONPZ in Omsk.';
case 'ООО «Петон»':
return 'L24/9. Technical upgrade. Heat recovery of diesel fuel hydrotreating unit (design and working documentation) at the GazpromneftONPZ site.';
case 'ОАО «Гипротрубопровод»':
return 'Reconstruction of the production base in Omsk.';
// Commercial real estate and tourism (examples)
case 'ООО «СУ-1 ОАО «Госстрой»':
return 'Fastfood restaurant “KFC” at the intersection of Marshala Zhukova and Akademika Korolyova streets in the Oktyabrsky district of Ufa.';
case 'ООО «Башкирский птицеводческий комплекс имени М. Гафури»':
return 'Architectural civil facility “Administrative and utility building” for the Bashkir Poultry Complex named after M. Gafuri.';
case 'ООО «Регион-Ресурс»':
return 'Construction of an ecotourism centre in the Kirovsky district of Ufa, Republic of Bashkortostan, including development of design documentation, support through expert review and approvals.';
case 'МБУ «Управление пожарной охраны ГО г. Уфа Республики Башкортостан':
return 'Fire station building with four bays located in the Leninsky district, settlement 8 Marta, Republic of Bashkortostan.';
case 'ООО «Управление капитального строительства «Монолитстрой»':
return 'Administrative, retail and entertainment complex in the Dema9 neighbourhood, Demsky district of Ufa, Republic of Bashkortostan.';
case 'ОАО «Уфимский хлопчатобумажный комбинат»':
return '“Ferris wheel58” on the site of the Ufa Cotton Mill at 137 Mendeleeva Street, Ufa.';
case 'ЗАО «Штрабаг»':
return 'Technology park of energyefficient technologies on a land plot within the administrative boundaries of the Ufimsky municipal district, Republic of Bashkortostan.';
case 'ООО «Уралстройсервис»':
return 'Underground garage with public service premises on the roof, at Rossiyskaya Street and Davletkildeyev Boulevard intersection in the Oktyabrsky district of Ufa.';
case 'ООО «РаушБиер»':
return 'Twostorey restaurant complex located at 8 Tukaeva Street, Tuymazy, Republic of Bashkortostan.';
case 'ООО СОК «Трамплин»':
return 'Ski tow lift in the Oktyabrsky district of Ufa, Republic of Bashkortostan.';
default:
return project.description;
}
})()
: project.description;
return (
<div
key={project.id}
className="group cursor-pointer bg-gray-50 hover:bg-gray-100 rounded-lg p-5 transition-all duration-300 border border-gray-200 hover:border-brand-orange"
>
<div className="flex items-start gap-4">
<div className="flex-shrink-0 w-10 h-10 bg-white border-2 border-brand-orange text-brand-orange rounded-lg flex items-center justify-center font-bold text-sm">
{index + 1}
</div>
<div className="flex-1">
<h4 className="text-base font-bold text-gray-900 mb-2 group-hover:text-brand-orange transition-colors">
{title}
</h4>
<div className="flex items-start gap-2 text-gray-600 text-sm">
<MapPin size={14} className="mt-1 flex-shrink-0 text-brand-orange" />
<span className="leading-relaxed line-clamp-2">{description}</span>
</div>
</div>
</div>
</div>
)})}
</div>
</div>
</div>
)})}
</div>
<div className="text-center">
<Link
to={`${prefix}/projects`}
className="inline-block px-8 py-3 bg-brand-orange text-white font-bold rounded-lg hover:bg-orange-600 transition-colors"
>
{isEnglish ? 'View all projects' : 'Смотреть все проекты'}
</Link>
</div>
</div>
</div>
);
};
export default Projects;