diff --git a/src/components/layout/DashboardLayout.tsx b/src/components/layout/DashboardLayout.tsx index 128826f..56e7f6a 100644 --- a/src/components/layout/DashboardLayout.tsx +++ b/src/components/layout/DashboardLayout.tsx @@ -20,6 +20,7 @@ import { Menu, MenuItem, Badge, + Collapse, } from '@mui/material'; import { Menu as MenuIcon, @@ -31,10 +32,16 @@ import { Logout, NotificationsNone, SearchRounded, - Group, - Home, + Groups, + RssFeed, PostAdd, - Message, + Chat, + ExpandLess, + ExpandMore, + Hub, + List as ListIcon, + AccountTree, + Map, } from '@mui/icons-material'; import BottomNavigation from '../navigation/BottomNavigation'; @@ -45,6 +52,7 @@ interface NavItem { icon: ReactNode; path: string; badge?: number; + children?: NavItem[]; } interface DashboardLayoutProps { @@ -56,18 +64,16 @@ const DashboardLayout = ({ children }: DashboardLayoutProps) => { const isMobile = useMediaQuery(theme.breakpoints.down('md')); const [mobileOpen, setMobileOpen] = useState(false); const [profileMenuAnchor, setProfileMenuAnchor] = useState(null); + const [expandedItems, setExpandedItems] = useState>(new Set(['Network'])); const location = useLocation(); const navigate = useNavigate(); const navItems: NavItem[] = [ - { text: 'Feed', icon: , path: '/feed' }, - { text: 'Contacts', icon: , path: '/contacts' }, - { text: 'Groups', icon: , path: '/groups' }, - { text: 'Posts & Offers', icon: , path: '/posts' }, - { text: 'Messages', icon: , path: '/messages' }, - { text: 'Import', icon: , path: '/import' }, - { text: 'Invite', icon: , path: '/invite' }, - { text: 'Join Network', icon: , path: '/onboarding' }, + { text: 'Feed', icon: , path: '/feed' }, + { text: 'Network', icon: , path: '/contacts' }, + { text: 'Groups', icon: , path: '/groups' }, + { text: 'Post', icon: , path: '/posts' }, + { text: 'Chat', icon: , path: '/messages' }, ]; const handleDrawerToggle = () => { @@ -89,66 +95,111 @@ const DashboardLayout = ({ children }: DashboardLayoutProps) => { } }; + const toggleExpanded = (itemText: string) => { + setExpandedItems(prev => { + const newSet = new Set(prev); + if (newSet.has(itemText)) { + newSet.delete(itemText); + } else { + newSet.add(itemText); + } + return newSet; + }); + }; + const isActiveRoute = (path: string) => { if (path === '/feed' && (location.pathname === '/' || location.pathname === '/feed')) return true; if (path !== '/feed' && location.pathname.startsWith(path)) return true; return false; }; + const isParentActive = (item: NavItem) => { + if (item.children) { + return item.children.some(child => isActiveRoute(child.path)); + } + return false; + }; + + const renderNavItem = (item: NavItem, level: number = 0) => { + const hasChildren = item.children && item.children.length > 0; + const isExpanded = expandedItems.has(item.text); + const isActive = isActiveRoute(item.path); + const isParentOfActive = isParentActive(item); + + return ( +
+ + { + if (hasChildren) { + toggleExpanded(item.text); + } else { + handleNavigation(item.path); + } + }} + selected={isActive || isParentOfActive} + sx={{ + mx: 1, + ml: level > 0 ? 3 : 1, + borderRadius: 2, + minHeight: 48, + '&.Mui-selected': { + backgroundColor: 'primary.main', + color: 'primary.contrastText', + ml: level > 0 ? 3 : 1, + mr: 2, + '&:hover': { + backgroundColor: 'primary.dark', + }, + '& .MuiListItemIcon-root': { + color: 'primary.contrastText', + }, + }, + }} + > + + {item.badge ? ( + + {item.icon} + + ) : ( + item.icon + )} + + + {hasChildren && ( + isExpanded ? : + )} + + + {hasChildren && ( + + + {item.children?.map((child) => renderNavItem(child, level + 1))} + + + )} +
+ ); + }; + const drawerContent = ( - - + + NAO - - Personal Network Hub - - - {navItems.map((item) => ( - - handleNavigation(item.path)} - selected={isActiveRoute(item.path)} - sx={{ - mx: 1, - borderRadius: 2, - minHeight: 48, - '&.Mui-selected': { - backgroundColor: 'primary.main', - color: 'primary.contrastText', - ml: 1, - mr: 2, - '&:hover': { - backgroundColor: 'primary.dark', - }, - '& .MuiListItemIcon-root': { - color: 'primary.contrastText', - }, - }, - }} - > - - {item.badge ? ( - - {item.icon} - - ) : ( - item.icon - )} - - - - - ))} + + {navItems.map((item) => renderNavItem(item))} diff --git a/src/components/navigation/BottomNavigation.tsx b/src/components/navigation/BottomNavigation.tsx index 1128bdc..4593c6b 100644 --- a/src/components/navigation/BottomNavigation.tsx +++ b/src/components/navigation/BottomNavigation.tsx @@ -5,11 +5,11 @@ import { Paper } from '@mui/material'; import { - Home, - People, + RssFeed, + Hub, PostAdd, - Message, - AccountCircle, + Chat, + Groups, } from '@mui/icons-material'; const BottomNavigation = () => { @@ -17,16 +17,27 @@ const BottomNavigation = () => { const navigate = useNavigate(); const navigationItems = [ - { label: 'Feed', icon: , path: '/feed' }, - { label: 'Contacts', icon: , path: '/contacts' }, - { label: 'Posts', icon: , path: '/posts' }, - { label: 'Messages', icon: , path: '/messages' }, - { label: 'Account', icon: , path: '/account' }, + { label: 'Feed', icon: , path: '/feed' }, + { label: 'Network', icon: , path: '/contacts' }, + { label: 'Groups', icon: , path: '/groups' }, + { label: 'Post', icon: , path: '/posts' }, + { label: 'Chat', icon: , path: '/messages' }, ]; const getCurrentValue = () => { const currentPath = location.pathname; if (currentPath === '/' || currentPath === '/feed') return '/feed'; + + // Handle network path - should highlight Network tab + if (currentPath.startsWith('/contacts')) { + return '/contacts'; + } + + // Groups has its own tab now + if (currentPath.startsWith('/groups')) { + return '/groups'; + } + const activeItem = navigationItems.find(item => item.path === currentPath || (item.path !== '/feed' && currentPath.startsWith(item.path)) ); diff --git a/src/pages/ContactListPage.tsx b/src/pages/ContactListPage.tsx index 94edcf4..08357ba 100644 --- a/src/pages/ContactListPage.tsx +++ b/src/pages/ContactListPage.tsx @@ -19,15 +19,16 @@ import { } from '@mui/material'; import { List as ListIcon, - AccountTree, - ScatterPlot, + Hub, + Map, Search, Add, LinkedIn, Phone, Email, QrCode, - Group + Group, + CloudDownload } from '@mui/icons-material'; import { dataService } from '../services/dataService'; import type { Contact } from '../types/contact'; @@ -109,11 +110,16 @@ const ContactListPage = () => { Contacts - - Manage your network of {filteredContacts.length} contacts - +