zephyrdark 3e733ec1b8 feat(frontend): add new layout components
- Collapsible Sidebar with navigation
- Header with page titles and logout
- DashboardLayout with responsive design
- Updated dashboard page

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 22:46:54 +09:00

85 lines
2.2 KiB
TypeScript

'use client';
import { usePathname, useRouter } from 'next/navigation';
import { Menu, LogOut, User } from 'lucide-react';
import { api } from '@/lib/api';
import { Button } from '@/components/ui/button';
const pageTitles: Record<string, string> = {
'/': '대시보드',
'/portfolio': '포트폴리오',
'/strategy': '전략',
'/backtest': '백테스트',
'/admin/data': '데이터 관리',
};
function getPageTitle(pathname: string): string {
// Check exact match first
if (pageTitles[pathname]) {
return pageTitles[pathname];
}
// Check for partial matches (for nested routes)
for (const [path, title] of Object.entries(pageTitles)) {
if (path !== '/' && pathname.startsWith(path)) {
return title;
}
}
return '대시보드';
}
interface NewHeaderProps {
username?: string;
onMenuClick?: () => void;
showMenuButton?: boolean;
}
export function NewHeader({ username, onMenuClick, showMenuButton = false }: NewHeaderProps) {
const pathname = usePathname();
const router = useRouter();
const pageTitle = getPageTitle(pathname);
const handleLogout = () => {
api.logout();
router.push('/login');
};
return (
<header className="flex items-center justify-between h-16 px-4 border-b bg-background">
<div className="flex items-center gap-4">
{showMenuButton && (
<Button
variant="ghost"
size="icon"
onClick={onMenuClick}
className="md:hidden"
>
<Menu className="h-5 w-5" />
<span className="sr-only"> </span>
</Button>
)}
<h1 className="text-xl font-semibold">{pageTitle}</h1>
</div>
<div className="flex items-center gap-4">
{username && (
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<User className="h-4 w-4" />
<span>{username}</span>
</div>
)}
<Button
variant="ghost"
size="sm"
onClick={handleLogout}
className="gap-2"
>
<LogOut className="h-4 w-4" />
<span className="hidden sm:inline"></span>
</Button>
</div>
</header>
);
}