92 lines
3.1 KiB
TypeScript
92 lines
3.1 KiB
TypeScript
import React from "react";
|
||
import { useAuth } from "~/contexts/auth-context";
|
||
import { useLocation } from "react-router";
|
||
import { LoadingPage } from "~/components/ui/loading";
|
||
|
||
interface ProtectedRouteProps {
|
||
children: React.ReactNode;
|
||
fallback?: React.ReactNode;
|
||
requireAuth?: boolean;
|
||
redirectTo?: string;
|
||
}
|
||
|
||
export function ProtectedRoute({
|
||
children,
|
||
fallback,
|
||
requireAuth = true,
|
||
redirectTo = "/login",
|
||
}: ProtectedRouteProps) {
|
||
const { isAuthenticated, isLoading, token, user } = useAuth();
|
||
const location = useLocation();
|
||
|
||
// Show loading while checking authentication
|
||
if (isLoading) {
|
||
return (
|
||
fallback || (
|
||
<div
|
||
className="min-h-screen flex items-center justify-center"
|
||
style={{
|
||
background:
|
||
"linear-gradient(135deg, var(--color-login-dark-start) 0%, var(--color-login-dark-end) 100%)",
|
||
}}
|
||
>
|
||
<div className="text-center space-y-6 max-w-md mx-auto p-8">
|
||
<div className="flex justify-center">
|
||
<div className="w-8 h-8 border-2 border-[var(--color-login-primary)] border-t-transparent rounded-full animate-spin"></div>
|
||
</div>
|
||
<div className="space-y-2">
|
||
<h2 className="text-lg font-medium font-persian text-white">
|
||
در حال بررسی احراز هویت...
|
||
</h2>
|
||
<p className="text-sm font-persian leading-relaxed text-gray-300">
|
||
لطفاً منتظر بمانید
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
);
|
||
}
|
||
|
||
// If access is not allowed, render fallback and let the global route guard handle navigation/toasts
|
||
if (
|
||
(requireAuth && !isAuthenticated) ||
|
||
(requireAuth && isAuthenticated && (!token || !token.accessToken)) ||
|
||
(!requireAuth && isAuthenticated && location.pathname === "/login")
|
||
) {
|
||
return (
|
||
fallback || (
|
||
<div
|
||
className="min-h-screen flex items-center justify-center"
|
||
style={{
|
||
background:
|
||
"linear-gradient(135deg, var(--color-login-dark-start) 0%, var(--color-login-dark-end) 100%)",
|
||
}}
|
||
>
|
||
<div className="text-center space-y-6 max-w-md mx-auto p-8">
|
||
<div className="flex justify-center">
|
||
<div className="w-8 h-8 border-2 border-[var(--color-login-primary)] border-t-transparent rounded-full animate-spin"></div>
|
||
</div>
|
||
<div className="space-y-2">
|
||
<h2 className="text-lg font-medium font-persian text-white">
|
||
در حال انتقال...
|
||
</h2>
|
||
<p className="text-sm font-persian leading-relaxed text-gray-300">
|
||
لطفاً منتظر بمانید
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
);
|
||
}
|
||
|
||
// If all checks pass, render the protected content
|
||
return <>{children}</>;
|
||
}
|
||
|
||
// Helper component for public routes
|
||
export function PublicRoute({ children }: { children: React.ReactNode }) {
|
||
return <ProtectedRoute requireAuth={false}>{children}</ProtectedRoute>;
|
||
}
|