gauthambinoy
Add Investment Profit Prediction Engine - the core product
3aaed2e
Raw
History Blame Contribute Delete
9.19 kB
import React, { useState } from 'react';
import { Outlet, NavLink, useNavigate } from 'react-router-dom';
import { useAuthStore } from '../utils/store';
import { useTheme } from './ThemeProvider';
import {
LayoutDashboard,
Briefcase,
TrendingUp,
TrendingDown,
Flame,
Bell,
LogOut,
Menu,
X,
ChevronDown,
User,
Eye,
ArrowLeftRight,
BarChart3,
Target,
DollarSign,
Newspaper,
Brain,
ArrowRightLeft,
Trophy,
GitCompare,
Share2,
Gauge,
Sun,
Moon,
FileDown,
Shield,
SlidersHorizontal,
Calculator,
FileText,
Scale,
Zap,
Search,
BarChart2
} from 'lucide-react';
const Layout = () => {
const [sidebarOpen, setSidebarOpen] = useState(false);
const [userMenuOpen, setUserMenuOpen] = useState(false);
const { user, logout } = useAuthStore();
const { theme, toggleTheme } = useTheme();
const navigate = useNavigate();
const handleLogout = () => {
logout();
navigate('/login');
};
const navSections = [
{
title: 'Invest',
items: [
{ path: '/top-picks', icon: Zap, label: 'Top Picks Today' },
{ path: '/invest/analyze', icon: Search, label: 'Deep Analysis' },
{ path: '/market-pulse', icon: BarChart2, label: 'Market Pulse' },
{ path: '/profit-calc', icon: Calculator, label: 'Profit Calculator' },
]
},
{
title: 'Portfolio',
items: [
{ path: '/dashboard', icon: LayoutDashboard, label: 'Dashboard' },
{ path: '/portfolio', icon: Briefcase, label: 'Portfolio' },
{ path: '/analytics', icon: BarChart3, label: 'Analytics' },
{ path: '/risk', icon: Shield, label: 'Risk Analysis' },
{ path: '/rebalance', icon: Scale, label: 'Rebalance' },
]
},
{
title: 'Markets',
items: [
{ path: '/markets', icon: TrendingUp, label: 'Markets' },
{ path: '/watchlist', icon: Eye, label: 'Watchlist' },
{ path: '/screener', icon: SlidersHorizontal, label: 'Screener' },
{ path: '/gainers', icon: Flame, label: 'Top Gainers' },
{ path: '/losers', icon: TrendingDown, label: 'Top Losers' },
{ path: '/news', icon: Newspaper, label: 'News Feed' },
{ path: '/fear-greed', icon: Gauge, label: 'Fear & Greed' },
]
},
{
title: 'Tools',
items: [
{ path: '/prediction', icon: Brain, label: 'AI Prediction' },
{ path: '/dca', icon: Calculator, label: 'DCA Calculator' },
{ path: '/converter', icon: ArrowRightLeft, label: 'Converter' },
{ path: '/alerts', icon: Bell, label: 'Alerts' },
{ path: '/compare', icon: GitCompare, label: 'Compare' },
]
},
{
title: 'Finance',
items: [
{ path: '/transactions', icon: ArrowLeftRight, label: 'Transactions' },
{ path: '/tax-report', icon: FileText, label: 'Tax Report' },
{ path: '/goals', icon: Target, label: 'Goals' },
{ path: '/dividends', icon: DollarSign, label: 'Dividends' },
]
},
{
title: 'Social',
items: [
{ path: '/leaderboard', icon: Trophy, label: 'Leaderboard' },
{ path: '/share', icon: Share2, label: 'Share Portfolio' },
]
},
];
return (
<div className="min-h-screen flex">
{/* Sidebar */}
<aside className={`
fixed inset-y-0 left-0 z-50 w-64 bg-dark-300 border-r border-white/5
transform transition-transform duration-300 ease-in-out overflow-y-auto
lg:translate-x-0 lg:static lg:inset-auto
${sidebarOpen ? 'translate-x-0' : '-translate-x-full'}
`}>
{/* Logo */}
<div className="h-16 flex items-center justify-between px-6 border-b border-white/5 sticky top-0 bg-dark-300 z-10">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-xl bg-gradient-to-br from-primary-500 to-success-500 flex items-center justify-center">
<TrendingUp className="w-6 h-6 text-white" />
</div>
<span className="font-bold text-xl">CryptoStock</span>
</div>
<button
className="lg:hidden text-gray-400 hover:text-white"
onClick={() => setSidebarOpen(false)}
>
<X className="w-6 h-6" />
</button>
</div>
{/* Navigation */}
<nav className="p-4 space-y-6 pb-24">
{navSections.map((section) => (
<div key={section.title}>
<p className="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2 px-4">
{section.title}
</p>
<div className="space-y-1">
{section.items.map(({ path, icon: Icon, label }) => (
<NavLink
key={path}
to={path}
onClick={() => setSidebarOpen(false)}
className={({ isActive }) => `
flex items-center gap-3 px-4 py-2.5 rounded-xl transition-all duration-200 text-sm
${isActive
? 'bg-primary-500/20 text-primary-400 border border-primary-500/30'
: 'text-gray-400 hover:bg-white/5 hover:text-white'
}
`}
>
<Icon className="w-4 h-4" />
<span className="font-medium">{label}</span>
</NavLink>
))}
</div>
</div>
))}
</nav>
{/* User Section */}
<div className="absolute bottom-0 left-0 right-0 p-4 border-t border-white/5 bg-dark-300">
<div className="flex items-center gap-3 px-4 py-3 rounded-xl bg-white/5">
<div className="w-10 h-10 rounded-full bg-gradient-to-br from-primary-500 to-purple-500 flex items-center justify-center">
<User className="w-5 h-5 text-white" />
</div>
<div className="flex-1 min-w-0">
<p className="text-sm font-medium truncate">{user?.full_name || user?.username}</p>
<p className="text-xs text-gray-400 truncate">{user?.email}</p>
</div>
</div>
</div>
</aside>
{/* Main Content */}
<div className="flex-1 flex flex-col min-h-screen">
{/* Header */}
<header className="h-16 flex items-center justify-between px-4 lg:px-8 border-b border-white/5 bg-dark-300/50 backdrop-blur-xl sticky top-0 z-40">
<button
className="lg:hidden text-gray-400 hover:text-white"
onClick={() => setSidebarOpen(true)}
>
<Menu className="w-6 h-6" />
</button>
<div className="hidden lg:flex items-center gap-2 text-sm text-gray-400">
<span>Press</span>
<kbd className="px-2 py-1 bg-white/10 rounded-md text-xs font-mono">Ctrl+K</kbd>
<span>to search</span>
</div>
{/* Right side */}
<div className="flex items-center gap-3 ml-auto">
{/* Theme Toggle */}
<button
onClick={toggleTheme}
className="p-2 text-gray-400 hover:text-white transition-colors rounded-lg hover:bg-white/5"
>
{theme === 'dark' ? <Sun className="w-5 h-5" /> : <Moon className="w-5 h-5" />}
</button>
{/* Notifications */}
<button className="relative p-2 text-gray-400 hover:text-white transition-colors">
<Bell className="w-5 h-5" />
<span className="absolute top-1 right-1 w-2 h-2 bg-danger-500 rounded-full"></span>
</button>
{/* User Menu */}
<div className="relative">
<button
onClick={() => setUserMenuOpen(!userMenuOpen)}
className="flex items-center gap-2 text-gray-400 hover:text-white transition-colors"
>
<div className="w-8 h-8 rounded-full bg-gradient-to-br from-primary-500 to-purple-500 flex items-center justify-center">
<User className="w-4 h-4 text-white" />
</div>
<ChevronDown className="w-4 h-4" />
</button>
{userMenuOpen && (
<div className="absolute right-0 mt-2 w-48 glass-card py-2 animate-fade-in">
<button
onClick={handleLogout}
className="w-full flex items-center gap-2 px-4 py-2 text-gray-400 hover:text-white hover:bg-white/5 transition-colors"
>
<LogOut className="w-4 h-4" />
<span>Logout</span>
</button>
</div>
)}
</div>
</div>
</header>
{/* Page Content */}
<main className="flex-1 p-4 lg:p-8 overflow-auto">
<Outlet />
</main>
</div>
{/* Mobile sidebar overlay */}
{sidebarOpen && (
<div
className="fixed inset-0 bg-black/50 z-40 lg:hidden"
onClick={() => setSidebarOpen(false)}
/>
)}
</div>
);
};
export default Layout;