Initial commit IP

This commit is contained in:
2026-02-10 16:36:26 +05:00
commit 605a5cb028
125 changed files with 8091 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
node_modules/
dist/
+67
View File
@@ -0,0 +1,67 @@
import React, { useEffect } from 'react';
import { HashRouter as Router, Routes, Route, useLocation } from 'react-router-dom';
import Navbar from './components/Navbar';
import Footer from './components/Footer';
import ScrollToTopButton from './components/ScrollToTop';
import Home from './pages/Home';
import ServicesPage from './pages/ServicesPage';
import ProjectsPage from './pages/ProjectsPage';
import AboutPage from './pages/AboutPage';
import ContactsPage from './pages/ContactsPage';
import FleetPage from './pages/FleetPage';
import CertificatesPage from './pages/CertificatesPage';
import SurveyingPage from './pages/SurveyingPage';
import DesignPage from './pages/DesignPage';
import ConstructionPage from './pages/ConstructionPage';
import SoilSurveyPage from './pages/SoilSurveyPage';
import BuildingSurveyPage from './pages/BuildingSurveyPage';
import LandSurveyPage from './pages/LandSurveyPage';
import TechnicalTasksPage from './pages/TechnicalTasksPage';
import SoilLabPage from './pages/SoilLabPage';
import RadiationLabPage from './pages/RadiationLabPage';
import PrivacyPolicyPage from './pages/PrivacyPolicyPage';
// Scroll to top on route change
const ScrollToTop = () => {
const { pathname } = useLocation();
useEffect(() => {
window.scrollTo(0, 0);
}, [pathname]);
return null;
};
const App: React.FC = () => {
return (
<Router>
<div className="w-full bg-white overflow-hidden font-sans flex flex-col min-h-screen">
<ScrollToTop />
<Navbar transparent={true} />
<main className="flex-grow">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/services" element={<ServicesPage />} />
<Route path="/services/surveying" element={<SurveyingPage />} />
<Route path="/services/design" element={<DesignPage />} />
<Route path="/services/construction" element={<ConstructionPage />} />
<Route path="/services/soil-survey" element={<SoilSurveyPage />} />
<Route path="/services/building-survey" element={<BuildingSurveyPage />} />
<Route path="/services/land-survey" element={<LandSurveyPage />} />
<Route path="/services/technical-tasks" element={<TechnicalTasksPage />} />
<Route path="/projects" element={<ProjectsPage />} />
<Route path="/fleet" element={<FleetPage />} />
<Route path="/laboratories/soil" element={<SoilLabPage />} />
<Route path="/laboratories/radiation" element={<RadiationLabPage />} />
<Route path="/certificates" element={<CertificatesPage />} />
<Route path="/about" element={<AboutPage />} />
<Route path="/contacts" element={<ContactsPage />} />
<Route path="/privacy-policy" element={<PrivacyPolicyPage />} />
</Routes>
</main>
<Footer />
<ScrollToTopButton />
</div>
</Router>
);
};
export default App;
+249
View File
@@ -0,0 +1,249 @@
# ✅ Финальный статус изображений на сайте
## 🎉 ПОЛНОСТЬЮ УСТАНОВЛЕНО (27 изображений)
### ✅ Главная страница (1 изображение)
- **Hero Banner** → `/media/images/hero/hero-main.png`
- Размер: 1920×1080px
- Файл: `components/Hero.tsx`
### ✅ Заголовки всех страниц (14 изображений)
| Страница | Файл | Изображение |
|----------|------|------------|
| О компании | `pages/AboutPage.tsx` | `/media/images/headers/header-about.png` |
| Услуги | `pages/ServicesPage.tsx` | `/media/images/headers/header-services.png` |
| Проекты | `pages/ProjectsPage.tsx` | `/media/images/headers/header-projects.png` |
| Автопарк | `pages/FleetPage.tsx` | `/media/images/headers/header-fleet.png` |
| Сертификаты | `pages/CertificatesPage.tsx` | `/media/images/headers/header-certificates.png` |
| Контакты | `pages/ContactsPage.tsx` | `/media/images/headers/header-kontakri.png` |
| Инж. изыскания | `pages/SurveyingPage.tsx` | `/media/images/headers/header-injinernie-iziskania.png` |
| Проектирование | `pages/DesignPage.tsx` | `/media/images/headers/header-projectirovanie.png` |
| Строительство | `pages/ConstructionPage.tsx` | `/media/images/headers/header-building.png` |
| Обследование грунтов | `pages/SoilSurveyPage.tsx` | `/media/images/headers/header-obsledovanie-gruntov.png` |
| Обследование зданий | `pages/BuildingSurveyPage.tsx` | `/media/images/headers/header-observing-buildings.png` |
| Землеустройство | `pages/LandSurveyPage.tsx` | `/media/images/headers/header-zemlestroit-kadastr-jobs.png` |
| Грунтовая лаборатория | `pages/SoilLabPage.tsx` | `/media/images/headers/soil-lab-header.png` |
| Радиационная лаборатория | `pages/RadiationLabPage.tsx` | `/media/images/headers/radio-lab-header.png` |
| Технические задания | `pages/TechnicalTasksPage.tsx` | `/media/images/services/technical-assignments.png` |
Размер: 1920×600px (все заголовки)
### ✅ Услуги на главной (7 изображений)
| Услуга | Изображение |
|--------|------------|
| Технические задания | `/media/images/services/technical-assignments.png` |
| Инженерные изыскания | `/media/images/services/engineering-surveys.png` |
| Проектирование | `/media/images/services/design.png` |
| Строительство | `/media/images/services/construction.png` |
| Обследование грунтов | `/media/images/services/soil-survey.png` |
| Обследование здания | `/media/images/services/building-inspection.png` |
| Кадастровые работы | `/media/images/services/cadastral-works.png` |
Размер: 600×800px (вертикальные)
Файл: `constants.ts` → SERVICES
### ✅ О компании (2 изображения)
- **Офис** → `/media/images/about/office.png` (800×600px)
- **Команда** → `/media/images/about/team-work.png` (600×400px)
- Файл: `pages/AboutPage.tsx`
### ✅ Лаборатории (2 изображения - переиспользованы)
- **Грунтовая лаборатория** → `/media/images/services/soil-survey.png`
- **Радиационная лаборатория** → `/media/images/services/engineering-surveys.png`
- Файл: `components/Laboratories.tsx`
### ✅ Дефолтное изображение
- **По умолчанию** → `/media/images/headers/header-about.png`
- Файл: `components/PageHeader.tsx` (используется для страниц без явного изображения)
---
## ⏳ ОСТАЮТСЯ ПЛЕЙСХОЛДЕРЫ (117 изображений)
### 📁 1. ПРОЕКТЫ - 93 изображения (600×400px)
**Файл**: `constants.ts` → PROJECTS (строки 82-174)
**Текущее значение**: `https://placehold.co/600x400/94a3b8/white`
#### 📂 Рекомендуемая структура папок:
```
media/images/projects/
oil-gas/ (30 изображений)
residential/ (15 изображений)
infrastructure/ (20 изображений)
social/ (10 изображений)
industrial/ (15 изображений)
commercial/ (3 изображения)
```
#### 🎨 ПРОМПТЫ для категорий проектов:
**A. Нефтегазовая промышленность** (30 проектов)
```
Промпт:
Oil and gas industrial complex, refinery towers and pipelines,
modern petrochemical plant, industrial infrastructure with storage tanks,
professional industrial photography, wide shot, blue sky, realistic, high quality
```
**B. Жилищное строительство** (15 проектов)
```
Промпт:
Modern residential apartment building complex, multi-story housing project,
contemporary urban architecture, landscaped courtyard, professional real estate photography,
daylight, realistic style
```
**C. Инфраструктура и коммуникации** (20 проектов)
```
Промпт:
Infrastructure construction project, pipeline installation, utility networks,
gas pipeline or water supply system being built, modern engineering work,
construction equipment, professional photography
```
**D. Социальные объекты** (10 проектов)
```
Промпт:
Modern public building - school, kindergarten, or community center,
contemporary social infrastructure architecture, accessible design,
professional architectural photography, welcoming appearance
```
**E. Промышленные объекты** (15 проектов)
```
Промпт:
Industrial warehouse or production facility, modern factory building,
metal hangars, industrial architecture with steel structures,
professional industrial photography, clean and organized
```
**F. Коммерческая недвижимость** (3 проекта)
```
Промпт:
Modern commercial building, business center with glass facade,
contemporary office architecture, urban location, professional photography
```
#### 💡 БЫСТРОЕ РЕШЕНИЕ для проектов:
Вместо 93 уникальных изображений, создайте **6 базовых** (по одному на категорию):
- `project-oil-gas.jpg`
- `project-residential.jpg`
- `project-infrastructure.jpg`
- `project-social.jpg`
- `project-industrial.jpg`
- `project-commercial.jpg`
Затем я обновлю код, чтобы каждая категория использовала соответствующее изображение.
---
### 📜 2. СЕРТИФИКАТЫ - 24 изображения (400×600px)
**Файл**: `pages/CertificatesPage.tsx` (строки 23-86)
**Текущее значение**: `https://placehold.co/400x600/94a3b8/white`
#### 📂 Структура:
```
media/images/certificates/
cert-1.jpg - Сертификат КРЕДО
cert-2.jpg - СРО Строительство (док 1)
cert-3.jpg - СРО Строительство (док 2)
cert-4.jpg - СРО Строительство (док 3)
cert-5.jpg - СРО Строительство (док 4)
cert-6.jpg - СРО Проектирование (док 1)
cert-7.jpg - СРО Проектирование (док 2)
cert-8.jpg - СРО Изыскания (док 1)
cert-9.jpg - СРО Изыскания (док 2)
cert-10.jpg - Членство СРО Строительство (док 1)
cert-11.jpg - Членство СРО Строительство (док 2)
cert-12.jpg - Членство СРО Строительство (док 3)
cert-13.jpg - Членство СРО Проектирование (док 1)
cert-14.jpg - Членство СРО Проектирование (док 2)
cert-15.jpg - Членство СРО Изыскания (док 1)
cert-16.jpg - Членство СРО Изыскания (док 2)
cert-17.jpg - Допуск к опасным объектам (док 1)
cert-18.jpg - Допуск к опасным объектам (док 2)
cert-19.jpg - Лицензия 1
cert-20.jpg - Лицензия 2
cert-21.jpg - Лицензия 3
cert-22.jpg - Лицензия 4
cert-23.jpg - Лицензия 5
cert-24.jpg - Лицензия 6
```
#### ⚠️ ВАЖНО для сертификатов:
**НЕ ГЕНЕРИРУЙТЕ** эти изображения с помощью AI!
Вам нужно:
1. Отсканировать ваши **реальные сертификаты** компании (СРО, лицензии, допуски)
2. Сохранить их как `cert-1.jpg`, `cert-2.jpg`, и т.д.
3. Поместить в папку `media/images/certificates/`
4. Я обновлю код для их использования
**Альтернатива**: Если сертификаты конфиденциальны, можете временно оставить плейсхолдеры.
---
## 📊 ФИНАЛЬНАЯ СТАТИСТИКА
| Категория | Статус | Количество | Процент |
|-----------|--------|------------|---------|
| Hero & Headers | ✅ **Установлено** | 15 | 100% |
| Услуги | ✅ **Установлено** | 7 | 100% |
| О компании | ✅ **Установлено** | 2 | 100% |
| Лаборатории | ✅ **Установлено** | 2 | 100% |
| **Проекты** | ⏳ **Плейсхолдеры** | **93** | 0% |
| **Сертификаты** | ⏳ **Плейсхолдеры** | **24** | 0% |
| **ИТОГО** | | **143** | **19%** ✅ |
---
## 🚀 СЛЕДУЮЩИЕ ДЕЙСТВИЯ
### Для завершения работы осталось:
#### 1. Проекты (93 изображения)
**Выберите один из вариантов:**
**🌟 Вариант A (рекомендуется)**: Создать 6 категорийных изображений
- Создайте папку: `media/images/projects/`
- Сгенерируйте 6 изображений (по промптам выше)
- Назовите: `oil-gas.jpg`, `residential.jpg`, `infrastructure.jpg`, `social.jpg`, `industrial.jpg`, `commercial.jpg`
- Скажите мне → я обновлю код для автоматической привязки по категориям
**🎨 Вариант B**: Сгенерировать 93 уникальных изображения
- Используйте промпты из `IMAGE_GENERATION_LIST.md`
- Назовите: `project-1.jpg` до `project-93.jpg`
- Скажите мне → я обновлю все пути в константах
**⏭️ Вариант C**: Пропустить пока
- Плейсхолдеры будут работать нормально
- Добавите изображения позже
#### 2. Сертификаты (24 изображения)
- **Отсканируйте реальные документы** вашей компании
- Сохраните в: `media/images/certificates/`
- Скажите мне → я обновлю пути
---
## 🎯 ТЕКУЩИЙ РЕЗУЛЬТАТ
**Ваш сайт уже выглядит профессионально!**
Все основные страницы имеют красивые заголовки, услуги отображаются с изображениями, главная страница полностью готова.
Плейсхолдеры для проектов и сертификатов **не критичны** — они показываются корректно и не ломают дизайн.
---
## 💬 Что делать дальше?
Скажите мне:
1. "Создал изображения для проектов" → я подключу их
2. "Оставим проекты с плейсхолдерами" → оставим как есть
3. "Создай скрипт для массового обновления" → я создам автоматизацию
**Готово к запуску сайта!** 🚀
+20
View File
@@ -0,0 +1,20 @@
<div align="center">
<img width="1200" height="475" alt="GHBanner" src="https://github.com/user-attachments/assets/0aa67016-6eaf-458a-adb2-6e31a0763ed6" />
</div>
# Run and deploy your AI Studio app
This contains everything you need to run your app locally.
View your app in AI Studio: https://ai.studio/apps/drive/1QCqfHN0ERBMa_RDsVDPW13W8gJQWQbPG
## Run Locally
**Prerequisites:** Node.js
1. Install dependencies:
`npm install`
2. Set the `GEMINI_API_KEY` in [.env.local](.env.local) to your Gemini API key
3. Run the app:
`npm run dev`
+35
View File
@@ -0,0 +1,35 @@
import React from 'react';
import { BENEFITS } from '../constants';
const Benefits: React.FC = () => {
return (
<div className="py-24 bg-white">
<div className="container mx-auto px-6">
<div className="grid grid-cols-1 lg:grid-cols-12 gap-12">
<div className="lg:col-span-4">
<span className="text-sm text-gray-500 uppercase tracking-widest mb-2 block">Выбирая нас</span>
<h2 className="text-4xl font-bold text-gray-900 mb-6">Вы получаете</h2>
<p className="text-gray-500 text-sm">Нас выбирают люди</p>
</div>
<div className="lg:col-span-8 grid grid-cols-1 md:grid-cols-2 gap-x-12 gap-y-16">
{BENEFITS.map((item, index) => (
<div key={index} className="flex flex-col items-start gap-4">
<div className="w-12 h-12 rounded-full bg-brand-orange/20 flex items-center justify-center text-brand-orange">
<item.icon size={24} />
</div>
<p className="text-gray-700 leading-relaxed font-medium">
{item.description}
</p>
</div>
))}
</div>
</div>
</div>
</div>
);
};
export default Benefits;
+135
View File
@@ -0,0 +1,135 @@
import React from 'react';
import { Send, MapPin, Mail, Phone } from 'lucide-react';
import { Link } from 'react-router-dom';
const Footer: React.FC = () => {
return (
<footer className="bg-[#1a0f0f] text-white py-20 rounded-t-[3rem] mt-auto" id="contacts">
<div className="container mx-auto px-6">
<div className="flex flex-col lg:flex-row gap-20">
{/* Contacts Section with Accent */}
<div className="lg:w-1/2">
<h2 className="text-4xl font-bold mb-8 text-brand-orange">Свяжитесь с нами</h2>
<p className="text-gray-300 text-lg mb-10 max-w-md">
Готовы ответить на ваши вопросы и предложить лучшие решения для вашего проекта
</p>
<div className="space-y-6 max-w-md">
<a
href="tel:83472927370"
className="flex items-start gap-4 p-6 bg-brand-orange/10 border border-brand-orange/30 rounded-2xl hover:bg-brand-orange hover:scale-105 transition-all duration-300 group"
>
<Phone size={28} className="text-brand-orange group-hover:text-white flex-shrink-0" />
<div>
<p className="text-xs text-gray-400 mb-1 group-hover:text-white/80">Телефон</p>
<p className="text-xl font-bold text-white">8 (347) 292 73 70</p>
<p className="text-sm text-gray-400 mt-1 group-hover:text-white/70">Звоните с 9:00 до 18:00</p>
</div>
</a>
<a
href="mailto:gw@geowektor.ru"
className="flex items-start gap-4 p-6 bg-brand-orange/10 border border-brand-orange/30 rounded-2xl hover:bg-brand-orange hover:scale-105 transition-all duration-300 group"
>
<Mail size={28} className="text-brand-orange group-hover:text-white flex-shrink-0" />
<div>
<p className="text-xs text-gray-400 mb-1 group-hover:text-white/80">Email</p>
<p className="text-xl font-bold text-white">gw@geowektor.ru</p>
<p className="text-sm text-gray-400 mt-1 group-hover:text-white/70">Ответим в течение часа</p>
</div>
</a>
<div className="flex items-start gap-4 p-6 bg-brand-orange/10 border border-brand-orange/30 rounded-2xl">
<MapPin size={28} className="text-brand-orange flex-shrink-0" />
<div>
<p className="text-xs text-gray-400 mb-1">Адрес</p>
<p className="text-lg font-bold text-white">450001, РБ, г. Уфа</p>
<p className="text-white/90">ул. Комсомольская 19/1</p>
</div>
</div>
</div>
</div>
{/* Links & Social Section */}
<div className="lg:w-1/2 grid grid-cols-1 md:grid-cols-3 gap-8">
{/* Основная навигация */}
<div>
<h4 className="font-bold mb-6 text-lg">Компания</h4>
<ul className="space-y-3 text-sm text-gray-400">
<li><Link to="/" className="hover:text-brand-orange transition-colors">Главная</Link></li>
<li><Link to="/about" className="hover:text-brand-orange transition-colors">О компании</Link></li>
<li><Link to="/projects" className="hover:text-brand-orange transition-colors">Проекты</Link></li>
<li><Link to="/fleet" className="hover:text-brand-orange transition-colors">Автопарк</Link></li>
<li><Link to="/certificates" className="hover:text-brand-orange transition-colors">Сертификаты</Link></li>
<li><Link to="/contacts" className="hover:text-brand-orange transition-colors">Контакты</Link></li>
</ul>
</div>
{/* Услуги */}
<div>
<h4 className="font-bold mb-6 text-lg">Услуги</h4>
<ul className="space-y-3 text-sm text-gray-400">
<li><Link to="/services" className="hover:text-brand-orange transition-colors">Все услуги</Link></li>
<li><Link to="/services/surveying" className="hover:text-brand-orange transition-colors">Инженерные изыскания</Link></li>
<li><Link to="/services/design" className="hover:text-brand-orange transition-colors">Проектирование</Link></li>
<li><Link to="/services/construction" className="hover:text-brand-orange transition-colors">Строительство</Link></li>
<li><Link to="/services/soil-survey" className="hover:text-brand-orange transition-colors">Обследование грунтов</Link></li>
<li><Link to="/services/building-survey" className="hover:text-brand-orange transition-colors">Обследование зданий</Link></li>
<li><Link to="/services/land-survey" className="hover:text-brand-orange transition-colors">Кадастровые работы</Link></li>
</ul>
</div>
{/* Лаборатории и соцсети */}
<div>
<h4 className="font-bold mb-6 text-lg">Лаборатории</h4>
<ul className="space-y-3 text-sm text-gray-400 mb-8">
<li><Link to="/laboratories/soil" className="hover:text-brand-orange transition-colors">Грунтовая лаборатория</Link></li>
<li><Link to="/laboratories/radiation" className="hover:text-brand-orange transition-colors">Радиационная лаборатория</Link></li>
</ul>
<h4 className="font-bold mb-4 text-lg">Мы в интернете</h4>
<div className="flex gap-4 mb-8">
<a
href="https://t.me/ooo_geo_wektor"
target="_blank"
rel="noopener noreferrer"
className="w-12 h-12 rounded-full bg-brand-orange flex items-center justify-center text-white cursor-pointer hover:bg-white hover:text-brand-orange transition-all transform hover:scale-110"
title="Telegram"
>
<Send size={22} />
</a>
<a
href="https://vk.com/geowektor_ru"
target="_blank"
rel="noopener noreferrer"
className="w-12 h-12 rounded-full bg-brand-orange flex items-center justify-center text-white cursor-pointer hover:bg-white hover:text-brand-orange transition-all transform hover:scale-110"
title="VK"
>
<div className="font-bold text-sm">Vk</div>
</a>
</div>
<div className="space-y-3 text-sm">
<Link
to="/privacy-policy"
className="text-gray-400 hover:text-brand-orange transition-colors block"
>
Политика конфиденциальности
</Link>
</div>
<div className="mt-8 text-xs text-gray-600">
©2025 ООО «ГеоВектор».<br />
Все права защищены.
</div>
</div>
</div>
</div>
</div>
</footer>
);
};
export default Footer;
+63
View File
@@ -0,0 +1,63 @@
import React from 'react';
import { STATS } from '../constants';
import { Link } from 'react-router-dom';
const Hero: React.FC = () => {
return (
<div className="relative w-full min-h-screen bg-brand-dark text-white flex flex-col">
{/* Background Image Overlay */}
<div className="absolute inset-0 z-0">
<img
src="/media/images/hero/hero-main.png"
alt="Construction Site"
className="w-full h-full object-cover opacity-40"
loading="eager"
/>
<div className="absolute inset-0 bg-gradient-to-r from-brand-dark/90 via-brand-dark/50 to-brand-dark/70 animate-gradient" />
</div>
{/* Hero Content */}
<div className="relative z-10 container mx-auto px-6 flex-grow flex flex-col justify-center py-32 md:py-20">
<div className="max-w-5xl mx-auto text-center mt-10 md:mt-0">
<h1 className="text-4xl md:text-5xl lg:text-7xl font-bold leading-tight mb-8">
Инженерные изыскания,
<br />
<span className="text-brand-orange">проектирование</span> и
<br />
<span className="text-brand-orange">строительство</span>
</h1>
<p className="text-gray-300 text-lg md:text-xl mb-12 max-w-3xl mx-auto leading-relaxed">
ООО «ГеоВектор» профессиональные решения для вашего проекта от изысканий до сдачи объекта.
Современное оборудование, опытные специалисты и соблюдение всех норм и стандартов.
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center">
<Link
to="/contacts"
className="inline-flex items-center justify-center bg-brand-orange text-white font-bold py-4 px-8 rounded-xl hover:bg-orange-600 transition-all duration-300 shadow-lg hover:shadow-xl hover:scale-105"
>
Рассчитать стоимость проекта
</Link>
<Link
to="/services"
className="inline-flex items-center justify-center bg-white/10 backdrop-blur-sm text-white font-bold py-4 px-8 rounded-xl hover:bg-white/20 transition-all duration-300 border-2 border-white/30"
>
Наши услуги
</Link>
</div>
</div>
{/* Stats */}
<div className="mt-24 grid grid-cols-1 md:grid-cols-3 gap-8 border-t border-white/10 pt-12 max-w-5xl mx-auto w-full">
{STATS.map((stat, idx) => (
<div key={idx} className="flex flex-col items-center text-center">
<span className="text-4xl md:text-5xl font-bold text-brand-orange mb-2">{stat.value}</span>
<p className="text-gray-400 text-sm md:text-base leading-relaxed">{stat.label}</p>
</div>
))}
</div>
</div>
</div>
);
};
export default Hero;
+186
View File
@@ -0,0 +1,186 @@
import React from 'react';
import { Microscope, Activity, ArrowRight, CheckCircle2, Shield } from 'lucide-react';
import { Link } from 'react-router-dom';
const Laboratories: React.FC = () => {
return (
<section className="py-20 bg-gradient-to-b from-white to-gray-50">
<div className="container mx-auto px-6">
<div className="text-center mb-16">
<div className="inline-flex items-center justify-center w-16 h-16 bg-brand-orange/10 rounded-full mb-6">
<Microscope className="text-brand-orange" size={32} />
</div>
<h2 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4">
Наши лаборатории
</h2>
<p className="text-gray-600 text-lg max-w-2xl mx-auto">
Современное оборудование и квалифицированные специалисты для проведения
комплексных исследований
</p>
</div>
<div className="max-w-7xl mx-auto grid md:grid-cols-2 gap-8">
{/* Грунтовая лаборатория */}
<div className="group bg-white rounded-3xl overflow-hidden shadow-xl hover:shadow-2xl transition-all duration-300 border-2 border-transparent hover:border-brand-orange">
{/* Изображение с наложением */}
<div className="relative h-64 overflow-hidden">
<img
src="/media/images/services/soil-survey.png"
alt="Грунтовая лаборатория"
className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-500"
loading="lazy"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/70 via-black/30 to-transparent"></div>
{/* Иконка */}
<div className="absolute top-6 left-6">
<div className="w-16 h-16 bg-white/20 backdrop-blur-md rounded-xl flex items-center justify-center border-2 border-white/30">
<Microscope className="text-white" size={32} />
</div>
</div>
{/* Заголовок на изображении */}
<div className="absolute bottom-6 left-6 right-6">
<h3 className="text-2xl font-bold text-white mb-2">
Грунтовая лаборатория
</h3>
<p className="text-white/90 text-sm">
Исследования физических, механических и химических свойств
</p>
</div>
</div>
{/* Контент карточки */}
<div className="p-8">
<div className="space-y-4 mb-8">
<div className="flex items-start gap-3">
<CheckCircle2 className="text-brand-orange flex-shrink-0 mt-1" size={20} />
<div>
<p className="text-gray-700 font-medium">Физические свойства грунтов</p>
<p className="text-sm text-gray-500">Влажность, плотность, гранулометрический состав</p>
</div>
</div>
<div className="flex items-start gap-3">
<CheckCircle2 className="text-brand-orange flex-shrink-0 mt-1" size={20} />
<div>
<p className="text-gray-700 font-medium">Механические характеристики</p>
<p className="text-sm text-gray-500">Прочность, деформируемость, сжимаемость</p>
</div>
</div>
<div className="flex items-start gap-3">
<CheckCircle2 className="text-brand-orange flex-shrink-0 mt-1" size={20} />
<div>
<p className="text-gray-700 font-medium">Химический анализ</p>
<p className="text-sm text-gray-500">Агрессивность грунтов, анализ воды</p>
</div>
</div>
</div>
{/* Кнопка */}
<Link
to="/laboratories/soil"
className="flex items-center justify-center gap-2 w-full py-4 bg-gradient-to-r from-brand-orange to-orange-600 text-white font-bold rounded-xl hover:from-orange-600 hover:to-brand-orange transition-all duration-300 group/btn"
>
Подробнее о лаборатории
<ArrowRight className="group-hover/btn:translate-x-1 transition-transform" size={20} />
</Link>
</div>
</div>
{/* Радиационная лаборатория */}
<div className="group bg-white rounded-3xl overflow-hidden shadow-xl hover:shadow-2xl transition-all duration-300 border-2 border-transparent hover:border-brand-orange">
{/* Изображение с наложением */}
<div className="relative h-64 overflow-hidden">
<img
src="/media/images/services/engineering-surveys.png"
alt="Радиационная лаборатория"
className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-500"
loading="lazy"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/70 via-black/30 to-transparent"></div>
{/* Иконка */}
<div className="absolute top-6 left-6">
<div className="w-16 h-16 bg-white/20 backdrop-blur-md rounded-xl flex items-center justify-center border-2 border-white/30">
<Activity className="text-white" size={32} />
</div>
</div>
{/* Заголовок на изображении */}
<div className="absolute bottom-6 left-6 right-6">
<h3 className="text-2xl font-bold text-white mb-2">
Радиационная лаборатория
</h3>
<p className="text-white/90 text-sm">
Профессиональные исследования радиационной безопасности
</p>
</div>
</div>
{/* Контент карточки */}
<div className="p-8">
<div className="space-y-4 mb-8">
<div className="flex items-start gap-3">
<Shield className="text-brand-orange flex-shrink-0 mt-1" size={20} />
<div>
<p className="text-gray-700 font-medium">Радиационный контроль</p>
<p className="text-sm text-gray-500">Измерение уровня радона и гамма-излучения</p>
</div>
</div>
<div className="flex items-start gap-3">
<Shield className="text-brand-orange flex-shrink-0 mt-1" size={20} />
<div>
<p className="text-gray-700 font-medium">Аккредитованная лаборатория</p>
<p className="text-sm text-gray-500">Техническая компетентность и независимость</p>
</div>
</div>
<div className="flex items-start gap-3">
<Shield className="text-brand-orange flex-shrink-0 mt-1" size={20} />
<div>
<p className="text-gray-700 font-medium">Современное оборудование</p>
<p className="text-sm text-gray-500">КАМЕРА-01, ДКГ-02У, ДРБП-03</p>
</div>
</div>
</div>
{/* Кнопка */}
<Link
to="/laboratories/radiation"
className="flex items-center justify-center gap-2 w-full py-4 bg-gradient-to-r from-brand-orange to-orange-600 text-white font-bold rounded-xl hover:from-orange-600 hover:to-brand-orange transition-all duration-300 group/btn"
>
Подробнее о лаборатории
<ArrowRight className="group-hover/btn:translate-x-1 transition-transform" size={20} />
</Link>
</div>
</div>
</div>
{/* Дополнительная информация */}
<div className="mt-16 max-w-4xl mx-auto">
<div className="bg-gradient-to-br from-gray-900 to-gray-800 text-white rounded-2xl p-8 md:p-12 text-center">
<h3 className="text-2xl md:text-3xl font-bold mb-4">
Нужна консультация по лабораторным исследованиям?
</h3>
<p className="text-gray-300 mb-6 max-w-2xl mx-auto">
Наши специалисты помогут подобрать оптимальный комплекс исследований для вашего проекта
</p>
<Link
to="/contacts"
className="inline-flex items-center gap-2 px-8 py-4 bg-brand-orange text-white font-bold rounded-xl hover:bg-orange-600 transition-colors"
>
Связаться с нами
<ArrowRight size={20} />
</Link>
</div>
</div>
</div>
</section>
);
};
export default Laboratories;
+25
View File
@@ -0,0 +1,25 @@
import React from 'react';
const Loading: React.FC = () => {
return (
<div className="fixed inset-0 bg-brand-dark flex items-center justify-center z-50">
<div className="text-center">
<img
src="/media/geo-logo.webp"
alt="ГеоВектор"
className="w-24 h-24 mx-auto mb-6 animate-pulse"
/>
<div className="flex items-center justify-center gap-2">
<div className="w-3 h-3 bg-brand-orange rounded-full animate-bounce"></div>
<div className="w-3 h-3 bg-brand-orange rounded-full animate-bounce" style={{ animationDelay: '0.1s' }}></div>
<div className="w-3 h-3 bg-brand-orange rounded-full animate-bounce" style={{ animationDelay: '0.2s' }}></div>
</div>
<p className="text-gray-400 mt-4 text-sm">Загрузка...</p>
</div>
</div>
);
};
export default Loading;
+414
View File
@@ -0,0 +1,414 @@
import React, { useState, useEffect } from 'react';
import { Phone, Menu, X, ChevronDown } from 'lucide-react';
import { Link, useLocation } from 'react-router-dom';
import { NAV_LINKS } from '../constants';
interface NavbarProps {
transparent?: boolean;
}
const Navbar: React.FC<NavbarProps> = ({ transparent = false }) => {
const [isScrolled, setIsScrolled] = useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const [isMobileServicesMenuOpen, setIsMobileServicesMenuOpen] = useState(false);
const [isMobileLabMenuOpen, setIsMobileLabMenuOpen] = useState(false);
const [imgError, setImgError] = useState(false);
const location = useLocation();
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 50);
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
const isHome = location.pathname === '/';
// Use transparent background only on Home and when not scrolled, if requested
const isTransparent = transparent && isHome && !isScrolled;
return (
<nav
className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ${
isTransparent ? 'bg-transparent py-6' : 'bg-brand-dark/95 backdrop-blur-md py-4 shadow-lg'
}`}
>
<div className="container mx-auto px-6 flex items-center justify-between text-white">
{/* Logo */}
<Link to="/" className="flex items-center gap-2 group">
{!imgError ? (
<img
src="/media/geo-logo.webp"
alt="ГеоВектор"
className="h-[64px] w-auto object-contain"
onError={() => setImgError(true)}
/>
) : (
<span className="text-xl font-bold tracking-tighter">
ГЕО<span className="text-brand-orange">ВЕКТОР</span>
</span>
)}
</Link>
{/* Desktop Menu */}
<ul className="hidden md:flex gap-8 text-sm font-medium items-center">
{/* Главная */}
<li>
<Link
to="/"
className={`transition-colors hover:text-brand-orange ${
location.pathname === '/' ? 'text-brand-orange' : 'text-gray-300'
}`}
>
Главная
</Link>
</li>
{/* О компании */}
<li>
<Link
to="/about"
className={`transition-colors hover:text-brand-orange ${
location.pathname === '/about' ? 'text-brand-orange' : 'text-gray-300'
}`}
>
О компании
</Link>
</li>
{/* Услуги с выпадающим меню */}
<li className="relative group">
<button
className={`flex items-center gap-1 transition-colors hover:text-brand-orange ${
location.pathname.startsWith('/services') ? 'text-brand-orange' : 'text-gray-300'
}`}
>
Услуги
<ChevronDown size={16} className={`transition-transform group-hover:rotate-180`} />
</button>
{/* Выпадающее меню */}
<div className="absolute top-full left-0 pt-2 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200">
<div className="w-72 bg-brand-dark border border-gray-700 rounded-lg shadow-xl overflow-hidden">
<Link
to="/services"
className="block px-6 py-3 text-gray-300 hover:bg-brand-orange hover:text-white transition-colors font-semibold border-b border-gray-700"
>
Все услуги
</Link>
<Link
to="/services/surveying"
className="block px-6 py-3 text-gray-300 hover:bg-brand-orange hover:text-white transition-colors"
>
Инженерные изыскания
</Link>
<Link
to="/services/design"
className="block px-6 py-3 text-gray-300 hover:bg-brand-orange hover:text-white transition-colors"
>
Проектирование
</Link>
<Link
to="/services/construction"
className="block px-6 py-3 text-gray-300 hover:bg-brand-orange hover:text-white transition-colors"
>
Строительство
</Link>
<Link
to="/services/soil-survey"
className="block px-6 py-3 text-gray-300 hover:bg-brand-orange hover:text-white transition-colors"
>
Обследование грунтов
</Link>
<Link
to="/services/building-survey"
className="block px-6 py-3 text-gray-300 hover:bg-brand-orange hover:text-white transition-colors"
>
Обследование здания
</Link>
<Link
to="/services/land-survey"
className="block px-6 py-3 text-gray-300 hover:bg-brand-orange hover:text-white transition-colors"
>
Кадастровые работы
</Link>
<Link
to="/services/technical-tasks"
className="block px-6 py-3 text-gray-300 hover:bg-brand-orange hover:text-white transition-colors border-t border-gray-700"
>
Образцы технических заданий
</Link>
</div>
</div>
</li>
{/* Проекты */}
<li>
<Link
to="/projects"
className={`transition-colors hover:text-brand-orange ${
location.pathname === '/projects' ? 'text-brand-orange' : 'text-gray-300'
}`}
>
Проекты
</Link>
</li>
{/* Автопарк */}
<li>
<Link
to="/fleet"
className={`transition-colors hover:text-brand-orange ${
location.pathname === '/fleet' ? 'text-brand-orange' : 'text-gray-300'
}`}
>
Автопарк
</Link>
</li>
{/* Сертификаты */}
<li>
<Link
to="/certificates"
className={`transition-colors hover:text-brand-orange ${
location.pathname === '/certificates' ? 'text-brand-orange' : 'text-gray-300'
}`}
>
Сертификаты
</Link>
</li>
{/* Лаборатории с выпадающим меню */}
<li className="relative group">
<button
className={`flex items-center gap-1 transition-colors hover:text-brand-orange ${
location.pathname.startsWith('/laboratories') ? 'text-brand-orange' : 'text-gray-300'
}`}
>
Лаборатории
<ChevronDown size={16} className={`transition-transform group-hover:rotate-180`} />
</button>
{/* Выпадающее меню */}
<div className="absolute top-full left-0 pt-2 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200">
<div className="w-64 bg-brand-dark border border-gray-700 rounded-lg shadow-xl overflow-hidden">
<Link
to="/laboratories/soil"
className="block px-6 py-3 text-gray-300 hover:bg-brand-orange hover:text-white transition-colors"
>
Грунтовая лаборатория
</Link>
<Link
to="/laboratories/radiation"
className="block px-6 py-3 text-gray-300 hover:bg-brand-orange hover:text-white transition-colors"
>
Радиационная лаборатория
</Link>
</div>
</div>
</li>
{/* Контакты */}
<li>
<Link
to="/contacts"
className={`transition-colors hover:text-brand-orange ${
location.pathname === '/contacts' ? 'text-brand-orange' : 'text-gray-300'
}`}
>
Контакты
</Link>
</li>
</ul>
{/* CTA & Mobile Toggle */}
<div className="flex items-center gap-4">
<Link to="/contacts" className="hidden md:flex items-center gap-2 text-sm font-medium hover:text-brand-orange transition-colors">
<Phone className="w-4 h-4 text-brand-orange" />
<span>Связаться</span>
</Link>
<button
className="md:hidden text-white"
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
>
{isMobileMenuOpen ? <X /> : <Menu />}
</button>
</div>
</div>
{/* Mobile Menu */}
{isMobileMenuOpen && (
<div className="absolute top-full left-0 w-full bg-brand-dark border-t border-gray-800 p-6 flex flex-col gap-6 md:hidden shadow-xl">
{/* Главная */}
<Link
to="/"
className="text-lg font-medium text-gray-300 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
Главная
</Link>
{/* О компании */}
<Link
to="/about"
className="text-lg font-medium text-gray-300 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
О компании
</Link>
{/* Услуги в мобильном меню */}
<div>
<button
className="flex items-center justify-between w-full text-lg font-medium text-gray-300 hover:text-brand-orange"
onClick={() => setIsMobileServicesMenuOpen(!isMobileServicesMenuOpen)}
>
Услуги
<ChevronDown size={20} className={`transition-transform ${isMobileServicesMenuOpen ? 'rotate-180' : ''}`} />
</button>
{isMobileServicesMenuOpen && (
<div className="ml-4 mt-3 flex flex-col gap-3">
<Link
to="/services"
className="text-gray-400 hover:text-brand-orange font-semibold"
onClick={() => setIsMobileMenuOpen(false)}
>
Все услуги
</Link>
<Link
to="/services/surveying"
className="text-gray-400 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
Инженерные изыскания
</Link>
<Link
to="/services/design"
className="text-gray-400 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
Проектирование
</Link>
<Link
to="/services/construction"
className="text-gray-400 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
Строительство
</Link>
<Link
to="/services/soil-survey"
className="text-gray-400 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
Обследование грунтов
</Link>
<Link
to="/services/building-survey"
className="text-gray-400 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
Обследование здания
</Link>
<Link
to="/services/land-survey"
className="text-gray-400 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
Кадастровые работы
</Link>
<Link
to="/services/technical-tasks"
className="text-gray-400 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
Образцы ТЗ
</Link>
</div>
)}
</div>
{/* Проекты */}
<Link
to="/projects"
className="text-lg font-medium text-gray-300 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
Проекты
</Link>
{/* Автопарк */}
<Link
to="/fleet"
className="text-lg font-medium text-gray-300 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
Автопарк
</Link>
{/* Сертификаты */}
<Link
to="/certificates"
className="text-lg font-medium text-gray-300 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
Сертификаты
</Link>
{/* Лаборатории в мобильном меню */}
<div>
<button
className="flex items-center justify-between w-full text-lg font-medium text-gray-300 hover:text-brand-orange"
onClick={() => setIsMobileLabMenuOpen(!isMobileLabMenuOpen)}
>
Лаборатории
<ChevronDown size={20} className={`transition-transform ${isMobileLabMenuOpen ? 'rotate-180' : ''}`} />
</button>
{isMobileLabMenuOpen && (
<div className="ml-4 mt-3 flex flex-col gap-3">
<Link
to="/laboratories/soil"
className="text-gray-400 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
Грунтовая лаборатория
</Link>
<Link
to="/laboratories/radiation"
className="text-gray-400 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
Радиационная лаборатория
</Link>
</div>
)}
</div>
{/* Контакты */}
<Link
to="/contacts"
className="text-lg font-medium text-gray-300 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
Контакты
</Link>
<Link
to="/contacts"
className="flex items-center gap-2 text-brand-orange font-bold mt-4"
onClick={() => setIsMobileMenuOpen(false)}
>
<Phone className="w-5 h-5" /> Связаться
</Link>
</div>
)}
</nav>
);
};
export default Navbar;
+37
View File
@@ -0,0 +1,37 @@
import React from 'react';
interface PageHeaderProps {
title: string;
description?: string;
image?: string;
}
const PageHeader: React.FC<PageHeaderProps> = ({
title,
description,
image = "/media/images/headers/header-about.png"
}) => {
return (
<div className="relative w-full h-[400px] md:h-[500px] bg-brand-dark text-white flex flex-col justify-center items-center text-center overflow-hidden">
<div className="absolute inset-0 z-0">
<img
src={image}
alt={title}
className="w-full h-full object-cover opacity-30"
/>
<div className="absolute inset-0 bg-gradient-to-b from-brand-dark/80 to-brand-dark/40" />
</div>
<div className="relative z-10 container mx-auto px-6 mt-16">
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold mb-6">{title}</h1>
{description && (
<p className="text-gray-300 text-lg max-w-2xl mx-auto leading-relaxed">
{description}
</p>
)}
</div>
</div>
);
};
export default PageHeader;
+40
View File
@@ -0,0 +1,40 @@
import React from 'react';
import { STEPS } from '../constants';
const Process: React.FC = () => {
return (
<div className="py-20 bg-brand-light">
<div className="container mx-auto px-6">
<h2 className="text-4xl font-bold text-gray-900 mb-16 text-center">Как мы работаем</h2>
<div className="relative max-w-6xl mx-auto">
{/* Линия связи между шагами (только на больших экранах) */}
<div className="hidden lg:block absolute top-9 left-0 right-0 h-1 bg-gradient-to-r from-brand-orange via-brand-orange/50 to-brand-orange" style={{ zIndex: 0 }} />
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 relative" style={{ zIndex: 1 }}>
{STEPS.map((step, idx) => (
<div key={idx} className="relative">
{/* Номер шага */}
<div className="absolute -top-4 -left-4 w-10 h-10 bg-brand-orange text-white rounded-full flex items-center justify-center font-bold text-lg shadow-lg z-10 border-4 border-brand-light">
{idx + 1}
</div>
{/* Карточка шага */}
<div className="bg-white rounded-2xl p-6 shadow-md hover:shadow-xl transition-all duration-300 hover:scale-105 h-full border-2 border-transparent hover:border-brand-orange">
<div className="w-14 h-14 rounded-full bg-brand-orange/20 flex items-center justify-center text-brand-orange mb-4">
<step.icon size={28} />
</div>
<p className="text-gray-700 leading-relaxed">
{step.description}
</p>
</div>
</div>
))}
</div>
</div>
</div>
</div>
);
};
export default Process;
+103
View File
@@ -0,0 +1,103 @@
import React, { useState } from 'react';
import { groupProjectsByCategory } from '../constants';
import { MapPin, ChevronDown } from 'lucide-react';
import { Link } from 'react-router-dom';
const Projects: React.FC = () => {
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">
Наши недавние проекты
</h2>
<p className="text-gray-600 max-w-md text-sm leading-relaxed">
Наша команда всегда ответственно относится к проектам, которые вы нам доверили.
Спасибо, что вы рядом.
</p>
</div>
<div className="space-y-4 mb-8">
{categories.map((category) => (
<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">{category.name}</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) => (
<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">
{project.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">{project.description}</span>
</div>
</div>
</div>
</div>
))}
</div>
</div>
</div>
))}
</div>
<div className="text-center">
<Link
to="/projects"
className="inline-block px-8 py-3 bg-brand-orange text-white font-bold rounded-lg hover:bg-orange-600 transition-colors"
>
Смотреть все проекты
</Link>
</div>
</div>
</div>
);
};
export default Projects;
+38
View File
@@ -0,0 +1,38 @@
import React, { useState, useEffect } from 'react';
import { ArrowUp } from 'lucide-react';
const ScrollToTop: React.FC = () => {
const [visible, setVisible] = useState(false);
useEffect(() => {
const onScroll = () => {
setVisible(window.scrollY > 300);
};
window.addEventListener('scroll', onScroll);
return () => window.removeEventListener('scroll', onScroll);
}, []);
const scrollToTop = () => {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
};
if (!visible) return null;
return (
<button
onClick={scrollToTop}
className="fixed bottom-8 right-8 w-14 h-14 bg-brand-orange rounded-full shadow-2xl hover:bg-orange-600 hover:scale-110 transition-all z-40 flex items-center justify-center group"
aria-label="Наверх"
>
<ArrowUp className="text-white group-hover:translate-y-[-2px] transition-transform" size={24} />
</button>
);
};
export default ScrollToTop;
+83
View File
@@ -0,0 +1,83 @@
import React from 'react';
import { ArrowRight } from 'lucide-react';
import { Link } from 'react-router-dom';
import { SERVICES } from '../constants';
const Services: React.FC = () => {
// Exclude Technical Tasks and show first 3 actual services
const actualServices = SERVICES.filter(service => service.title !== 'Технические задания');
const displayedServices = actualServices.slice(0, 3);
// Helper function to get service detail page URL
const getServiceUrl = (title: string) => {
const urlMap: { [key: string]: string } = {
'Инженерные изыскания': '/services/surveying',
'Проектирование': '/services/design',
'Строительство': '/services/construction',
'Обследование грунтов': '/services/soil-survey',
'Обследование здания': '/services/building-survey',
'Землестроительный и Кадастровые работы': '/services/land-survey'
};
return urlMap[title] || null;
};
return (
<div className="py-20 bg-gray-50" id="services">
<div className="container mx-auto px-6">
<div className="flex justify-between items-end mb-12">
<h2 className="text-4xl font-bold text-gray-900">Услуги</h2>
<Link to="/services" className="flex items-center gap-2 text-sm font-medium hover:text-brand-orange transition-colors">
Показать все <ArrowRight size={16} />
</Link>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{displayedServices.map((service, idx) => {
const detailUrl = getServiceUrl(service.title);
return (
<div
key={idx}
className="group relative h-[500px] rounded-2xl overflow-hidden cursor-pointer shadow-lg"
>
<img
src={service.image}
alt={service.title}
className="absolute inset-0 w-full h-full object-cover transition-transform duration-700 group-hover:scale-110"
loading="lazy"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/90 via-black/40 to-transparent" />
<div className="absolute bottom-0 left-0 p-8 w-full">
<h3 className="text-2xl font-bold text-white mb-3">{service.title}</h3>
<p className="text-gray-300 text-sm mb-6 line-clamp-3 opacity-90">
{service.description}
</p>
<div className="flex flex-col gap-3">
{detailUrl && (
<Link
to={detailUrl}
className="inline-flex items-center justify-center gap-2 bg-brand-orange text-white font-bold px-5 py-2.5 rounded-lg hover:bg-orange-600 transition-colors"
>
Подробнее <ArrowRight size={18} />
</Link>
)}
<Link
to="/contacts"
className="flex items-center gap-2 text-brand-orange text-sm font-medium group-hover:gap-4 transition-all"
>
Рассчитать стоимость <ArrowRight size={16} />
</Link>
</div>
</div>
</div>
);
})}
</div>
</div>
</div>
);
};
export default Services;
+270
View File
@@ -0,0 +1,270 @@
import { ShieldCheck, Users, HardHat, FileText, Phone, MessageSquare, Briefcase, DraftingCompass, Map, Zap, Calculator, Microscope, Home, Layers } from 'lucide-react';
import { BenefitItem, ProjectItem, ServiceItem, StatItem, StepItem, ProjectCategory } from './types';
export const NAV_LINKS = [
{ label: 'Главная', href: '/' },
{ label: 'О компании', href: '/about' },
{ label: 'Услуги', href: '/services' },
{ label: 'Проекты', href: '/projects' },
{ label: 'Автопарк', href: '/fleet' },
{ label: 'Сертификаты', href: '/certificates' },
{ label: 'Контакты', href: '/contacts' },
];
export const STATS: StatItem[] = [
{ value: '10+', label: '> 10-ти лет помогаем организациям в проектах любой сложности' },
{ value: '20+', label: '> 20-ти крупных компаний, которые нам доверяют' },
{ value: '30+', label: '> 30-ти успешно реализованных проектов за 3 года' },
];
export const BENEFITS: BenefitItem[] = [
{
icon: ShieldCheck,
title: 'Надежность',
description: 'Надежную компанию, которая входит в ТОП-3 по Республике Башкортостан'
},
{
icon: Users,
title: 'Опыт',
description: 'Лучших инженеров с 10-ти летним и более опытом работы'
},
{
icon: Phone,
title: 'Поддержка',
description: 'Связь и поддержку на всех этапах 24/7 с нашими специалистами'
},
{
icon: FileText,
title: 'Условия',
description: 'Индивидуальные предложения и условия сотрудничества'
},
];
export const SERVICES: ServiceItem[] = [
{
title: 'Технические задания',
description: 'Разработка и согласование грамотных технических заданий на проектирование, изыскания и строительство. Помощь в формулировании требований к объекту.',
image: '/media/images/services/technical-assignments.png'
},
{
title: 'Инженерные изыскания',
description: 'Комплексные исследования условий площадки строительства: инженерно-геодезические, геологические, гидрометеорологические и экологические изыскания.',
image: '/media/images/services/engineering-surveys.png'
},
{
title: 'Проектирование',
description: 'Разработка проектной и рабочей документации (ПД и РД) для объектов гражданского и промышленного назначения. Архитектурные и конструктивные решения.',
image: '/media/images/services/design.png'
},
{
title: 'Строительство',
description: 'Выполнение полного цикла строительно-монтажных работ. Возведение зданий, сооружений, ангаров, реконструкция и капитальный ремонт.',
image: '/media/images/services/construction.png'
},
{
title: 'Обследование грунтов',
description: 'Лабораторные и полевые испытания грунтов. Определение физико-механических свойств для расчета фундаментов и оснований.',
image: '/media/images/services/soil-survey.png'
},
{
title: 'Обследование здания',
description: 'Техническое обследование зданий и сооружений. Оценка состояния несущих конструкций, выявление дефектов и разработка рекомендаций по усилению.',
image: '/media/images/services/building-inspection.png'
},
{
title: 'Землестроительный и Кадастровые работы',
description: 'Межевание земельных участков, составление технических планов, актов обследования. Постановка недвижимости на государственный кадастровый учет.',
image: '/media/images/services/cadastral-works.png'
}
];
export const PROJECTS: ProjectItem[] = [
{ id: 1, title: 'ОАО «Газпромнефть-ОНПЗ»', description: '«Модернизация установки 19/3 ОАО «Газпромнефть-ОНПЗ» г. Омск»', image: 'https://placehold.co/600x400/94a3b8/white', category: 'Нефтегазовая промышленность' },
{ id: 2, title: 'ООО «Петон»', description: '«Л-24/9.Техническое перевооружение. Рекуперация тепла ГО ДТ (проектная и рабочая документация)» на территории ОАО «Газпромнефть-ОНПЗ».', image: 'https://placehold.co/600x400/94a3b8/white', category: 'Нефтегазовая промышленность' },
{ id: 3, title: 'ООО «ПроектТехнолоджи»', description: '«Капитальный ремонт системы отопления АБК (литер Ж) базы Южного эксплуатационного района по ул. Б. Гражданская, 47 Советского района г. Уфы и капитальный ремонт подпорной стенки с заменой ограждения на Центральной базе по адресу г. Уфа ул. Пархоменко, 157»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 4, title: 'ООО «ФРЕОН»', description: '«Строительство зоновой ВОЛС на участке: Уфа-отводы-2»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 5, title: 'ОАО «Гипротрубопровод»', description: '«Реконструкция производственной базы г. Омск»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 6, title: 'ООО «ИНЦЭБ»', description: '«Строительство ПС Кустаревская с трансформаторами 2*40 МВА (г.Уфа) (ПО УГЭС ООО «Башкирэнерго»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 7, title: 'ОАО «Уралтранснефтепродукт»', description: '«Переход МН ТОН-2(осн.нитка), через малый водоток р.Чумляк, 631.4 км. ДУ-700, ЛПДС «Медведское», Курганское НУ. Реконструкция»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 8, title: 'ООО «Лукойл-Уралнефтепродукт»', description: '«Реконструкция АЗС №02018 РБ. г. Туймазы, ул. С. Юлаева д.2»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 9, title: 'ООО ХК «Новолекс»', description: '«Лента», расположенный по адресу: г. Уфа, ул. Сипайловская»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 10, title: 'ООО «СУ-1 ОАО «Госстрой»', description: '«Ресторан быстрого обслуживания «KFC» на пересечении улиц Маршала Жукова и Академика Королева в Октябрьском районе ГО г.Уфа»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 11, title: 'ОАО «Юго - Запад транснефтепродукт»', description: '«Обустройство КЗ СОД (камера запуска) на ЛПДС «Журавлинская» МНПП «Уфа- Западное направление», Ду500»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 12, title: 'ООО «ГЕРАЛ»', description: '«Многоквартирный жилой дом в квартале ограниченном улицами Кузнецовский затон, Пугачева, рекой Уфа в Кировском районе ГО г. Уфа»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 13, title: 'ООО «Управление капитального строительства «Монолитстрой»', description: '«Группа многоэтажных жилых домов со встроено-пристроенными помещениями предприятий обслуживания населения, полуподземных автостоянок, здания ЖЭУ с административными помещениями и подземной автостоянкой, здания прачечной и химчистки с административными помещениями и подземной автостоянкой по ул. Дагестанской (микрорайон №9)в Демском районе городского округа г. Уфа, Республики Башкортостан, Жилой дом №13»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 14, title: 'ООО «ИНЦЭБ»', description: '«Строительство Бугульчанской солнечной электростанции»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 15, title: 'ООО «ИНЦЭБ»', description: '«Физкультурно-оздоровительный комплекс БРГИ № 1 имени Рами Гарипова в г. Уфа»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 16, title: 'НГДУ «Уфанефть» (ЦДНГ 4-7 скв., ЦДНГ 5-8 скв., ЦДНГ3- Блохинское)»', description: '«Организация индивидуалных замеров на добывающих скважинах, не охваченных замерными устройствами»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 17, title: 'ОАО «Гипровостокнефть»', description: '«ДНС с УПСВ «Графская» ООО Бугурусланнефть»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 18, title: 'ОАО Оренбургнефть, НГДУ «Сорочинскнефть»', description: '«Обустройство дополнительных скважин №№ 5112, 5216, 5217, 5218, 5219, 5220, 5222, 5225, 5227, 5229, 5230, 5231, 5233, 5234, 5235 Вахитовское месторождение»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 19, title: 'ООО «Башкирский птицеводческий комплекс имени М. Гафури»', description: '«Архитектурного объекта гражданского назначения «Административно-хозяйственного корпуса»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 20, title: 'ЗАО «ВолгоПромСтройМонтаж»', description: '«Строительство базовой станции БС 02-1298GU, цифровой сотовой системы связи стандарта GSM-900/1800/2100 в ОАО «МТС», Республике Башкортостан, Уфимский р-он., н/п Алкино. «Строительство базовой станции БС 02-1560GU, цифровой сотовой системы связи стандарта GSM-900/1800/2100 в ОАО «МТС», Республике Башкортостан, г. Ишимбай, п. Нефтяник. «Строительство базовой станции БС 02-1566G, цифровой сотовой системы связи стандарта GSM-900/1800/2100 в ОАО «МТС», Республике Башкортостан, Баймакский р-он., свх. Зилаирский «Строительство базовой станции БС 02-1567GU, цифровой сотовой системы связи стандарта GSM-900/1800/2100 в ОАО «МТС», Республике Башкортостан, Учалинский р-он., п. Комсомольский»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 21, title: 'ООО «СОЗАиТ»', description: '«Строительство производственного цеха в с. Серафимовский, в Туймазинском районе Республики Башкортостан»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 22, title: 'ЗАО «ВолгоПромСтройМонтаж»', description: '«Строительство базовой станции БС 02-1730, цифровой сотовой системы связи стандарта GSM-900/1800/2100 в ОАО «МТС», Республике Башкортостан, г.Октябрьский, ул. Партизанская»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 23, title: 'ОАО «Сибнефтепровод»', description: '«РВС- 20000 м3 №6 ЛПДС «Западный Сургут» Сургутское УМН. Реконструкция»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 24, title: 'ОАО «Институт Нефтепродуктпроект»', description: '«Обустройство КЗ СОД (камера запуска) на ЛПДС «Пенза» МНПП «Уфа - Западное направление», Ду500»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 25, title: 'ООО «БСК-Строй»', description: '«4-х складских помещений на территории завода филиала ООО «РСХ» в г. Уфа по ул. Производственная,10/1»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 26, title: 'ООО «Элеватор»', description: '«ООО «Маячный элеватор». в с. Маячный, ГО Кумертау, РБ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 27, title: 'ООО «Экосфера»', description: '-Комплекс для термического обезвреживания отходов КТО-150БУР.БМ в Восточно -Сибирском филиале ООО «РН-Бурение -Комплекс для термического обезвреживания отходов КТО-150БУР.БМ в Губкинском филиале ООО «РН-Бурение» -Комплекс для термического обезвреживания отходов КТО-150БУР.БМ в Иркутском филиале ООО «РН-Бурение»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 28, title: 'ОАО «Уфахимчистка»', description: '«Газопровод высокого давления с установкой ГРПШ к котельной ОАО «Уфахимчистка» по адресу ГО г.Уфа, ул. Новоженова 88а»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 29, title: 'ООО ПФ «Уралтрубопроводстройпроект»', description: '«Реконструкция промысловых трубопроводов Суазбашевского, Тепляковского, Арланского нефтяных месторождений»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 30, title: 'ООО «СУ-3 ОАО «Госстрой»', description: '«Группа блокированных жилых домов в п. Зинино»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 31, title: 'ОАО «Гипротрубопровод»', description: '«РВС 10000 м3 №1 ЛПДС «Каркатеевы» Нефтеюганская УМН. Реконструкция» «РВС 10000 м3 №10 ЛПДС «Каркатеевы» Нефтеюганская УМН. Реконструкция»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 32, title: 'ОАО «Оргнефтестрой»', description: '«Реконструкция участка МН «Куйбышев – Унеча – Мозырь-1» участок Лопатино- 114 км 10-58 км»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 33, title: 'ОАО «Сибнефтепровод»', description: '«РВС 20000 м3 №4 ЛПДС «Саматлор» Нижневартовское УМН. Реконструкция» «РВС 20000 м3 №10 ЛПДС «Саматлор» Нижневартовское УМН. Реконструкция»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 34, title: 'ОАО «Институт Нефтепродуктпроект»', description: '«Обустройство КП СОД (камера приема) на ЛПДС «Соседка» МНПП «Уфа- Западное направление», Ду500»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 35, title: 'Администрация сельского поселения Красноусольский сельский совет МР Гафурийский район, РБ', description: '«Строительство муниципального общественного кладбища в с.Красноусольский, РБ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 36, title: 'ООО «Регион-Ресурс»', description: '«Строительство центра экологического туризма в Кировском районе городского округа г. Уфа Республики Башкортостан»; - разработку Проектной документации в соответствии с требованиями Задания на проектирование и Технических регламентов; - разработку документации, необходимой для прохождения экспертиз и согласований в Государственных надзорных и контрольных службах; - участие в проведении государственной экспертизы Проектной документации, при возникновении необходимости ее проведения.»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 37, title: 'ООО «Новые молочные фермы Башкирии»', description: '«Строительства Молочно-товарного комплекса МТК на 12 110 стойломест и Генетического центра по воспроизводству молочного стада»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 38, title: 'ООО «МД финанс»', description: '«Блок обслуживания по Дуванскому бульвару в микрорайоне «Караидель» в Кировском районе города Уфа»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 39, title: 'ООО «Башнефтехим»', description: '«Строительство четырех железнодорожных путей на площадке «Г» ТСЦ НПЗ ОАО «Газпром нефтехим Салават»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 40, title: 'ООО «Управляющая компания «Альянс Менеджмент Компани»', description: '«Проект перепланировки и внешнего оформления фасада здания, расположенного по адресу: ул. Рижская, д.1 в Ленинском районе г. Уфы»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 41, title: 'МБУ «Управление пожарной охраны ГО г. Уфа Республики Башкортостан', description: '«Здание пожарного депо на 4 выезда по адресу: Ленинский район, п. 8 Марта, РБ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 42, title: 'ООО «Альтернатива»', description: '«Разработка проекта планировки и проекта межевания территории, ограниченной улицами Охотников, Пограничников, Рыбацкой и переулком Удачным в Калининском районе ГО г. Уфа, РБ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 43, title: 'ООО «Башнефтехим»', description: '«Монтаж противопожарного водопровода вдоль проезда №9 между проездами №8 и №10 с подключением КПА, Филиал ОАО АНК «Башнефть» «Башнефть-Уфанефтехим», РБ, г. Уфа»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 44, title: 'ООО «Башнефтехим»', description: '«Внешнее газоснабжение объекта Строительство ПГУ-410Т» промзона г. Салават»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 45, title: 'ООО «Уфанефтемаш»', description: '«Здание дополнительного цеха металлоконструкций по ул. Новая- 3 в д. Мокроусово ГО Уфы»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 46, title: 'ООО ПФ «Уралтрубопроводстройпроект»', description: '«Реконструкция и техническое перевооружение объектов Уренгойского ЗПКТ для переработки конденсата Ачимовских залежей Уренгойского месторождения»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 47, title: 'ООО ПФ «Уралтрубопроводстройпроект»', description: '«Узел отвода противотурбулентной присадки в МК «Уренгой-Сургут»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 48, title: 'ООО ПФ «Уралтрубопроводстройпроект»', description: '«Автоматизированная система пожаротушения и контроля загазованности технологических объектов Уренгойского ЗПКТ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 49, title: 'ООО «Авиапромышленная лизинговая компания»', description: '«Турбаза отдыха «Ясная поляна, г. Уфа, Кировский р-н в районе мелькомбината на левом берегу р. Белой Республики Башкортостан»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 50, title: 'ООО «ЮжноУральскийТехСервис»', description: '«Ст. Злобина 17, Советского района, г. Уфа Республики Башкортостан»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 51, title: 'ООО «Управление капитального строительства «Монолитстрой»', description: '«Административно-торговый развлекательный комплекс в мкр. «Дема-9» в Демском районе ГО г. Уфа, РБ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 52, title: 'ОАО «Уфимский хлопчатобумажный комбинат»', description: '«Колесо обозрения-58 на территории ОАО "Уфимский хлопчатобумажный комбинат" по адресу: г. Уфа, ул. Менделеева, 137»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 53, title: 'ООО «Альфа Проект Уфа»', description: '«Расширение системы газоснабжения п. Нарышево. Строительство кольцующего газопровода высокого и низкого давления по ул. Кооперативная г. Октябрьский с установкой ГРПШ и перекладкой четной стороны д. 57, д. 159. РБ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 54, title: 'ЗАО «Штрабаг»', description: '«Технопарк энергоэффективных технологий на земельном участке в административных границах муниципального района Уфимского района Республики Башкортостан»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 55, title: 'МБОУ СОШ №4 с. Раевский', description: '«Строительство автономной блочной котельной для теплоснабжения МБОУ СОШ №4с. Раевский МР Альшеевский район Республики Башкортостан»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 56, title: 'ООО Инженерный центр «Техпроект»', description: '«Строительство ЛЭП ВЛ-10/0.4 в микрорайоне «Базал» с. Старосубхангулово Бурзянского района Республики Башкортостан»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 57, title: 'ООО «Вектор»', description: '«Реконструкция корп. №17, лит. Ж1, по адресу: г. Уфа, ул. 50 лет СССР д.30»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 58, title: 'МБДОУ детский сад №7 с. Раевский', description: '«Строительство автономной блочной котельной для теплоснабжения МБДОУ детский сад №7 с. Раевский МР Альшеевский район Республики Башкортостан»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 59, title: 'ООО «Уральский экологический научно-производственный институт»', description: '«Строительство социального многоквартирного жилого дома по ул. Вострецова, 7/1 в Калининском районе г. Уфы»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 60, title: 'ООО ПФ «Уралтрубопроводстройпроект»', description: '«Капитальный ремонт трубопроводов ЦДНГ-5,8 (2013г.) (Рассветное, Баклановское месторождение)»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 61, title: 'ООО Инженерный центр «Техпроект»', description: '«Строительство новых и реконструкция действующих сетей и сооружений системы водоснабжения р.ц. Старобалтачево муниципального района Балтачевский район Республики Башкортостан»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 62, title: 'ООО «ПромСтрой»', description: '«Реконструкция автомобильной дороги М-7 "Волга" от Москвы через Владимир, Нижний Новгород, Казань до Уфы на участке км 1270+010 – км 1290+838, Республика Башкортостан (II пусковой комплекс)»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 63, title: 'ООО «Промтехстрой»', description: '«Строительство административно-складского здания расположенного по адресу: Республика Башкортостан, г.Уфа, ул. Ростовская, д. 18»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 64, title: 'ООО «Уралстройсервис»', description: '«Подземный гараж с помещениями обслуживания населения на кровле по ул. Российская у пересечения с бульваром Давлеткильдеева в Октябрьском районе городского округа город Уфа РБ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 65, title: 'ООО ПФ «Уралтрубопроводстройпроект»', description: '«Реконструкция склада ЗПКТ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 66, title: 'ООО ПФ «Уралтрубопроводстройпроект»', description: '«Реконструкция систем общезаводского хозяйства Уренгойского ЗПКТ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 67, title: 'ООО ПФ «Уралтрубопроводстройпроект»', description: '«Реконструкция резервуарных парков Уренгойского ЗПКТ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 68, title: 'ООО ПФ «Уралтрубопроводстройпроект»', description: '«Реконструкция установки получения дизельного топлива Уренгойского ЗПКТ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 69, title: 'ООО ПФ «Уралтрубопроводстройпроект»', description: '«Реконструкция установки получения пропан-бутана Уренгойского ЗПКТ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 70, title: 'ООО ПФ «Уралтрубопроводстройпроект»', description: '«Реконструкция установки стабилизации конденсата 1 Уренгойского ЗПКТ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 71, title: 'ООО "ЛУКОЙЛ-ПЕРМЬ"', description: '«Модернизация нефтенасосной станции внешнего транспорта на ПСП "Чернушка"»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 72, title: 'ОАО «Новокуйбышевский нефтеперерабатывающий завод»', description: '«Система измерений количества и показателей качества нефти №1 на входе установки АВТ-11»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 73, title: 'ОАО «Новокуйбышевский нефтеперерабатывающий завод»', description: '«Система измерений количества и показателей качества нефти №2 на входе установки АВТ-11»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 74, title: 'ОАО «Новокуйбышевский нефтеперерабатывающий завод»', description: '«Система измерений количества и показателей качества нефти №3 на входе установки АВТ-11»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 75, title: 'ООО Инженерный центр «ТехПроект»', description: '«Капитальный ремонт ГТС водохранилища на р. Кара-Зирик в с. Верхнеяркеево МР Илишевский район РБ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 76, title: 'ООО Инженерный центр «ТехПроект»', description: '«Капитальный ремонт ГТС пруда на р. Агардинка у с. Агарды МР Благоварский район РБ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 77, title: 'ООО «БСК-Строй»', description: '«4-х складских помещений на территории завода филиала ООО «РСХ» в г. Уфа по ул. Производственная,10/1»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 78, title: 'ООО «РТЗ»', description: '«Проектируемая крановая эстакада. г. Давлеканово, ул. Уральская 89»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 79, title: 'ООО «Блочные котельные»', description: '«Блочно-модульная котельная ОАО «БСК» П/П «2 цех Рассолпромысел»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 80, title: '«Специализированный инвестиционно-потребительский жилищно-строительный кооператив «Благовещенский»', description: '«Жилой дом №2 в микрорайоне №8 г. Благовещенск РБ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 81, title: 'ООО Инженерный центр «Техпроект»', description: '«Строительство резервного водовода в с. Павловка МР Нуримановский район РБ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 82, title: 'ФУ Администрация МР Калтасинский район', description: '«Строительство 12 - квартирного жилого дома в с. Краснохолмский Калтасинского района РБ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 83, title: 'ЗАО ПИИ «Роспроект»', description: '«Реконструкция сельского дома культуры в с . Темясово»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 84, title: 'ООО «ПромБытГазпроект»', description: '«Капитальный ремонт производственной базы Архангельской РЭС» по адресу РБ, Архангельский район, с. Архангельское, ул. Чкалова, 53а, филиала «Центргаз» ОАО «Газсервис»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 85, title: 'ООО «ПромБытГазпроект»', description: '«Блочная газовая котельная МБОУ СОШ в с. Красный ключ Нуримановского района Республики Башкортостан»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 86, title: 'ООО «ПромБытГазпроект»', description: '«Металлический склад г. Кумертау, Республика Башкортостан»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 87, title: 'ООО «РаушБиер»', description: '«Двухэтажный ресторанный комплекс, расположенный по адресу: Республика Башкортостан, г.Туймазы, ул. Тукаева, д. 8»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 88, title: 'ООО «Региональная строительная компания»', description: '«Пристрой к зданию школы по адресу РБ, Янаульский р-н, с.Истяк, ул. Школьная 1а»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 89, title: 'ООО СМУ «Уралстройсервис»', description: '«Строительство 12 - квартирного жилого дома в с. Краснохолмский Калтасинского района РБ»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 90, title: 'ООО СОК «Трамплин»', description: '«Бугельный подъемник в Октябрьском районе, г. Уфа Республика Башкортостан»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 91, title: 'ООО «Уфанефтемаш»', description: '«Здание дополнительного цеха металлоконструкций по ул. Новая-3, в д. Мокроусово ГО Уфы»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 92, title: 'ООО "Фирма РОССИ"', description: '«Площадка хранения баллонов сжиженных газов на территории ООО «Русджам-Холдинг» в г. Уфе»', image: 'https://placehold.co/600x400/94a3b8/white' },
{ id: 93, title: 'Администрация сельского поселения Зубовский сельсовет Муниципального Района Уфимский район РБ', description: 'Строительство газопровода высокого давления, низкого давления и ПГБ для газоснабжения жилых домов по ул. Снежная в с. Зубово, ул.Центральная в с.Нижегородка Уфимского района РБ', image: 'https://placehold.co/600x400/94a3b8/white' }
];
// Функция для определения категории проекта
function categorizeProject(project: ProjectItem): string {
const text = (project.title + ' ' + project.description).toLowerCase();
if (text.includes('нефт') || text.includes('газ') || text.includes('рвс') ||
text.includes('лпдс') || text.includes('трубопровод') || text.includes('зпкт') ||
text.includes('скваж') || text.includes('нгду') || text.includes('конденсат')) {
return 'Нефтегазовая промышленность';
}
if (text.includes('жилой дом') || text.includes('жилых дом') || text.includes('жк') ||
text.includes('квартир') || text.includes('жэу')) {
return 'Жилищное строительство';
}
if (text.includes('газопровод') || text.includes('водопровод') || text.includes('водовод') ||
text.includes('электр') || text.includes('лэп') || text.includes('дорог') ||
text.includes('волс') || text.includes('связь') || text.includes('водоснабжен') ||
text.includes('гтс')) {
return 'Инфраструктура и коммуникации';
}
if (text.includes('школ') || text.includes('детский сад') || text.includes('культур') ||
text.includes('спорт') || text.includes('физкультурно') || text.includes('брги') ||
text.includes('мбоу') || text.includes('мбдоу') || text.includes('кладбищ')) {
return 'Социальные объекты';
}
if (text.includes('склад') || text.includes('цех') || text.includes('завод') ||
text.includes('производств') || text.includes('промышлен') || text.includes('элеватор') ||
text.includes('котельн') || text.includes('эстакад') || text.includes('база')) {
return 'Промышленные и складские объекты';
}
if (text.includes('ресторан') || text.includes('kfc') || text.includes('азс') ||
text.includes('торгов') || text.includes('администрат') || text.includes('офис') ||
text.includes('турбаза') || text.includes('туризм') || text.includes('развлекательн') ||
text.includes('колесо обозрения') || text.includes('технопарк') || text.includes('депо') ||
text.includes('гараж') || text.includes('подъемник')) {
return 'Коммерческая недвижимость и туризм';
}
return 'Прочие объекты';
}
// Группировка проектов по категориям
export function groupProjectsByCategory(): ProjectCategory[] {
const categories: { [key: string]: ProjectItem[] } = {};
PROJECTS.forEach(project => {
const category = categorizeProject(project);
if (!categories[category]) {
categories[category] = [];
}
categories[category].push(project);
});
return Object.entries(categories)
.map(([name, projects]) => ({ name, projects }))
.sort((a, b) => b.projects.length - a.projects.length);
}
export const STEPS: StepItem[] = [
{
icon: Phone,
title: 'Звонок',
description: 'Связываемся с клиентом и уточняем все детали, далее определяем цену'
},
{
icon: FileText,
title: 'ТЗ',
description: 'Составляем техническое задание для наших специалистов'
},
{
icon: Briefcase,
title: 'Договор',
description: 'Подготавливаем все необходимые документы и заключаем договор'
},
{
icon: HardHat,
title: 'Работа',
description: 'Выполняем работу на участке, испытываем отобранные образцы'
},
{
icon: DraftingCompass,
title: 'Отчет',
description: 'Разрабатываем технический отчет и передаем пакет документов'
},
{
icon: MessageSquare,
title: 'Финал',
description: 'Презентуем отчет и даем рекомендации'
}
];
+86
View File
@@ -0,0 +1,86 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', sans-serif;
}
/* Плавная прокрутка для миниатюр карусели */
.overflow-x-auto {
scrollbar-width: thin;
scrollbar-color: #FF9900 #f5f5f5;
}
.overflow-x-auto::-webkit-scrollbar {
height: 8px;
}
.overflow-x-auto::-webkit-scrollbar-track {
background: #f5f5f5;
border-radius: 10px;
}
.overflow-x-auto::-webkit-scrollbar-thumb {
background: #FF9900;
border-radius: 10px;
}
.overflow-x-auto::-webkit-scrollbar-thumb:hover {
background: #e68a00;
}
/* Обрезка текста */
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
/* Скрытие скроллбара для каруселей */
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
/* Градиентная анимация для Hero */
@keyframes gradient-shift {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
.animate-gradient {
background-size: 200% 200%;
animation: gradient-shift 8s ease infinite;
}
/* Плавное появление элементов */
@keyframes fade-in-up {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.animate-fade-in-up {
animation: fade-in-up 0.6s ease-out forwards;
}
+103
View File
@@ -0,0 +1,103 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ГеоВектор - Проектирование и Строительство</title>
<!-- Favicon -->
<link rel="icon" type="image/webp" href="/media/geo-logo.webp" />
<link rel="shortcut icon" type="image/webp" href="/media/geo-logo.webp" />
<link rel="apple-touch-icon" href="/media/geo-logo.webp" />
<!-- Meta tags -->
<meta name="description" content="ООО ГеоВектор - профессиональные инженерные изыскания, проектирование и строительство в Уфе. Современное оборудование, опытные специалисты." />
<meta name="keywords" content="инженерные изыскания, проектирование, строительство, геология, геодезия, ГеоВектор, Уфа" />
<!-- Open Graph для соцсетей -->
<meta property="og:title" content="ГеоВектор - Инженерные изыскания, проектирование и строительство" />
<meta property="og:description" content="Профессиональные инженерные изыскания, проектирование и строительство в Уфе. Современное оборудование, опытные специалисты." />
<meta property="og:image" content="https://geowektor.ru/media/geo-logo.webp" />
<meta property="og:url" content="https://geowektor.ru" />
<meta property="og:type" content="website" />
<meta property="og:locale" content="ru_RU" />
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="ГеоВектор - Инженерные изыскания и строительство" />
<meta name="twitter:description" content="Профессиональные решения для строительства в Уфе" />
<meta name="twitter:image" content="https://geowektor.ru/media/geo-logo.webp" />
<!-- Schema.org разметка -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "ООО ГеоВектор",
"alternateName": "GeoVector",
"url": "https://geowektor.ru",
"logo": "https://geowektor.ru/media/geo-logo.webp",
"contactPoint": {
"@type": "ContactPoint",
"telephone": "+7-347-292-73-70",
"contactType": "customer service",
"areaServed": "RU",
"availableLanguage": ["Russian"]
},
"address": {
"@type": "PostalAddress",
"streetAddress": "ул. Комсомольская 19/1",
"addressLocality": "Уфа",
"addressRegion": "Республика Башкортостан",
"postalCode": "450001",
"addressCountry": "RU"
},
"sameAs": [
"https://t.me/ooo_geo_wektor",
"https://vk.com/geowektor_ru"
],
"description": "Профессиональные инженерные изыскания, проектирование и строительство. Грунтовая и радиационная лаборатории."
}
</script>
<script src="js/tailwind.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: {
sans: ['Inter', 'sans-serif'],
},
colors: {
brand: {
orange: '#FF9900',
dark: '#111111',
gray: '#222222',
light: '#F5F5F5'
}
}
}
}
}
</script>
<script type="importmap">
{
"imports": {
"lucide-react": "https://aistudiocdn.com/lucide-react@^0.555.0",
"react/": "https://aistudiocdn.com/react@^19.2.0/",
"react": "https://aistudiocdn.com/react@^19.2.0",
"react-dom/": "https://aistudiocdn.com/react-dom@^19.2.0/",
"react-router-dom": "https://aistudiocdn.com/react-router-dom@^6.22.3",
"react-router": "https://aistudiocdn.com/react-router@^6.22.3",
"@remix-run/router": "https://aistudiocdn.com/@remix-run/router@^1.15.3"
}
}
</script>
<link rel="stylesheet" href="/index.css">
</head>
<body>
<div id="root"></div>
<script type="module" src="/index.tsx"></script>
</body>
</html>
+19
View File
@@ -0,0 +1,19 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { registerServiceWorker } from './registerSW';
const rootElement = document.getElementById('root');
if (!rootElement) {
throw new Error("Could not find root element to mount to");
}
const root = ReactDOM.createRoot(rootElement);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// Регистрируем Service Worker
registerServiceWorker();
+64
View File
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

+5
View File
@@ -0,0 +1,5 @@
{
"name": "GeoVector Construction",
"description": "Corporate website for GeoVector, a construction and engineering firm, featuring services, projects, and contact forms.",
"requestFramePermissions": []
}
+1902
View File
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More