Spaces:
Sleeping
Sleeping
| import { Navigate, useLocation } from 'react-router-dom'; | |
| import { useAuth } from '../../contexts/AuthContext'; | |
| import Loader from './Loader'; | |
| /** | |
| * ProtectedRoute — Guards routes based on authentication, email verification, and roles. | |
| * @param {Object} props | |
| * @param {React.ReactNode} props.children - Child components to render | |
| * @param {string[]} [props.allowedRoles] - Array of allowed roles (empty = any authenticated user) | |
| * @param {string} [props.redirectTo] - Where to redirect if not authenticated | |
| * @param {boolean} [props.requireVerified] - If true, user must have verified their email | |
| */ | |
| export default function ProtectedRoute({ | |
| children, | |
| allowedRoles = [], | |
| redirectTo = '/login', | |
| requireVerified = true, | |
| }) { | |
| const { currentUser, userProfile, loading } = useAuth(); | |
| const location = useLocation(); | |
| if (loading) { | |
| return <Loader fullScreen />; | |
| } | |
| // Not authenticated → send to login | |
| if (!currentUser) { | |
| return <Navigate to={redirectTo} state={{ from: location }} replace />; | |
| } | |
| // Authenticated but email not verified → send to verify-email page | |
| // Google sign-ins are already considered verified by Firebase (emailVerified = true) | |
| if (requireVerified && !currentUser.emailVerified) { | |
| return <Navigate to="/verify-email" state={{ from: location }} replace />; | |
| } | |
| // Check role if specified | |
| if (allowedRoles.length > 0 && userProfile) { | |
| if (!allowedRoles.includes(userProfile.role)) { | |
| return <Navigate to="/unauthorized" replace />; | |
| } | |
| } | |
| return children; | |
| } | |