109 lines
4.4 KiB
TypeScript
109 lines
4.4 KiB
TypeScript
import React, { useState } from 'react';
|
||
import { NavLink, useLocation, useNavigate } from 'react-router-dom';
|
||
import {
|
||
LayoutDashboard,
|
||
Grid,
|
||
CheckSquare,
|
||
MessageSquareText,
|
||
Menu,
|
||
} from 'lucide-react';
|
||
import { MobileMenuDrawer } from './MobileMenuDrawer';
|
||
|
||
export const BottomNav: React.FC = () => {
|
||
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
||
const location = useLocation();
|
||
const navigate = useNavigate();
|
||
|
||
const isCatalogActive = location.pathname === '/' && !location.search.includes('tab=dashboard');
|
||
const isDashboardActive = location.pathname === '/' && location.search.includes('tab=dashboard');
|
||
|
||
return (
|
||
<>
|
||
<nav
|
||
aria-label="Мобильная навигация"
|
||
data-testid="bottom-nav"
|
||
className="fixed bottom-0 inset-x-0 bg-krona-surface text-krona-secondary border-t border-krona-border flex items-center justify-around z-40 px-1 pt-1 pb-[max(0.5rem,env(safe-area-inset-bottom))] shadow-lg backdrop-blur-md"
|
||
>
|
||
{/* 1. Главная (KPI Сводка) */}
|
||
<button
|
||
onClick={() => navigate('/?tab=dashboard')}
|
||
className={`flex-1 min-h-[48px] min-w-[44px] flex flex-col items-center justify-center gap-1 p-1 rounded-xl transition-colors select-none ${
|
||
isDashboardActive
|
||
? 'text-krona-gold font-bold bg-krona-gold/10'
|
||
: 'text-krona-secondary hover:text-krona-primary active:bg-krona-workspace'
|
||
}`}
|
||
data-testid="bottom-nav-dashboard"
|
||
>
|
||
<LayoutDashboard className="w-5 h-5 shrink-0" />
|
||
<span className="text-[10px] leading-none font-medium">Главная</span>
|
||
</button>
|
||
|
||
{/* 2. Модули (Единый каталог) */}
|
||
<button
|
||
onClick={() => navigate('/')}
|
||
className={`flex-1 min-h-[48px] min-w-[44px] flex flex-col items-center justify-center gap-1 p-1 rounded-xl transition-colors select-none ${
|
||
isCatalogActive
|
||
? 'text-krona-gold font-bold bg-krona-gold/10'
|
||
: 'text-krona-secondary hover:text-krona-primary active:bg-krona-workspace'
|
||
}`}
|
||
data-testid="bottom-nav-catalog"
|
||
>
|
||
<Grid className="w-5 h-5 shrink-0" />
|
||
<span className="text-[10px] leading-none font-medium">Модули</span>
|
||
</button>
|
||
|
||
{/* 3. Задачи */}
|
||
<NavLink
|
||
to="/tasks"
|
||
className={({ isActive }) =>
|
||
`flex-1 min-h-[48px] min-w-[44px] flex flex-col items-center justify-center gap-1 p-1 rounded-xl transition-colors select-none ${
|
||
isActive
|
||
? 'text-krona-gold font-bold bg-krona-gold/10'
|
||
: 'text-krona-secondary hover:text-krona-primary active:bg-krona-workspace'
|
||
}`
|
||
}
|
||
data-testid="bottom-nav-tasks"
|
||
>
|
||
<CheckSquare className="w-5 h-5 shrink-0" />
|
||
<span className="text-[10px] leading-none font-medium">Задачи</span>
|
||
</NavLink>
|
||
|
||
{/* 4. Коммуникации */}
|
||
<NavLink
|
||
to="/communications"
|
||
className={({ isActive }) =>
|
||
`flex-1 min-h-[48px] min-w-[44px] flex flex-col items-center justify-center gap-1 p-1 rounded-xl transition-colors select-none ${
|
||
isActive
|
||
? 'text-krona-gold font-bold bg-krona-gold/10'
|
||
: 'text-krona-secondary hover:text-krona-primary active:bg-krona-workspace'
|
||
}`
|
||
}
|
||
data-testid="bottom-nav-communications"
|
||
>
|
||
<MessageSquareText className="w-5 h-5 shrink-0" />
|
||
<span className="text-[10px] leading-none font-medium">Диалоги</span>
|
||
</NavLink>
|
||
|
||
{/* 5. Ещё */}
|
||
<button
|
||
onClick={() => setIsDrawerOpen(true)}
|
||
className={`flex-1 min-h-[48px] min-w-[44px] flex flex-col items-center justify-center gap-1 p-1 rounded-xl transition-colors select-none ${
|
||
isDrawerOpen
|
||
? 'text-krona-gold font-bold bg-krona-gold/10'
|
||
: 'text-krona-secondary hover:text-krona-primary active:bg-krona-workspace'
|
||
}`}
|
||
data-testid="bottom-nav-more"
|
||
>
|
||
<Menu className="w-5 h-5 shrink-0" />
|
||
<span className="text-[10px] leading-none font-medium">Ещё</span>
|
||
</button>
|
||
</nav>
|
||
|
||
{/* Slide-out Mobile Menu Drawer */}
|
||
<MobileMenuDrawer
|
||
isOpen={isDrawerOpen}
|
||
onClose={() => setIsDrawerOpen(false)}
|
||
/>
|
||
</>
|
||
);
|
||
};
|