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

@@ -10,11 +10,12 @@ interface NavbarProps {
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();
const isEnglish = location.pathname.startsWith('/en');
const prefix = isEnglish ? '/en' : '';
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 50);
@@ -24,7 +25,7 @@ const Navbar: React.FC<NavbarProps> = ({ transparent = false }) => {
return () => window.removeEventListener('scroll', handleScroll);
}, []);
const isHome = location.pathname === '/';
const isHome = location.pathname === '/' || location.pathname === '/en';
// Use transparent background only on Home and when not scrolled, if requested
const isTransparent = transparent && isHome && !isScrolled;
@@ -37,7 +38,7 @@ const Navbar: React.FC<NavbarProps> = ({ transparent = false }) => {
<div className="container mx-auto px-6 flex items-center justify-between text-white">
{/* Logo */}
<Link to="/" className="flex items-center gap-2 group">
<Link to={isEnglish ? '/en' : '/'} className="flex items-center gap-2 group">
{!imgError ? (
<img
src="/media/geo-logo.webp"
@@ -57,177 +58,105 @@ const Navbar: React.FC<NavbarProps> = ({ transparent = false }) => {
{/* Главная */}
<li>
<Link
to="/"
to={isEnglish ? '/en' : '/'}
className={`transition-colors hover:text-brand-orange ${
location.pathname === '/' ? 'text-brand-orange' : 'text-gray-300'
(location.pathname === '/' || location.pathname === '/en')
? 'text-brand-orange'
: 'text-gray-300'
}`}
>
Главная
{isEnglish ? 'Home' : 'Главная'}
</Link>
</li>
{/* Услуги */}
<li>
<Link
to={`${prefix}/services`}
className={`transition-colors hover:text-brand-orange ${
location.pathname.replace('/en', '').startsWith('/services')
? 'text-brand-orange'
: 'text-gray-300'
}`}
>
{isEnglish ? 'Services' : 'Услуги'}
</Link>
</li>
{/* Проекты */}
<li>
<Link
to={`${prefix}/projects`}
className={`transition-colors hover:text-brand-orange ${
location.pathname.replace('/en', '') === '/projects'
? 'text-brand-orange'
: 'text-gray-300'
}`}
>
{isEnglish ? 'Projects' : 'Проекты'}
</Link>
</li>
{/* О компании */}
<li>
<Link
to="/about"
to={`${prefix}/about`}
className={`transition-colors hover:text-brand-orange ${
location.pathname === '/about' ? 'text-brand-orange' : 'text-gray-300'
location.pathname.replace('/en', '') === '/about'
? 'text-brand-orange'
: 'text-gray-300'
}`}
>
О компании
{isEnglish ? 'About' : 'О компании'}
</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"
to={`${prefix}/contacts`}
className={`transition-colors hover:text-brand-orange ${
location.pathname === '/contacts' ? 'text-brand-orange' : 'text-gray-300'
location.pathname.replace('/en', '') === '/contacts'
? 'text-brand-orange'
: 'text-gray-300'
}`}
>
Контакты
{isEnglish ? 'Contacts' : 'Контакты'}
</Link>
</li>
</ul>
{/* CTA & Mobile Toggle */}
{/* Language switcher, 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">
{/* Языковой переключатель */}
<div className="hidden md:flex items-center gap-1 text-sm font-medium">
<button
onClick={() => {
if (location.pathname.startsWith('/en')) {
const ruPath = location.pathname.replace('/en', '') || '/';
window.location.hash = `#${ruPath}`;
}
}}
className={location.pathname.startsWith('/en') ? 'text-gray-400 hover:text-white transition-colors' : 'text-white font-semibold'}
>
RU
</button>
<span className="text-gray-500">/</span>
<button
onClick={() => {
if (!location.pathname.startsWith('/en')) {
const basePath = location.pathname === '/' ? '' : location.pathname;
window.location.hash = `#/en${basePath}`;
}
}}
className={location.pathname.startsWith('/en') ? 'text-white font-semibold' : 'text-gray-400 hover:text-white transition-colors'}
>
EN
</button>
</div>
<Link to={`${prefix}/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>
<span>{isEnglish ? 'Contact us' : 'Связаться'}</span>
</Link>
<button
@@ -244,166 +173,86 @@ const Navbar: React.FC<NavbarProps> = ({ transparent = false }) => {
<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="/"
to={isEnglish ? '/en' : '/'}
className="text-lg font-medium text-gray-300 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
Главная
{isEnglish ? 'Home' : 'Главная'}
</Link>
{/* О компании */}
<Link
to="/about"
to={`${prefix}/about`}
className="text-lg font-medium text-gray-300 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
О компании
{isEnglish ? 'About' : 'О компании'}
</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={`${prefix}/services`}
className="text-lg font-medium text-gray-300 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
{isEnglish ? 'Services' : 'Услуги'}
</Link>
{/* Проекты */}
<Link
to="/projects"
to={`${prefix}/projects`}
className="text-lg font-medium text-gray-300 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
Проекты
{isEnglish ? 'Projects' : 'Проекты'}
</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"
to={`${prefix}/contacts`}
className="text-lg font-medium text-gray-300 hover:text-brand-orange"
onClick={() => setIsMobileMenuOpen(false)}
>
Контакты
{isEnglish ? 'Contacts' : 'Контакты'}
</Link>
{/* Языковой переключатель (мобильный) */}
<div className="flex items-center gap-2 text-sm font-medium text-gray-300 pt-4 border-t border-gray-800">
<button
onClick={() => {
setIsMobileMenuOpen(false);
if (location.pathname.startsWith('/en')) {
const ruPath = location.pathname.replace('/en', '') || '/';
window.location.hash = `#${ruPath}`;
}
}}
className={location.pathname.startsWith('/en') ? 'text-gray-500' : 'text-white'}
>
RU
</button>
<span className="text-gray-500">/</span>
<button
onClick={() => {
setIsMobileMenuOpen(false);
if (!location.pathname.startsWith('/en')) {
const basePath = location.pathname === '/' ? '' : location.pathname;
window.location.hash = `#/en${basePath}`;
}
}}
className={location.pathname.startsWith('/en') ? 'text-white' : 'text-gray-500'}
>
EN
</button>
</div>
<Link
to="/contacts"
to={`${prefix}/contacts`}
className="flex items-center gap-2 text-brand-orange font-bold mt-4"
onClick={() => setIsMobileMenuOpen(false)}
>
<Phone className="w-5 h-5" /> Связаться
<Phone className="w-5 h-5" /> {isEnglish ? 'Contact us' : 'Связаться'}
</Link>
</div>
)}