Skip to content

Commit 2c21351

Browse files
authored
Merge pull request #80 from ayushpandey101/FIX1
Fix: Authentication State + Logout Functionality + Enhanced Avatar
2 parents d9400c4 + 092fdc0 commit 2c21351

File tree

6 files changed

+347
-517
lines changed

6 files changed

+347
-517
lines changed

frontend/app/HomeClient.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"use client";
22
import { useEffect, useState } from "react";
3+
import { SessionProvider } from "next-auth/react";
34
import Landing from "@/components/Landing";
45
import Preloader from "@/components/Preloder";
56

@@ -18,5 +19,9 @@ export default function HomeClient() {
1819
}
1920
}, []);
2021

21-
return isLoading ? <Preloader /> : <Landing />;
22+
return isLoading ? <Preloader /> : (
23+
<SessionProvider>
24+
<Landing />
25+
</SessionProvider>
26+
);
2227
}

frontend/app/api/auth/[...nextauth]/authOptions.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ const authOptions = {
7373
pages: {
7474
signIn: "/login",
7575
signUp: "/signup",
76+
signOut: "/",
7677
},
7778
};
7879

frontend/app/components/DashboardPage.tsx

Lines changed: 115 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,61 @@
22
import { Dashboard } from "@/components/dashboard";
33
import { ThemeToggle } from "@/components/theme-toggle";
44
import { Button } from "@/components/ui/button";
5+
import {
6+
DropdownMenu,
7+
DropdownMenuContent,
8+
DropdownMenuItem,
9+
DropdownMenuLabel,
10+
DropdownMenuSeparator,
11+
DropdownMenuTrigger,
12+
} from "@/components/ui/dropdown-menu";
13+
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
514
import { useIsMobile } from "@/hooks/use-mobile";
615
import { cn } from "@/lib/utils";
716
import { FloatingChatbot } from "@/components/floating-chatbot";
817
import { StockVisionErrorBoundary } from "../../lib/error-handling";
918
import {
1019
BarChart2, ChevronLeft, ChevronRight, Home, LineChart,
11-
Settings, Wallet,BriefcaseBusiness , ChartNoAxesCombined
20+
Settings, Wallet, BriefcaseBusiness, ChartNoAxesCombined, LogOut, User
1221
} from "lucide-react";
1322
import { useRouter } from "next/navigation";
1423
import { useEffect, useState } from "react";
24+
import { useSession, signOut } from "next-auth/react";
1525

1626
export default function DashboardPage() {
1727
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
1828
const isMobile = useIsMobile();
1929
const router = useRouter();
2030
const [activeSection, setActiveSection] = useState("overview");
31+
const { data: session } = useSession();
32+
33+
const handleSignOut = async () => {
34+
await signOut({ redirect: false });
35+
router.push('/');
36+
};
37+
38+
const getUsernameFromEmail = (email?: string | null) => {
39+
if (!email) return 'User';
40+
const username = email.split('@')[0];
41+
// Capitalize first letter
42+
return username.charAt(0).toUpperCase() + username.slice(1);
43+
};
44+
45+
const getInitials = (name?: string | null, email?: string | null) => {
46+
if (name) {
47+
return name
48+
.split(' ')
49+
.map(n => n[0])
50+
.join('')
51+
.toUpperCase()
52+
.slice(0, 2);
53+
}
54+
if (email) {
55+
const username = email.split('@')[0];
56+
return username.slice(0, 2).toUpperCase();
57+
}
58+
return 'U';
59+
};
2160

2261
useEffect(() => {
2362
if (isMobile) {
@@ -209,7 +248,81 @@ export default function DashboardPage() {
209248
</Button>
210249
</div>
211250
<h1 className="text-xl font-extrabold">Dashboard</h1>
212-
<ThemeToggle />
251+
<div className="flex items-center gap-3">
252+
<ThemeToggle />
253+
{session && (
254+
<DropdownMenu>
255+
<DropdownMenuTrigger asChild>
256+
<Button
257+
variant="ghost"
258+
className="relative h-10 w-10 rounded-full p-0 ring-2 ring-primary/30 hover:ring-primary/60 transition-all duration-300 hover:scale-105"
259+
>
260+
<Avatar className="h-10 w-10">
261+
<AvatarImage
262+
src={session.user?.image || undefined}
263+
alt={session.user?.name || getUsernameFromEmail(session.user?.email)}
264+
className="object-cover"
265+
/>
266+
<AvatarFallback className="bg-gradient-to-br from-blue-500 via-purple-500 to-pink-500 text-white font-bold shadow-lg">
267+
{getInitials(session.user?.name, session.user?.email)}
268+
</AvatarFallback>
269+
</Avatar>
270+
{/* Active indicator dot */}
271+
<span className="absolute bottom-0 right-0 h-2.5 w-2.5 rounded-full bg-green-500 border-2 border-background shadow-sm" />
272+
</Button>
273+
</DropdownMenuTrigger>
274+
<DropdownMenuContent className="w-64" align="end" forceMount>
275+
<DropdownMenuLabel className="font-normal">
276+
<div className="flex flex-col space-y-2 p-2">
277+
<div className="flex items-center gap-3">
278+
<Avatar className="h-12 w-12">
279+
<AvatarImage
280+
src={session.user?.image || undefined}
281+
alt={session.user?.name || getUsernameFromEmail(session.user?.email)}
282+
className="object-cover"
283+
/>
284+
<AvatarFallback className="bg-gradient-to-br from-blue-500 via-purple-500 to-pink-500 text-white font-bold shadow-lg">
285+
{getInitials(session.user?.name, session.user?.email)}
286+
</AvatarFallback>
287+
</Avatar>
288+
<div className="flex flex-col space-y-1 flex-1 min-w-0">
289+
<p className="text-sm font-semibold leading-none truncate">
290+
{session.user?.name || getUsernameFromEmail(session.user?.email)}
291+
</p>
292+
<p className="text-xs leading-none text-muted-foreground truncate">
293+
{session.user?.email}
294+
</p>
295+
</div>
296+
</div>
297+
</div>
298+
</DropdownMenuLabel>
299+
<DropdownMenuSeparator />
300+
<DropdownMenuItem
301+
onClick={() => handleSectionChange("settings")}
302+
className="cursor-pointer"
303+
>
304+
<Settings className="mr-2 h-4 w-4" />
305+
<span>Settings</span>
306+
</DropdownMenuItem>
307+
<DropdownMenuItem
308+
onClick={handleHomeClick}
309+
className="cursor-pointer"
310+
>
311+
<Home className="mr-2 h-4 w-4" />
312+
<span>Home</span>
313+
</DropdownMenuItem>
314+
<DropdownMenuSeparator />
315+
<DropdownMenuItem
316+
className="cursor-pointer text-red-600 focus:text-red-600 focus:bg-red-50 dark:focus:bg-red-950"
317+
onClick={handleSignOut}
318+
>
319+
<LogOut className="mr-2 h-4 w-4" />
320+
<span>Log out</span>
321+
</DropdownMenuItem>
322+
</DropdownMenuContent>
323+
</DropdownMenu>
324+
)}
325+
</div>
213326
</header>
214327
<main className="flex-1 overflow-y-auto">
215328
<Dashboard activeSection={activeSection} onSectionChange={handleSectionChange} />

frontend/app/components/Landing.tsx

Lines changed: 6 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@
22
import { MarketDataCenter } from "@/components/market-data-center";
33
import { Sidebar } from "@/components/sidebar";
44
import { StockTicker } from "@/components/stock-ticker";
5-
import { ThemeToggle } from "@/components/theme-toggle";
65
import { TreasuryBillSection } from "@/components/treasury-bill-section";
76
import { Badge } from "@/components/ui/badge";
87
import { Button } from "@/components/ui/button";
98
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
109
import { portfolioStocks } from "@/data/mock-data";
1110
import clsx from "clsx";
1211
import { type Variants } from "framer-motion";
13-
import { BarChart2, ChartLine, CheckCircle, CircleDollarSign, LineChart, LogIn, PieChart, TrendingUp, XCircle } from "lucide-react";
12+
import { BarChart2, ChartLine, CheckCircle, CircleDollarSign, LineChart, PieChart, TrendingUp, XCircle } from "lucide-react";
1413
import Link from "next/link";
1514
import { usePathname } from "next/navigation";
1615
import { useEffect, useRef, useState } from "react";
1716
import dash from '../../../Dashboard.png';
1817
import { CardSpotlight } from "../../components/ui/card-spotlight";
1918
import { ContainerScroll } from '../../components/ui/container-scroll-animation';
2019
import Testimonials from './Testimonials';
20+
import Navbar from './navbar';
2121
// Declare the global window interface extension
2222
declare global {
2323
interface Window {
@@ -171,64 +171,17 @@ export default function Landing() {
171171
return (
172172
<div className="min-h-screen flex flex-col">
173173

174-
{/* Header */}
175-
<header className="border-b backdrop-blur-lg bg-background/80 sticky top-0 z-50">
176-
174+
{/* Header with Progress Bar */}
175+
<div className="sticky top-0 z-50">
177176
{/* Progress Bar */}
178177
<div
179178
ref={progressBarRef}
180179
className="h-1 w-full origin-left will-change-transform transform-gpu rounded-full bg-gradient-to-r from-cyan-400 via-blue-400 to-purple-500 shadow-[0_0_10px_rgba(59,130,246,0.8),0_0_20px_rgba(139,92,246,0.6)]"
181180
style={{ transform: 'scaleX(0)' }}
182181
aria-hidden="true"
183182
/>
184-
185-
<div className="container mx-auto px-4 py-4 flex justify-between items-center">
186-
<div
187-
className="flex items-center gap-2 cursor-pointer"
188-
onClick={() => setSidebarOpen(true)}
189-
>
190-
<BarChart2 className="h-6 w-6 text-primary" />
191-
<span className="font-extrabold text-xl">StockVision</span>
192-
</div>
193-
194-
{/* Right Section */}
195-
<div className="flex items-center gap-4">
196-
<ThemeToggle />
197-
<Link href="/dashboard">
198-
<Button
199-
className="relative overflow-hidden font-bold flex items-center gap-2 px-6 py-3
200-
rounded-lg bg-gradient-to-r from-blue-600 to-indigo-600
201-
text-white hover:scale-105 transition-transform"
202-
>
203-
<span className="relative z-10 flex items-center gap-2">
204-
<LogIn className="h-4 w-4" />
205-
<span className="hidden sm:inline">Sign In</span>
206-
</span>
207-
208-
{/* shimmer overlay */}
209-
<span className="absolute inset-0 bg-gradient-to-r from-transparent via-white/40 to-transparent
210-
translate-x-[-100%] animate-[shimmer_2s_infinite]" />
211-
</Button>
212-
</Link>
213-
214-
{/* <div className="container mx-auto px-4 py-4 flex justify-between items-center">
215-
<div className="flex items-center gap-2" onClick={() => setSidebarOpen(true)}>
216-
<BarChart2 className="h-6 w-6 text-primary" />
217-
<span className="font-extrabold text-xl">StockVision</span>
218-
</div>
219-
<div className="flex items-center gap-4">
220-
<ThemeToggle />
221-
<Link href="/dashboard">
222-
<Button className="font-bold hover:scale-105 transition-transform flex items-center gap-2">
223-
<LogIn className="h-4 w-4" />
224-
<span className="hidden sm:inline">Sign In</span>
225-
</Button>
226-
</Link>
227-
</div>
228-
</div> */}
229-
</div>
230-
</div>
231-
</header>
183+
<Navbar onMenuClick={() => setSidebarOpen(true)} />
184+
</div>
232185

233186

234187
{/* Sidebar */}

0 commit comments

Comments
 (0)