Files
gridpilot.gg/apps/website/components/layout/AppHeader.tsx
2026-01-21 22:36:01 +01:00

113 lines
3.9 KiB
TypeScript

'use client';
import { Text } from '@/ui/Text';
import { Bell, Command } from 'lucide-react';
import { usePathname } from 'next/navigation';
import { useCurrentSession } from '@/hooks/auth/useCurrentSession';
import { useState, useEffect } from 'react';
import { ShellHeader } from '@/ui/shell/Shell';
import { CommandModal } from './CommandModal';
import { UserPill } from '@/components/profile/UserPill';
import { Input } from '@/ui/Input';
import { Box } from '@/ui/Box';
import { IconButton } from '@/ui/IconButton';
import { useSidebar } from '@/components/layout/SidebarContext';
import { PublicTopNav } from '@/ui/PublicTopNav';
import { PublicNavLogin } from '@/ui/PublicNavLogin';
import { PublicNavSignup } from '@/ui/PublicNavSignup';
export function AppHeader() {
const pathname = usePathname();
const { data: session } = useCurrentSession();
const isAuthenticated = !!session;
const [isCommandOpen, setIsCommandOpen] = useState(false);
const { isCollapsed } = useSidebar();
// Simple breadcrumb logic
const pathSegments = pathname.split('/').filter(Boolean);
const breadcrumbs = pathSegments.length > 0
? pathSegments.map(s => s.charAt(0).toUpperCase() + s.slice(1)).join(' / ')
: 'Home';
// Cmd+K Listener
useEffect(() => {
const down = (e: KeyboardEvent) => {
if (e.key === 'k' && (e.metaKey || e.ctrlKey)) {
e.preventDefault();
setIsCommandOpen((open) => !open);
}
};
document.addEventListener('keydown', down);
return () => document.removeEventListener('keydown', down);
}, []);
return (
<>
<ShellHeader collapsed={isCollapsed}>
{/* Left: Public Navigation & Context */}
<Box display="flex" alignItems="center" gap={6} flex={1}>
{/* Public Top Navigation - Only when not authenticated */}
{!isAuthenticated && (
<PublicTopNav pathname={pathname} />
)}
{/* Context & Search - Only when authenticated */}
{isAuthenticated && (
<>
<Text size="sm" variant="med" weight="medium" style={{ minWidth: '100px' }}>
{breadcrumbs}
</Text>
{/* Command Search Trigger */}
<Box display={{ base: 'none', md: 'block' }}>
<Input
readOnly
onClick={() => setIsCommandOpen(true)}
placeholder="Search or type a command..."
variant="search"
width="24rem"
rightElement={
<Box display="flex" alignItems="center" gap={1} paddingX={1.5} paddingY={0.5} rounded bg="white/5" border>
<Command size={10} />
<Text size="xs" font="mono" variant="low" style={{ fontSize: '10px' }}>K</Text>
</Box>
}
className="cursor-pointer"
/>
</Box>
</>
)}
</Box>
{/* Right: User & Notifications */}
<Box display="flex" alignItems="center" gap={4}>
{/* Notifications - Only when authed */}
{isAuthenticated && (
<Box position="relative">
<IconButton
icon={Bell}
variant="ghost"
title="Notifications"
/>
<Box position="absolute" top={2} right={2} width={1.5} height={1.5} bg="var(--ui-color-intent-primary)" rounded="full" ring="2px" />
</Box>
)}
{/* Public Login/Signup Buttons - Only when not authenticated */}
{!isAuthenticated && (
<>
<PublicNavLogin />
<PublicNavSignup />
</>
)}
{/* User Pill (Handles Auth & Menu) - Only when authenticated */}
{isAuthenticated && <UserPill />}
</Box>
</ShellHeader>
<CommandModal isOpen={isCommandOpen} onClose={() => setIsCommandOpen(false)} />
</>
);
}