From 7e414207d6d85d316c1c9f3c65730c00d60be040 Mon Sep 17 00:00:00 2001 From: priyanshuvish Date: Tue, 11 Nov 2025 11:57:39 +0530 Subject: [PATCH] fix nav expand --- src/App.tsx | 1 - src/components/layout/AuthenticatedLayout.tsx | 136 ++++++++++-------- src/components/pages/ContentManager.tsx | 43 +++--- 3 files changed, 100 insertions(+), 80 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index a7672e9..4acdb56 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -271,7 +271,6 @@ export default function App() { return ; // Updated content routes section - // In App.tsx - Update the content routes section case "/content": case "/content/profiler": case "/content/blogs": diff --git a/src/components/layout/AuthenticatedLayout.tsx b/src/components/layout/AuthenticatedLayout.tsx index 179bb55..2f6817f 100644 --- a/src/components/layout/AuthenticatedLayout.tsx +++ b/src/components/layout/AuthenticatedLayout.tsx @@ -1,16 +1,16 @@ import React, { useState, useEffect } from 'react'; import { Button } from '../ui/button'; import { NotificationPanel, Notification } from '../NotificationPanel'; -import { - Home, - FileText, - GraduationCap, - Users, - Calendar, - Globe, - BarChart3, - Settings, - Menu, +import { + Home, + FileText, + GraduationCap, + Users, + Calendar, + Globe, + BarChart3, + Settings, + Menu, ChevronLeft, LogOut, User, @@ -28,7 +28,7 @@ import { ChevronDown, Target } from 'lucide-react'; -import { +import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, @@ -37,7 +37,7 @@ import { BreadcrumbSeparator, } from '../ui/breadcrumb'; import { Avatar, AvatarFallback } from '../ui/avatar'; -import { +import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, @@ -112,10 +112,10 @@ const navigationItems: NavigationItem[] = [ route: '/content', children: [ { - id: 'profiler', - label: 'Profiler', - icon: Target, - route: '/content' + id: 'profiler', + label: 'Profiler', + icon: Target, + route: '/content/profiler' }, { id: 'blogs', @@ -257,7 +257,7 @@ const useAutoSave = ( // Save to localStorage for persistence localStorage.setItem(`autosave_${userId}_${currentRoute}`, JSON.stringify(autoSaveData)); onAutoSave(formData); - + // Show subtle toast notification toast.success("Draft saved", { duration: 1000 }); }, SESSION_CONFIG.AUTO_SAVE_INTERVAL); @@ -301,7 +301,7 @@ const useSessionTimeout = (onLogout: () => void) => { // Activity listeners const resetOnActivity = () => resetTimers(); - + // Listen for user activity const events = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart']; events.forEach(event => { @@ -320,12 +320,12 @@ const useSessionTimeout = (onLogout: () => void) => { }, [onLogout]); }; -export function AuthenticatedLayout({ - children, - currentRoute, - onNavigate, - onLogout, - user, +export function AuthenticatedLayout({ + children, + currentRoute, + onNavigate, + onLogout, + user, breadcrumbs = [], formData, onAutoSave, @@ -350,10 +350,10 @@ export function AuthenticatedLayout({ // Auto-expand parent items when on child routes useEffect(() => { const newExpandedItems = new Set(); - + navigationItems.forEach(item => { if (item.children) { - const isChildActive = item.children.some(child => + const isChildActive = item.children.some(child => isActiveRoute(child.route) ); if (isChildActive) { @@ -361,13 +361,14 @@ export function AuthenticatedLayout({ } } }); - + setExpandedItems(newExpandedItems); }, [currentRoute]); + // Notification handlers const handleMarkAsRead = (notificationId: string) => { - setLocalNotifications(prev => + setLocalNotifications(prev => prev.map(n => n.id === notificationId ? { ...n, read: true } : n) ); if (onMarkNotificationAsRead) { @@ -408,22 +409,32 @@ export function AuthenticatedLayout({ const isActiveRoute = (route: string) => { if (!currentRoute || !route) return false; - + // Exact match if (currentRoute === route) return true; - + // User routes if (route === '/users/individual' && currentRoute.startsWith('/users/')) return true; - - // Content routes - match both parent and children - if (route === '/content' && currentRoute.startsWith('/content/')) return true; - + + // Content section — highlight both parent and child routes + if (route === '/content') { + return currentRoute.startsWith('/content'); + } + + // Child route check + if (route.startsWith('/content/')) { + return currentRoute === route || currentRoute.startsWith(route + '/'); + } + return false; }; const getActiveParent = (items: NavigationItem[]): string | null => { for (const item of items) { + // Check if this item is active if (isActiveRoute(item.route)) return item.id; + + // Check if any children are active if (item.children) { for (const child of item.children) { if (isActiveRoute(child.route)) return item.id; @@ -453,31 +464,43 @@ export function AuthenticatedLayout({ const expanded = isExpanded(item.id); const Icon = item.icon; + // const handleItemClick = () => { + // if (hasChildren && !isChild) { + // // Always expand when parent clicked + // const newExpandedItems = new Set(expandedItems); + // newExpandedItems.add(item.id); + // setExpandedItems(newExpandedItems); + + // // Navigate to parent route (like /content) + // onNavigate(item.route); + // } else { + // // Navigate directly for child items + // onNavigate(item.route); + // } + // }; + const handleItemClick = () => { if (hasChildren && !isChild) { - // Toggle dropdown for parent items + // Toggle dropdown open/close when clicking parent toggleExpanded(item.id); - // If not active and has children, navigate to first child - if (!isActive && item.children && item.children.length > 0) { - onNavigate(item.children[0].route); - } } else { // Navigate directly for child items or items without children onNavigate(item.route); } }; + + return (
- + {/* Render children if dropdown is expanded and not collapsed */} {item.children && expanded && !sidebarCollapsed && (
@@ -511,7 +533,7 @@ export function AuthenticatedLayout({ - onNavigate('/dashboard')} className="cursor-pointer" > @@ -523,7 +545,7 @@ export function AuthenticatedLayout({ {crumb.href && index < breadcrumbs.length - 1 ? ( - onNavigate(crumb.href!)} className="cursor-pointer" > @@ -537,7 +559,7 @@ export function AuthenticatedLayout({ ))} - + {/* Notification Bell */} {/* Left Sidebar */} -
{!sidebarCollapsed && ( - Kautilya Leadership Centre )} diff --git a/src/components/pages/ContentManager.tsx b/src/components/pages/ContentManager.tsx index 819b1f0..2bfb766 100644 --- a/src/components/pages/ContentManager.tsx +++ b/src/components/pages/ContentManager.tsx @@ -132,25 +132,25 @@ export function ContentManager({ const getCurrentContentType = () => { console.log('🔄 getCurrentContentType called with currentRoute:', currentRoute); - + // Find exact route match first const exactMatch = contentTypes.find(type => currentRoute === type.route); if (exactMatch) { console.log('✅ Exact route match found:', exactMatch.id); return exactMatch; } - + // Find partial match for nested routes - const partialMatch = contentTypes.find(type => - currentRoute.startsWith(type.route + '/') || + const partialMatch = contentTypes.find(type => + currentRoute.startsWith(type.route + '/') || currentRoute.includes(type.id) ); - + if (partialMatch) { console.log('✅ Partial route match found:', partialMatch.id); return partialMatch; } - + console.log('⚠️ No match found, defaulting to profiler'); return contentTypes[0]; // Default to profiler }; @@ -159,34 +159,33 @@ export function ContentManager({ console.log('📌 Current content type:', currentContentType.label); const getBreadcrumbs = () => { - const breadcrumbs = [ - { label: "Content", href: "/content" } - ]; + const breadcrumbs = [{ label: "Content", href: "/content" }]; - // Add specific content type to breadcrumbs if not on the main content page - if (currentRoute !== "/content") { + // Always show current content type + if (currentContentType) { breadcrumbs.push({ label: currentContentType.label }); } return breadcrumbs; }; + const renderContent = () => { console.log('🎨 Rendering content for:', currentContentType.id); - + switch (currentContentType.id) { case "profiler": return ; - + case "blogs": return ; - + case "faqs": return ; - + case "webcasts": return ; - + case "training-materials": return ( ); - + case "reading-materials": return ; - + case "podcasts": return ; - + case "case-studies": return ; - + case "klc-archives": return ( ); - + default: console.log('⚠️ Defaulting to profiler tab'); return ; @@ -237,7 +236,7 @@ export function ContentManager({ {currentContentType.label}

- {currentContentType.id === "profiler" + {currentContentType.id === "profiler" ? "Manage all content types and profiler submissions with approval workflow" : `Manage and organize ${currentContentType.label.toLowerCase()}` }