diff --git a/apps/web/src/features/dashboard/RoleDashboardRedirect.tsx b/apps/web/src/features/dashboard/RoleDashboardRedirect.tsx
new file mode 100644
index 00000000..5392f2b3
--- /dev/null
+++ b/apps/web/src/features/dashboard/RoleDashboardRedirect.tsx
@@ -0,0 +1,27 @@
+import React, {useEffect} from 'react';
+import { useNavigate } from 'react-router-dom';
+import { useSelector } from 'react-redux';
+import { getDashboardPath } from '../../services/firestoreService'
+import type { RootState } from '../../store/store';
+/**
+ * RoleDashboardRedirect Component
+ * Dynamically redirects users to their appropriate dashboard based on their role
+ */
+export const RoleDashboardRedirect: React.FC = () => {
+ const { isAuthenticated, user } = useSelector((state: RootState) => state.auth);
+ const navigate = useNavigate();
+
+ useEffect(() => {
+ if (!isAuthenticated) {
+ navigate('/login', { replace: true });
+ return;
+ }
+
+ if (user?.userRole) {
+ const dashboardPath = getDashboardPath(user.userRole);
+ navigate(dashboardPath, { replace: true });
+ }
+ }, [isAuthenticated, user?.userRole, navigate]);
+
+ return null;
+};
\ No newline at end of file
diff --git a/apps/web/src/features/layouts/AppLayout.tsx b/apps/web/src/features/layouts/AppLayout.tsx
index 8ce252f7..3db7da5e 100644
--- a/apps/web/src/features/layouts/AppLayout.tsx
+++ b/apps/web/src/features/layouts/AppLayout.tsx
@@ -10,6 +10,7 @@ import {
} from 'lucide-react';
import Sidebar from './Sidebar';
import { getDashboardPath } from '../../services/firestoreService';
+import { useSessionPersistence } from '../../hooks/useSessionPersistence';
/**
* Main Application Layout for Authenticated Users.
@@ -17,6 +18,9 @@ import { getDashboardPath } from '../../services/firestoreService';
* Handles role-based navigation rendering and validates user access to dashboard routes.
*/
const AppLayout: React.FC = () => {
+ // Initialize session persistence and token refresh
+ useSessionPersistence();
+
// Typed selectors
const { isAuthenticated, user } = useSelector((state: RootState) => state.auth);
const dispatch = useDispatch
();
@@ -47,7 +51,10 @@ const AppLayout: React.FC = () => {
}
const handleLogout = () => {
- dispatch(logoutUser());
+ dispatch(logoutUser()).then(() => {
+ // Navigate to login page after logout is complete
+ navigate('/login', { replace: true });
+ });
};
return (
diff --git a/apps/web/src/features/layouts/DashboardLayout.tsx b/apps/web/src/features/layouts/DashboardLayout.tsx
new file mode 100644
index 00000000..219deff4
--- /dev/null
+++ b/apps/web/src/features/layouts/DashboardLayout.tsx
@@ -0,0 +1,48 @@
+import React from 'react';
+import PageHeader from '../../common/components/PageHeader';
+import { motion } from 'framer-motion';
+
+interface DashboardLayoutProps {
+ title: string;
+ subtitle?: string;
+ actions?: React.ReactNode;
+ children: React.ReactNode;
+ maxWidth?: string;
+ backAction?: React.ReactNode;
+}
+
+const DashboardLayout: React.FC = ({
+ title,
+ subtitle,
+ actions,
+ children,
+ maxWidth = 'max-w-7xl',
+ backAction
+}) => {
+ return (
+
+
+ {backAction && (
+
+ {backAction}
+
+ )}
+
+
+
+ {children}
+
+
+ );
+};
+
+export default DashboardLayout;
diff --git a/apps/web/src/features/layouts/PublicLayout.tsx b/apps/web/src/features/layouts/PublicLayout.tsx
new file mode 100644
index 00000000..ea4d1045
--- /dev/null
+++ b/apps/web/src/features/layouts/PublicLayout.tsx
@@ -0,0 +1,23 @@
+import React from 'react';
+
+interface PublicLayoutProps {
+ children: React.ReactNode;
+}
+
+/**
+ * Layout for public, unauthenticated pages (e.g. Login, Forgot Password).
+ * Provides a centered container with a gradient background.
+ */
+const PublicLayout: React.FC = ({ children }) => {
+ return (
+
+ {/* Background decoration */}
+
+
+ {children}
+
+
+ );
+};
+
+export default PublicLayout;
\ No newline at end of file
diff --git a/apps/web/src/features/layouts/Sidebar.tsx b/apps/web/src/features/layouts/Sidebar.tsx
index d230f205..401b4043 100644
--- a/apps/web/src/features/layouts/Sidebar.tsx
+++ b/apps/web/src/features/layouts/Sidebar.tsx
@@ -1,5 +1,5 @@
import React, { useMemo } from 'react';
-import { Link, useLocation } from 'react-router-dom';
+import { Link, useLocation, useNavigate } from 'react-router-dom';
import { LogOut, Menu, X } from 'lucide-react';
import { Button } from '../../common/components/ui/button';
import { NAV_CONFIG } from "../../common/config/navigation";
@@ -22,6 +22,19 @@ const Sidebar: React.FC = ({
onLogout
}) => {
const location = useLocation();
+ const navigate = useNavigate();
+
+ /**
+ * Handle logout with navigation
+ * Ensures user is redirected to login page after logout
+ */
+ const handleLogoutClick = async () => {
+ onLogout();
+ // Small delay to allow logout to complete before navigation
+ setTimeout(() => {
+ navigate('/login', { replace: true });
+ }, 100);
+ };
// Filter navigation based on user role
const filteredNav = useMemo(() => {
@@ -107,7 +120,7 @@ const Sidebar: React.FC = ({