Spaces:
Running
Running
| tsx | |
| import { Link, useNavigate, useSearchParams } from 'react-router-dom' | |
| import { Menu, Search, Video, Bell, User, LogOut, Settings, Moon, Sun, Monitor } from 'lucide-react' | |
| import { Button } from './ui/button' | |
| import { Input } from './ui/input' | |
| import { useUIStore } from '@/store/ui' | |
| import { useAuthStore } from '@/store/auth' | |
| import { useTheme } from '@/providers/ThemeProvider' | |
| import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from './ui/dropdown-menu' | |
| import { useMemo } from 'react' | |
| export default function Header() { | |
| const navigate = useNavigate() | |
| const [params, setParams] = useSearchParams() | |
| const q = useMemo(() => params.get('q') || '', [params]) | |
| const { toggleSidebar } = useUIStore() | |
| const { user, logout } = useAuthStore() | |
| const { theme, setTheme } = useTheme() | |
| function onSearch(e: React.FormEvent<HTMLFormElement>) { | |
| e.preventDefault() | |
| const form = e.currentTarget | |
| const data = new FormData(form) | |
| const query = data.get('q') as string | |
| navigate(`/search?q=${encodeURIComponent(query)}`) | |
| } | |
| return ( | |
| <header className="sticky top-0 z-50 border-b border-zinc-200/80 bg-white/80 backdrop-blur dark:border-zinc-800/80 dark:bg-zinc-950/80"> | |
| <div className="mx-auto flex h-14 max-w-[1920px] items-center gap-2 px-3 sm:px-5"> | |
| <div className="flex items-center gap-2"> | |
| <Button variant="ghost" size="icon" onClick={toggleSidebar} aria-label="Toggle menu"> | |
| <Menu className="h-5 w-5" /> | |
| </Button> | |
| <Link to="/" className="flex items-center gap-2"> | |
| <div className="h-7 w-7 rounded-md bg-red-600 text-white flex items-center justify-center font-black">LT</div> | |
| <span className="text-lg font-semibold tracking-tight">LobsterTube</span> | |
| </Link> | |
| </div> | |
| <form onSubmit={onSearch} className="flex-1 flex justify-center px-2"> | |
| <div className="flex w-full max-w-2xl items-stretch"> | |
| <Input name="q" defaultValue={q} placeholder="Поиск" className="rounded-r-none border-r-0" /> | |
| <Button type="submit" className="rounded-l-none border border-l-0 border-zinc-200 dark:border-zinc-800"> | |
| <Search className="h-5 w-5" /> | |
| </Button> | |
| </div> | |
| </form> | |
| <div className="flex items-center gap-1"> | |
| <Button variant="ghost" size="icon" onClick={() => navigate('/upload')} title="Создать"> | |
| <Video className="h-5 w-5" /> | |
| </Button> | |
| <Button variant="ghost" size="icon"> | |
| <Bell className="h-5 w-5" /> | |
| </Button> | |
| <DropdownMenu> | |
| <DropdownMenuTrigger asChild> | |
| <Button variant="ghost" size="icon" className="overflow-hidden"> | |
| {user ? ( | |
| <img src={user.avatarUrl || `https://api.dicebear.com/9.x/identicon/svg?seed=${user.id}`} className="h-7 w-7 rounded-full" alt="avatar" /> | |
| ) : ( | |
| <User className="h-5 w-5" /> | |
| )} | |
| </Button> | |
| </DropdownMenuTrigger> | |
| <DropdownMenuContent align="end" className="w-56"> | |
| {user ? ( | |
| <> | |
| <div className="px-2 py-2 text-sm text-zinc-500 dark:text-zinc-400">Вошли как {user.name}</div> | |
| <DropdownMenuItem onClick={() => navigate(`/channel/${user.id}`)}> | |
| <User className="mr-2 h-4 w-4" /> Мой канал | |
| </DropdownMenuItem> | |
| <DropdownMenuItem onClick={() => setTheme('system')}> | |
| <Monitor className="mr-2 h-4 w-4" /> Системная | |
| </DropdownMenuItem> | |
| <DropdownMenuItem onClick={() => setTheme('light')}> | |
| <Sun className="mr-2 h-4 w-4" /> Светлая | |
| </DropdownMenuItem> | |
| <DropdownMenuItem onClick={() => setTheme('dark')}> | |
| <Moon className="mr-2 h-4 w-4" /> Тёмная | |
| </DropdownMenuItem> | |
| <DropdownMenuItem> | |
| <Settings className="mr-2 h-4 w-4" /> Настройки | |
| </DropdownMenuItem> | |
| <DropdownMenuItem onClick={() => logout()}> | |
| <LogOut className="mr-2 h-4 w-4" /> Выйти | |
| </DropdownMenuItem> | |
| </> | |
| ) : ( | |
| <> | |
| <DropdownMenuItem onClick={() => navigate('/login')}> | |
| <User className="mr-2 h-4 w-4" /> Войти | |
| </DropdownMenuItem> | |
| <DropdownMenuItem onClick={() => setTheme('dark')}> | |
| <Moon className="mr-2 h-4 w-4" /> Тёмная | |
| </DropdownMenuItem> | |
| </> | |
| )} | |
| </DropdownMenuContent> | |
| </DropdownMenu> | |
| </div> | |
| </div> | |
| </header> | |
| ) | |
| } | |
| </html> |