diff --git a/apps/web/app/influencer-dashboard/layout.tsx b/apps/web/app/influencer-dashboard/layout.tsx index d2583dd..df18fcb 100644 --- a/apps/web/app/influencer-dashboard/layout.tsx +++ b/apps/web/app/influencer-dashboard/layout.tsx @@ -1,9 +1,9 @@ "use client"; -import React, { useState } from "react"; +import React, { useState, useEffect, useRef } from "react"; import Link from "next/link"; import Image from "next/image"; -import { usePathname } from "next/navigation"; +import { useRouter, usePathname } from "next/navigation"; import { LayoutDashboard, Users, @@ -11,20 +11,70 @@ import { MessageSquare, Calendar, DollarSign, + LogOut, + Menu, X } from "lucide-react"; +import { useAuthStore } from "@/store/auth.store"; import RoleGuard from "@/components/rbac/RoleGuard"; -import DashboardHeader from "@/components/DashboardHeader"; +import api from "@/lib/axios.client"; import NotificationBell from "@/components/NotificationBell"; + export default function InfluencerDashboardLayout({ children, }: { children: React.ReactNode; }) { + const router = useRouter(); const pathname = usePathname(); + const { user, clearAuth } = useAuthStore(); + const [showLogoutModal, setShowLogoutModal] = useState(false); const [isSidebarOpen, setIsSidebarOpen] = useState(false); + const [profile, setProfile] = useState<{ fullName?: string; profileImageUrl?: string; companyName?: string } | null>(null); + const [isLoadingProfile, setIsLoadingProfile] = useState(true); + + // Fetch real profile data for name & photo + useEffect(() => { + setIsLoadingProfile(true); + api.get("/profile/get_profile") + .then((res) => setProfile(res.data.data)) + .catch(() => { }) // silently fail — fallback to auth store values + .finally(() => setIsLoadingProfile(false)); + }, []); + + const rawDisplayName = profile?.fullName || user?.fullName || user?.email?.split("@")[0] || "User"; + const displayName = rawDisplayName.trim() || "User"; + const profileImage = (profile?.profileImageUrl || user?.profileImageUrl || user?.profileImage || "").trim() || null; + + const dropdownRef = useRef(null); + + // Close dropdown on outside click + useEffect(() => { + function handleClickOutside(event: MouseEvent) { + if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { + setShowLogoutModal(false); + } + } + if (showLogoutModal) { + document.addEventListener("mousedown", handleClickOutside); + } + return () => { + document.removeEventListener("mousedown", handleClickOutside); + }; + }, [showLogoutModal]); + + const handleLogout = async () => { + try { + await api.post("/auth/logout"); + } catch (e) { + console.error("Logout error", e); + } finally { + clearAuth(); + router.push("/login"); + } + }; const navItems = [ { name: "Overview", href: "/influencer-dashboard", icon: LayoutDashboard }, @@ -36,8 +86,8 @@ export default function InfluencerDashboardLayout({ ]; return ( - -
+ +
{/* Mobile Sidebar Overlay */} {isSidebarOpen && ( @@ -61,6 +111,7 @@ export default function InfluencerDashboardLayout({
+