Files
resolutionflow/frontend/src/components/layout/ProtectedRoute.tsx
chihlasm 042a12b190 feat: add landing page with beta signup + raise KB node limit to 100
Landing page at /landing with full marketing content: hero, features,
pricing, testimonials, and beta email signup form. Beta signups email
beta@resolutionflow.com via new public endpoint. Unauthenticated users
redirect to landing instead of login. Also raises KB Accelerator node
limit from 50 to 100 to accommodate dense troubleshooting articles.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 00:23:29 -04:00

49 lines
1.4 KiB
TypeScript

import { Navigate, useLocation } from 'react-router-dom'
import { useAuthStore } from '@/store/authStore'
import { usePermissions, type EffectiveRole } from '@/hooks/usePermissions'
import { Spinner } from '@/components/common/Spinner'
interface ProtectedRouteProps {
requiredRole?: EffectiveRole
children: React.ReactNode
}
export function ProtectedRoute({ requiredRole, children }: ProtectedRouteProps) {
const { isAuthenticated, isLoading, user } = useAuthStore()
const location = useLocation()
const { effectiveRole } = usePermissions()
if (isLoading) {
return (
<div className="flex h-screen items-center justify-center">
<Spinner className="border-t-foreground" />
</div>
)
}
if (!isAuthenticated) {
return <Navigate to="/landing" state={{ from: location }} replace />
}
// Enforce must_change_password — redirect unless already on /change-password
if (user?.must_change_password && location.pathname !== '/change-password') {
return <Navigate to="/change-password" replace />
}
if (requiredRole) {
const ROLE_HIERARCHY: Record<EffectiveRole, number> = {
super_admin: 4,
owner: 3,
engineer: 2,
viewer: 1,
}
if (ROLE_HIERARCHY[effectiveRole] < ROLE_HIERARCHY[requiredRole]) {
return <Navigate to="/trees" replace />
}
}
return <>{children}</>
}
export default ProtectedRoute