+ {/* Mobile menu toggle */}
+
PC
diff --git a/src/components/dashboard/Sidebar.tsx b/src/components/dashboard/Sidebar.tsx
index 3a2cc5ef..bc5918b0 100644
--- a/src/components/dashboard/Sidebar.tsx
+++ b/src/components/dashboard/Sidebar.tsx
@@ -1,140 +1,202 @@
-// 'use client';
+'use client';
-// import { motion, AnimatePresence } from "framer-motion";
-// import {
-// LayoutDashboard,
-// Building2,
-// BarChart3,
-// Wallet,
-// FileText,
-// Settings,
-// HelpCircle,
-// ChevronLeft,
-// X
-// } from "lucide-react";
+import Link from 'next/link';
+import { usePathname } from 'next/navigation';
+import {
+ LayoutDashboard,
+ Building2,
+ BarChart3,
+ Wallet,
+ FileText,
+ Settings,
+ HelpCircle,
+ X,
+ ChevronLeft,
+} from 'lucide-react';
+import { cn } from '@/lib/utils';
+import { Button } from '@/components/ui/button';
-// interface SidebarProps {
-// isOpen: boolean;
-// onClose: () => void;
-// activeItem?: string;
-// onItemClick?: (item: string) => void;
-// }
+const navItems = [
+ { href: '/dashboard', label: 'Dashboard', icon: LayoutDashboard },
+ { href: '/properties', label: 'Properties', icon: Building2 },
+ { href: '/dashboard?tab=analytics', label: 'Analytics', icon: BarChart3 },
+ { href: '/dashboard?tab=wallet', label: 'Wallet', icon: Wallet },
+ { href: '/tax-report', label: 'Reports', icon: FileText },
+];
-// const menuItems = [
-// { id: "dashboard", label: "Dashboard", icon: LayoutDashboard },
-// { id: "properties", label: "Properties", icon: Building2 },
-// { id: "analytics", label: "Analytics", icon: BarChart3 },
-// { id: "wallet", label: "Wallet", icon: Wallet },
-// { id: "reports", label: "Reports", icon: FileText },
-// ];
+const bottomItems = [
+ { href: '/dashboard?tab=settings', label: 'Settings', icon: Settings },
+ { href: '/dashboard?tab=help', label: 'Help & Support', icon: HelpCircle },
+];
-// const bottomItems = [
-// { id: "settings", label: "Settings", icon: Settings },
-// { id: "help", label: "Help & Support", icon: HelpCircle },
-// ];
+interface SidebarProps {
+ isOpen: boolean;
+ isCollapsed: boolean;
+ onClose: () => void;
+ onToggleCollapse: () => void;
+}
-// export const Sidebar = ({ isOpen, onClose, activeItem = "dashboard", onItemClick }: SidebarProps) => {
-// const SidebarContent = () => (
-//
-// {/* Logo section for mobile */}
-//
-//
-//
-// M
-//
-//
-//
MettaChain
-//
-//
-//
-//
+function NavLink({
+ href,
+ label,
+ icon: Icon,
+ isActive,
+ isCollapsed,
+ onClick,
+}: {
+ href: string;
+ label: string;
+ icon: React.ElementType;
+ isActive: boolean;
+ isCollapsed: boolean;
+ onClick?: () => void;
+}) {
+ return (
+
+
+ {!isCollapsed && (
+ <>
+
{label}
+ {isActive &&
}
+ >
+ )}
+
+ );
+}
-// {/* Navigation */}
-//
+function SidebarContent({
+ isCollapsed,
+ onClose,
+ onToggleCollapse,
+ isMobileDrawer,
+}: {
+ isCollapsed: boolean;
+ onClose: () => void;
+ onToggleCollapse: () => void;
+ isMobileDrawer?: boolean;
+}) {
+ const pathname = usePathname();
-// {/* Bottom section */}
-//
-// {bottomItems.map((item) => (
-//
-// ))}
-//
+ return (
+
+ {/* Header */}
+
+ {(!isCollapsed || isMobileDrawer) && (
+
+ )}
+ {isMobileDrawer ? (
+
+ ) : (
+
+ )}
+
-// {/* Upgrade card */}
-//
-//
-//
Upgrade to Pro
-//
Unlock advanced analytics and premium features
-//
-//
-//
-//
-// );
+ {/* Main nav */}
+
-// return (
-// <>
-// {/* Desktop sidebar */}
-//
+ {/* Bottom nav */}
+
+ {bottomItems.map((item) => (
+
+ ))}
+
+
+ );
+}
-// {/* Mobile sidebar overlay */}
-//
-// {isOpen && (
-// <>
-//
-//
-//
-//
-// >
-// )}
-//
-// >
-// );
-// };
+export function Sidebar({ isOpen, isCollapsed, onClose, onToggleCollapse }: SidebarProps) {
+ return (
+ <>
+ {/* Desktop sidebar */}
+
+
+ {/* Mobile overlay */}
+ {isOpen && (
+
+ )}
+
+ {/* Mobile drawer */}
+
+ >
+ );
+}
diff --git a/src/components/dashboard/__tests__/Sidebar.test.tsx b/src/components/dashboard/__tests__/Sidebar.test.tsx
new file mode 100644
index 00000000..07bff5ff
--- /dev/null
+++ b/src/components/dashboard/__tests__/Sidebar.test.tsx
@@ -0,0 +1,75 @@
+import React from 'react';
+import { render, screen, fireEvent } from '@testing-library/react';
+import { Sidebar } from '../Sidebar';
+
+// Mock next/navigation
+jest.mock('next/navigation', () => ({
+ usePathname: () => '/dashboard',
+}));
+
+// Mock next/link
+jest.mock('next/link', () => {
+ const Link = ({ href, children, ...props }: { href: string; children: React.ReactNode; [key: string]: unknown }) => (
+
{children}
+ );
+ Link.displayName = 'Link';
+ return Link;
+});
+
+const defaultProps = {
+ isOpen: false,
+ isCollapsed: false,
+ onClose: jest.fn(),
+ onToggleCollapse: jest.fn(),
+};
+
+describe('Sidebar', () => {
+ beforeEach(() => jest.clearAllMocks());
+
+ it('renders navigation links', () => {
+ render(
);
+ expect(screen.getAllByText('Dashboard').length).toBeGreaterThan(0);
+ expect(screen.getAllByText('Properties').length).toBeGreaterThan(0);
+ });
+
+ it('highlights the active route', () => {
+ render(
);
+ const activeLinks = screen.getAllByRole('link', { name: /dashboard/i });
+ const activeLink = activeLinks.find((el) => el.getAttribute('aria-current') === 'page');
+ expect(activeLink).toBeTruthy();
+ });
+
+ it('shows mobile drawer when isOpen is true', () => {
+ render(
);
+ // The mobile overlay should be present
+ const overlay = document.querySelector('[aria-hidden="true"]');
+ expect(overlay).toBeTruthy();
+ });
+
+ it('calls onClose when overlay is clicked', () => {
+ const onClose = jest.fn();
+ render(
);
+ const overlay = document.querySelector('[aria-hidden="true"]') as HTMLElement;
+ fireEvent.click(overlay);
+ expect(onClose).toHaveBeenCalledTimes(1);
+ });
+
+ it('calls onToggleCollapse when collapse button is clicked on desktop', () => {
+ const onToggleCollapse = jest.fn();
+ render(
);
+ const collapseBtn = screen.getByRole('button', { name: /collapse sidebar/i });
+ fireEvent.click(collapseBtn);
+ expect(onToggleCollapse).toHaveBeenCalledTimes(1);
+ });
+
+ it('hides labels when collapsed', () => {
+ render(
);
+ // Desktop sidebar should not show text labels (they're hidden via conditional render)
+ // The desktop aside is hidden on mobile, so we check the desktop aside
+ const desktopAside = document.querySelector('aside.hidden.lg\\:flex');
+ expect(desktopAside).toBeTruthy();
+ // Labels should not be in the desktop sidebar when collapsed
+ const labelsInDesktop = desktopAside?.querySelectorAll('span');
+ expect(labelsInDesktop?.length).toBe(0);
+ });
+});