From ae1e4c67de3d6cf52fbe71967da59fbdba036482 Mon Sep 17 00:00:00 2001 From: Admin Date: Wed, 29 Apr 2026 14:02:42 +0330 Subject: [PATCH] improvement: sidebar refactored. COMMING SOON page added for all non-developed tabs. --- .../src/app/(dashboard)/appointments/page.tsx | 10 +++ frontend/src/app/(dashboard)/lab/page.tsx | 10 +++ frontend/src/app/(dashboard)/layout.tsx | 55 +++++++++---- frontend/src/app/(dashboard)/reports/page.tsx | 10 +++ frontend/src/app/(dashboard)/staff/page.tsx | 10 +++ frontend/src/components/ui/Sidebar.tsx | 18 +++-- frontend/src/lib/hooks/useAuth.tsx | 81 +++++++++++-------- 7 files changed, 137 insertions(+), 57 deletions(-) create mode 100644 frontend/src/app/(dashboard)/appointments/page.tsx create mode 100644 frontend/src/app/(dashboard)/lab/page.tsx create mode 100644 frontend/src/app/(dashboard)/reports/page.tsx create mode 100644 frontend/src/app/(dashboard)/staff/page.tsx diff --git a/frontend/src/app/(dashboard)/appointments/page.tsx b/frontend/src/app/(dashboard)/appointments/page.tsx new file mode 100644 index 0000000..d638c9f --- /dev/null +++ b/frontend/src/app/(dashboard)/appointments/page.tsx @@ -0,0 +1,10 @@ +export default function AppointmentsPage() { + return ( +
+

Appointments

+

+ Appointments module is coming soon. +

+
+ ); +} diff --git a/frontend/src/app/(dashboard)/lab/page.tsx b/frontend/src/app/(dashboard)/lab/page.tsx new file mode 100644 index 0000000..42c2cab --- /dev/null +++ b/frontend/src/app/(dashboard)/lab/page.tsx @@ -0,0 +1,10 @@ +export default function LabPage() { + return ( +
+

Lab Management

+

+ Lab management module is coming soon. +

+
+ ); +} diff --git a/frontend/src/app/(dashboard)/layout.tsx b/frontend/src/app/(dashboard)/layout.tsx index be84b47..62735b2 100644 --- a/frontend/src/app/(dashboard)/layout.tsx +++ b/frontend/src/app/(dashboard)/layout.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useEffect } from 'react'; +import { memo, useCallback, useEffect } from 'react'; import { useRouter } from 'next/navigation'; import { useAuth } from '@/lib/hooks/useAuth'; import Sidebar from '@/components/ui/Sidebar'; @@ -10,6 +10,9 @@ import { LogOut } from 'lucide-react'; export default function DashboardLayout({ children }: { children: React.ReactNode }) { const { user, currentOrganization, isAuthReady, logout } = useAuth(); const router = useRouter(); + const handleLogout = useCallback(() => { + void logout(); + }, [logout]); // ✅ AUTH GUARD (runs once per navigation group) useEffect(() => { @@ -48,21 +51,11 @@ export default function DashboardLayout({ children }: { children: React.ReactNod
-
-

{currentOrganization.name}

- -
- - {user.name} - -
-
+
@@ -72,4 +65,32 @@ export default function DashboardLayout({ children }: { children: React.ReactNod
); -} \ No newline at end of file +} + +const DashboardHeader = memo(function DashboardHeader({ + organizationName, + userName, + onLogout, +}: { + organizationName: string; + userName: string; + onLogout: () => void; +}) { + return ( +
+

{organizationName}

+ +
+ + {userName} + +
+
+ ); +}); \ No newline at end of file diff --git a/frontend/src/app/(dashboard)/reports/page.tsx b/frontend/src/app/(dashboard)/reports/page.tsx new file mode 100644 index 0000000..0d53048 --- /dev/null +++ b/frontend/src/app/(dashboard)/reports/page.tsx @@ -0,0 +1,10 @@ +export default function ReportsPage() { + return ( +
+

Reports

+

+ Reports module is coming soon. +

+
+ ); +} diff --git a/frontend/src/app/(dashboard)/staff/page.tsx b/frontend/src/app/(dashboard)/staff/page.tsx new file mode 100644 index 0000000..e7167d2 --- /dev/null +++ b/frontend/src/app/(dashboard)/staff/page.tsx @@ -0,0 +1,10 @@ +export default function StaffPage() { + return ( +
+

Staff Management

+

+ Staff management module is coming soon. +

+
+ ); +} diff --git a/frontend/src/components/ui/Sidebar.tsx b/frontend/src/components/ui/Sidebar.tsx index 427539e..f3c59d3 100644 --- a/frontend/src/components/ui/Sidebar.tsx +++ b/frontend/src/components/ui/Sidebar.tsx @@ -1,6 +1,8 @@ 'use client'; -import { usePathname, useRouter } from 'next/navigation'; +import Link from 'next/link'; +import { memo } from 'react'; +import { usePathname } from 'next/navigation'; import { LayoutDashboard, Users, @@ -21,9 +23,8 @@ const menu = [ { name: 'Reports', path: '/reports', icon: FileText }, ]; -export default function Sidebar() { +function Sidebar() { const pathname = usePathname(); - const router = useRouter(); return ( ); -} \ No newline at end of file +} + +export default memo(Sidebar); \ No newline at end of file diff --git a/frontend/src/lib/hooks/useAuth.tsx b/frontend/src/lib/hooks/useAuth.tsx index 1f80eda..a97d5b0 100644 --- a/frontend/src/lib/hooks/useAuth.tsx +++ b/frontend/src/lib/hooks/useAuth.tsx @@ -1,6 +1,6 @@ 'use client'; -import React, { createContext, useContext, useEffect, useState } from 'react'; +import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'; import { useRouter } from 'next/navigation'; import { authApi } from '@/lib/api/auth'; import { User, Organization } from '@/types'; @@ -37,11 +37,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { const router = useRouter(); - useEffect(() => { - checkAuth(); - }, []); - - const normalizeProfilePayload = (payload: any): { user: User | null; organizations: Organization[] } => { + const normalizeProfilePayload = useCallback((payload: any): { user: User | null; organizations: Organization[] } => { const organizations = payload?.organizations || []; if (payload?.user) { @@ -60,9 +56,9 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { } return { user: null, organizations }; - }; + }, []); - const checkAuth = async () => { + const checkAuth = useCallback(async () => { try { setIsLoading(true); @@ -103,10 +99,14 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { setIsLoading(false); setIsAuthReady(true); } - }; + }, [normalizeProfilePayload]); + + useEffect(() => { + void checkAuth(); + }, [checkAuth]); // ✅ REGISTER - const registerTrial = async ( + const registerTrial = useCallback(async ( email: string, password: string, name: string, @@ -147,10 +147,10 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { } finally { setIsLoading(false); } - }; + }, [router]); // ✅ LOGIN - const login = async (email: string, password: string) => { + const login = useCallback(async (email: string, password: string) => { try { setIsLoading(true); setError(null); @@ -178,17 +178,17 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { } finally { setIsLoading(false); } - }; + }, [router]); - const logout = async () => { + const logout = useCallback(async () => { localStorage.clear(); setUser(null); setOrganizations([]); setCurrentOrganization(null); router.push('/'); - }; + }, [router]); - const selectOrganization = async (orgId: string) => { + const selectOrganization = useCallback(async (orgId: string) => { try { setIsLoading(true); @@ -208,26 +208,41 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { } finally { setIsLoading(false); } - }; + }, [router]); - const clearError = () => setError(null); + const clearError = useCallback(() => setError(null), []); + + const contextValue = useMemo( + () => ({ + user, + organizations, + currentOrganization, + isLoading, + isAuthReady, + error, + registerTrial, + login, + logout, + selectOrganization, + clearError, + }), + [ + user, + organizations, + currentOrganization, + isLoading, + isAuthReady, + error, + registerTrial, + login, + logout, + selectOrganization, + clearError, + ], + ); return ( - + {children} );