this repo has no description
at main 56 lines 1.7 kB view raw
1/** 2 * Protected Route Component 3 * Wraps routes that require authentication 4 */ 5 6import React from 'react'; 7import { Navigate, Outlet, useLocation } from 'react-router-dom'; 8import { useAuth } from '../../contexts/AuthContext'; 9 10interface ProtectedRouteProps { 11 children?: React.ReactNode; 12} 13 14export const ProtectedRoute: React.FC<ProtectedRouteProps> = ({ children }) => { 15 const { isAuthenticated, loading } = useAuth(); 16 const location = useLocation(); 17 18 // Show loading spinner while checking auth status 19 if (loading) { 20 return ( 21 <div className="min-h-screen flex items-center justify-center bg-gray-50"> 22 <div className="text-center"> 23 <svg 24 className="animate-spin h-8 w-8 text-blue-600 mx-auto" 25 xmlns="http://www.w3.org/2000/svg" 26 fill="none" 27 viewBox="0 0 24 24" 28 > 29 <circle 30 className="opacity-25" 31 cx="12" 32 cy="12" 33 r="10" 34 stroke="currentColor" 35 strokeWidth="4" 36 /> 37 <path 38 className="opacity-75" 39 fill="currentColor" 40 d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" 41 /> 42 </svg> 43 <p className="mt-2 text-sm text-gray-600">Loading...</p> 44 </div> 45 </div> 46 ); 47 } 48 49 // Redirect to login if not authenticated 50 if (!isAuthenticated) { 51 return <Navigate to="/login" state={{ from: location }} replace />; 52 } 53 54 // Render children or outlet for nested routes 55 return children || <Outlet />; 56};