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
This commit is contained in:
2026-03-13 19:41:07 +05:00
parent 575db0ac53
commit fde9609f9a
26 changed files with 1753 additions and 735 deletions

View File

@@ -1,8 +1,13 @@
import React from 'react';
import PageHeader from '../components/PageHeader';
import { CheckCircle2, MapPin, Mountain, Leaf, Cloud, Wrench, Award } from 'lucide-react';
import { useLocation } from 'react-router-dom';
const SurveyingPage: React.FC = () => {
const location = useLocation();
const isEnglish = location.pathname.startsWith('/en');
const prefix = isEnglish ? '/en' : '';
const surveyTypes = [
{
icon: MapPin,
@@ -70,25 +75,90 @@ const SurveyingPage: React.FC = () => {
];
const pricing = [
{ service: 'Инженерные изыскания под коттедж (геология+геодезия)', price: 'от 25000 ₽' },
{ service: 'Инженерно-геологические изыскания для строительства', price: 'от 500 ₽ / м.' },
{ service: 'Инженерно-геологические изыскания с экспертизой', price: 'от 500 ₽ / м.' },
{ service: 'Геологические изыскания (особо крупные объекты)', price: 'от 300 ₽ / м.' },
{ service: 'Геологические изыскания под коттедж', price: 'от 15000 ₽' },
{ service: 'Инженерно-геодезические изыскания для строительства', price: 'от 5000 ₽' },
{ service: 'Геоподоснова (топоплан с коммуникациями)', price: 'от 10000 ₽' },
{ service: 'Геодезические изыскания под коттедж (топосъемка)', price: 'от 5000 ₽' },
{ service: 'Определение границ, координатная привязка', price: 'от 2000 ₽' },
{ service: 'Разбивка осей, реперы, сопровождение строительства', price: 'от 2000 ₽' },
{ service: 'Инженерно-экологические изыскания', price: 'от 8000 ₽' },
{ service: 'Инженерные изыскания (комплекс работ)', price: '10% скидка', highlight: true }
{
service: isEnglish
? 'Engineering surveys for a cottage (geology + geodesy)'
: 'Инженерные изыскания под коттедж (геология+геодезия)',
price: isEnglish ? 'from 25 000 ₽' : 'от 25000 ₽',
},
{
service: isEnglish
? 'Engineering-geological surveys for construction'
: 'Инженерно-геологические изыскания для строительства',
price: isEnglish ? 'from 500 ₽ / m' : 'от 500 ₽ / м.',
},
{
service: isEnglish
? 'Engineering-geological surveys with expert review'
: 'Инженерно-геологические изыскания с экспертизой',
price: isEnglish ? 'from 500 ₽ / m' : 'от 500 ₽ / м.',
},
{
service: isEnglish
? 'Geological surveys (large-scale facilities)'
: 'Геологические изыскания (особо крупные объекты)',
price: isEnglish ? 'from 300 ₽ / m' : 'от 300 ₽ / м.',
},
{
service: isEnglish
? 'Geological surveys for a cottage'
: 'Геологические изыскания под коттедж',
price: isEnglish ? 'from 15 000 ₽' : 'от 15000 ₽',
},
{
service: isEnglish
? 'Engineering-geodetic surveys for construction'
: 'Инженерно-геодезические изыскания для строительства',
price: isEnglish ? 'from 5 000 ₽' : 'от 5000 ₽',
},
{
service: isEnglish
? 'Geodetic base plan (topographic plan with utilities)'
: 'Геоподоснова (топоплан с коммуникациями)',
price: isEnglish ? 'from 10 000 ₽' : 'от 10000 ₽',
},
{
service: isEnglish
? 'Geodetic surveys for a cottage (topographic survey)'
: 'Геодезические изыскания под коттедж (топосъемка)',
price: isEnglish ? 'from 5 000 ₽' : 'от 5000 ₽',
},
{
service: isEnglish
? 'Boundary identification and coordinate referencing'
: 'Определение границ, координатная привязка',
price: isEnglish ? 'from 2 000 ₽' : 'от 2000 ₽',
},
{
service: isEnglish
? 'Axis layout, benchmarks, construction support'
: 'Разбивка осей, реперы, сопровождение строительства',
price: isEnglish ? 'from 2 000 ₽' : 'от 2000 ₽',
},
{
service: isEnglish
? 'Engineering-environmental surveys'
: 'Инженерно-экологические изыскания',
price: isEnglish ? 'from 8 000 ₽' : 'от 8000 ₽',
},
{
service: isEnglish
? 'Engineering surveys (full scope)'
: 'Инженерные изыскания (комплекс работ)',
price: isEnglish ? '10% discount' : '10% скидка',
highlight: true,
},
];
return (
<div className="bg-white pb-20">
<PageHeader
title="Инженерные изыскания"
description="Комплекс мероприятий для сбора и анализа детальной информации о территории строительства"
title={isEnglish ? 'Engineering surveys' : 'Инженерные изыскания'}
description={
isEnglish
? 'A full set of activities for collecting and analysing detailed information about the construction site.'
: 'Комплекс мероприятий для сбора и анализа детальной информации о территории строительства'
}
image="/media/images/headers/header-injinernie-iziskania.png"
/>
@@ -97,24 +167,33 @@ const SurveyingPage: React.FC = () => {
<div className="max-w-5xl mx-auto mb-20">
<div className="bg-gray-50 rounded-2xl p-8 md:p-12 mb-12">
<p className="text-lg text-gray-700 leading-relaxed mb-6">
<strong>Инженерные изыскания для выполнения строительства</strong> комплекс мероприятий,
направленных на сбор и анализ детальной информации о техногенных и природных условиях территории
для будущего строительства. Полученные данные входят в состав обязательной документации для
разработки проекта и проведения строительных работ.
{isEnglish ? (
<>
<strong>Engineering surveys for construction</strong> are a set of activities aimed at collecting
and analysing detailed information about the natural and man-made conditions of the site.
The resulting data form part of the mandatory documentation for design and construction.
</>
) : (
<>
<strong>Инженерные изыскания для выполнения строительства</strong> комплекс мероприятий,
направленных на сбор и анализ детальной информации о техногенных и природных условиях территории
для будущего строительства. Полученные данные входят в состав обязательной документации для
разработки проекта и проведения строительных работ.
</>
)}
</p>
<p className="text-gray-600 leading-relaxed">
Необходимость проведения определенных видов изысканий, их объем и состав определяются после анализа
технического задания и зависят от вида, уровня ответственности, назначения сооружений, стадии
проектирования, условий участка и степени их изученности.
{isEnglish
? 'The required types and scope of surveys are determined after analysing the technical assignment and depend on the type and responsibility level of the structures, design stage and the conditions and degree of study of the site.'
: 'Необходимость проведения определенных видов изысканий, их объем и состав определяются после анализа технического задания и зависят от вида, уровня ответственности, назначения сооружений, стадии проектирования, условий участка и степени их изученности.'}
</p>
</div>
<div className="bg-brand-orange text-white rounded-2xl p-8 md:p-12">
<p className="text-lg leading-relaxed">
Проведение инженерных изысканий подразумевает анализ данных, оценку возможных последствий реализации
проекта, получение санитарно-эпидемиологических заключений и составление технических отчетов, состав
которых определяется действующими нормативными документами. Наши специалисты профессионально выполняют
изыскания для строящихся или реконструируемых объектов любых типов.
{isEnglish
? 'Engineering surveys include data analysis, assessment of possible consequences of the project implementation, obtaining sanitary and epidemiological conclusions and preparing technical reports in accordance with current regulations. Our specialists carry out surveys for new construction and reconstruction projects of any type.'
: 'Проведение инженерных изысканий подразумевает анализ данных, оценку возможных последствий реализации проекта, получение санитарно-эпидемиологических заключений и составление технических отчетов, состав которых определяется действующими нормативными документами. Наши специалисты профессионально выполняют изыскания для строящихся или реконструируемых объектов любых типов.'}
</p>
</div>
</div>
@@ -122,7 +201,9 @@ const SurveyingPage: React.FC = () => {
{/* Типы изысканий */}
<div className="max-w-6xl mx-auto mb-20">
<h2 className="text-3xl font-bold text-gray-900 mb-12 text-center">
Мы выполняем следующие типы инженерных изысканий
{isEnglish
? 'We carry out the following types of engineering surveys'
: 'Мы выполняем следующие типы инженерных изысканий'}
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
@@ -149,27 +230,43 @@ const SurveyingPage: React.FC = () => {
{/* Допуски к работам */}
<div className="max-w-6xl mx-auto mb-20">
<div className="text-center mb-12">
<div className="inline-flex items-center gap-3 bg-brand-orange text-white px-8 py-4 rounded-full mb-6">
<Award size={32} />
<span className="text-xl font-bold">ООО ГЕОВЕКТОР ИМЕЕТ ДОПУСК К СЛЕДУЮЩИМ ВИДАМ РАБОТ</span>
<div className="text-center mb-12">
<div className="inline-flex items-center gap-3 bg-brand-orange text-white px-8 py-4 rounded-full mb-6">
<Award size={32} />
<span className="text-xl font-bold">
{isEnglish
? 'GeoVector LLC is certified to perform the following types of work'
: 'ООО ГЕОВЕКТОР ИМЕЕТ ДОПУСК К СЛЕДУЮЩИМ ВИДАМ РАБОТ'}
</span>
</div>
</div>
</div>
<div className="space-y-12">
{/* Инженерно-геодезические */}
<div className="bg-gray-50 rounded-2xl p-8">
<h3 className="text-2xl font-bold text-gray-900 mb-6 flex items-center gap-3">
<div className="w-2 h-8 bg-brand-orange rounded"></div>
Инженерно-геодезические изыскания
{isEnglish ? 'Engineering and geodetic surveys' : 'Инженерно-геодезические изыскания'}
</h3>
<ul className="space-y-3">
{geodesicWorks.map((work, index) => (
<li key={index} className="flex items-start gap-3">
<CheckCircle2 className="flex-shrink-0 text-brand-orange mt-1" size={20} />
<span className="text-gray-700">{work}</span>
</li>
))}
{geodesicWorks.map((work, index) => {
const text = isEnglish
? [
'Establishment of control geodetic networks.',
'Geodetic monitoring of deformations and settlements of buildings and structures, ground surface displacements and hazardous natural processes.',
'Creation and updating of engineering topographic plans at scales 1:2001:5000, including digital form, surveying of underground utilities and structures.',
'Route setting-out for linear facilities.',
'Engineering hydrographic works.',
'Special geodetic and topographic works during construction and reconstruction of buildings and structures.',
][index] || work
: work;
return (
<li key={index} className="flex items-start gap-3">
<CheckCircle2 className="flex-shrink-0 text-brand-orange mt-1" size={20} />
<span className="text-gray-700">{text}</span>
</li>
);
})}
</ul>
</div>
@@ -177,15 +274,28 @@ const SurveyingPage: React.FC = () => {
<div className="bg-gray-50 rounded-2xl p-8">
<h3 className="text-2xl font-bold text-gray-900 mb-6 flex items-center gap-3">
<div className="w-2 h-8 bg-brand-orange rounded"></div>
Инженерно-геологические изыскания
{isEnglish ? 'Engineering and geological surveys' : 'Инженерно-геологические изыскания'}
</h3>
<ul className="space-y-3">
{geologicalWorks.map((work, index) => (
<li key={index} className="flex items-start gap-3">
<CheckCircle2 className="flex-shrink-0 text-brand-orange mt-1" size={20} />
<span className="text-gray-700">{work}</span>
</li>
))}
{geologicalWorks.map((work, index) => {
const text = isEnglish
? [
'Engineeringgeological mapping at scales 1:5001:25 000.',
'Drilling of exploratory boreholes with sampling and laboratory testing of soil physicalmechanical properties and groundwater chemistry.',
'Study of hazardous geological and engineeringgeological processes with recommendations for engineering protection of the territory.',
'Hydrogeological investigations.',
'Engineeringgeophysical investigations.',
'Engineeringgeocryological investigations.',
'Seismological and seismotectonic investigations, seismic microzoning of the territory.',
][index] || work
: work;
return (
<li key={index} className="flex items-start gap-3">
<CheckCircle2 className="flex-shrink-0 text-brand-orange mt-1" size={20} />
<span className="text-gray-700">{text}</span>
</li>
);
})}
</ul>
</div>
@@ -193,15 +303,26 @@ const SurveyingPage: React.FC = () => {
<div className="bg-gray-50 rounded-2xl p-8">
<h3 className="text-2xl font-bold text-gray-900 mb-6 flex items-center gap-3">
<div className="w-2 h-8 bg-brand-orange rounded"></div>
Инженерно-экологические изыскания
{isEnglish ? 'Engineering and environmental surveys' : 'Инженерно-экологические изыскания'}
</h3>
<ul className="space-y-3">
{ecologicalWorks.map((work, index) => (
<li key={index} className="flex items-start gap-3">
<CheckCircle2 className="flex-shrink-0 text-brand-orange mt-1" size={20} />
<span className="text-gray-700">{work}</span>
</li>
))}
{ecologicalWorks.map((work, index) => {
const text = isEnglish
? [
'Engineeringenvironmental mapping of the territory.',
'Investigation of chemical contamination of soils, surface and groundwater, air and pollution sources.',
'Laboratory chemicalanalytical and gaschemical testing of soil and water samples.',
'Study and assessment of physical impacts and radiation conditions across the territory.',
'Study of vegetation and wildlife, sanitaryepidemiological and biomedical investigations of the area.',
][index] || work
: work;
return (
<li key={index} className="flex items-start gap-3">
<CheckCircle2 className="flex-shrink-0 text-brand-orange mt-1" size={20} />
<span className="text-gray-700">{text}</span>
</li>
);
})}
</ul>
</div>
@@ -209,15 +330,25 @@ const SurveyingPage: React.FC = () => {
<div className="bg-gray-50 rounded-2xl p-8">
<h3 className="text-2xl font-bold text-gray-900 mb-6 flex items-center gap-3">
<div className="w-2 h-8 bg-brand-orange rounded"></div>
Инженерно-гидрометеорологические изыскания
{isEnglish ? 'Engineering and hydrometeorological surveys' : 'Инженерно-гидрометеорологические изыскания'}
</h3>
<ul className="space-y-3">
{hydrometeorologicalWorks.map((work, index) => (
<li key={index} className="flex items-start gap-3">
<CheckCircle2 className="flex-shrink-0 text-brand-orange mt-1" size={20} />
<span className="text-gray-700">{work}</span>
</li>
))}
{hydrometeorologicalWorks.map((work, index) => {
const text = isEnglish
? [
'Meteorological observations and study of the hydrological regime of water bodies.',
'Analysis of hazardous hydrometeorological processes and phenomena with calculation of their characteristics.',
'Study of channel processes in watercourses, bank deformation and erosion.',
'Investigation of ice regime in water bodies.',
][index] || work
: work;
return (
<li key={index} className="flex items-start gap-3">
<CheckCircle2 className="flex-shrink-0 text-brand-orange mt-1" size={20} />
<span className="text-gray-700">{text}</span>
</li>
);
})}
</ul>
</div>
@@ -225,19 +356,32 @@ const SurveyingPage: React.FC = () => {
<div className="bg-gray-50 rounded-2xl p-8">
<h3 className="text-2xl font-bold text-gray-900 mb-6 flex items-center gap-3">
<div className="w-2 h-8 bg-brand-orange rounded"></div>
Инженерно-геотехнические изыскания
{isEnglish ? 'Engineering and geotechnical surveys' : 'Инженерно-геотехнические изыскания'}
</h3>
<p className="text-sm text-gray-600 italic mb-6">
(Выполняются в составе инженерно-геологических изысканий или отдельно на изученной
в инженерно-геологическом отношении территории под отдельные здания и сооружения).
{isEnglish
? 'Performed as part of engineering and geological surveys or separately on sites that have already been investigated from an engineering-geological perspective.'
: '(Выполняются в составе инженерно-геологических изысканий или отдельно на изученной в инженерно-геологическом отношении территории под отдельные здания и сооружения).'}
</p>
<ul className="space-y-3">
{geotechnicalWorks.map((work, index) => (
<li key={index} className="flex items-start gap-3">
<CheckCircle2 className="flex-shrink-0 text-brand-orange mt-1" size={20} />
<span className="text-gray-700">{work}</span>
</li>
))}
{geotechnicalWorks.map((work, index) => {
const text = isEnglish
? [
'Excavation of test pits and boreholes with sampling and laboratory tests to obtain parameters for specific foundation design schemes.',
'Field testing of soils to determine standard strength and deformation characteristics (plate load, shear, pressuremeter, vane shear tests) and testing of reference and fullscale piles.',
'Determination of standard mechanical characteristics of soils using static, dynamic and drilling penetration tests.',
'Physical and numerical modelling of interaction between buildings/structures and the geological environment.',
'Special soil studies under bespoke programmes for nonstandard, including nonlinear, foundation and structure design methods.',
'Geotechnical monitoring of construction of buildings, structures and adjacent areas.',
][index] || work
: work;
return (
<li key={index} className="flex items-start gap-3">
<CheckCircle2 className="flex-shrink-0 text-brand-orange mt-1" size={20} />
<span className="text-gray-700">{text}</span>
</li>
);
})}
</ul>
</div>
</div>
@@ -246,15 +390,21 @@ const SurveyingPage: React.FC = () => {
{/* Прайс-лист */}
<div className="max-w-5xl mx-auto">
<h2 className="text-3xl font-bold text-gray-900 mb-8 text-center">
Цены на основные виды работ по инженерным изысканиям
{isEnglish
? 'Prices for main types of engineering surveys'
: 'Цены на основные виды работ по инженерным изысканиям'}
</h2>
<div className="overflow-x-auto shadow-lg rounded-2xl">
<table className="w-full bg-white">
<thead>
<tr className="bg-brand-orange text-white">
<th className="px-6 py-4 text-left font-bold">Наименование услуги</th>
<th className="px-6 py-4 text-right font-bold w-48">Стоимость</th>
<th className="px-6 py-4 text-left font-bold">
{isEnglish ? 'Service name' : 'Наименование услуги'}
</th>
<th className="px-6 py-4 text-right font-bold w-48">
{isEnglish ? 'Price' : 'Стоимость'}
</th>
</tr>
</thead>
<tbody>
@@ -285,13 +435,15 @@ const SurveyingPage: React.FC = () => {
<div className="mt-12 text-center">
<div className="bg-gray-50 rounded-2xl p-8">
<p className="text-gray-700 mb-6">
Точную стоимость работ можно узнать после анализа технического задания и условий объекта
{isEnglish
? 'The exact cost can be calculated after analysing the technical assignment and site conditions.'
: 'Точную стоимость работ можно узнать после анализа технического задания и условий объекта'}
</p>
<a
href="#/contacts"
href={`#${prefix}/contacts`}
className="inline-block px-8 py-4 bg-brand-orange text-white font-bold rounded-lg hover:bg-orange-600 transition-colors text-lg"
>
Получить консультацию
{isEnglish ? 'Request a consultation' : 'Получить консультацию'}
</a>
</div>
</div>