414 lines
16 KiB
TypeScript
414 lines
16 KiB
TypeScript
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; |