proposal-system/web/src/components/ProtectedRoute.tsx
Adam Moussa 4d72b63547 Add frontend role guards, fix dashboard data exposure, and harden UX
RoleGuard: New component wrapping admin routes — dispatchers navigating
to /admin/* by URL now redirect to / instead of seeing error states.

Dashboard: Add mine=true filter so dispatchers only see their own
proposals and stats, not all users' data.

AdminWorkspace: Auto-save dirty changes before approving so edits to
refined scope and line items aren't silently discarded.

ProposalFormPage: Add onError toast and 300ms debounce on customer
search (was firing an API call per keystroke).

admin.ts: Stop swallowing errors in getPdf — let them propagate to the
mutation's onError handler. Fix AuditEntry.details type to string|null.

LoginPage: Fix pre-existing TS error with noUncheckedIndexedAccess.
2026-05-20 18:09:04 -04:00

22 lines
569 B
TypeScript

import { Navigate } from 'react-router-dom';
import { useAuth } from '../hooks/useAuth';
export default function ProtectedRoute({ children }: { children: React.ReactNode }) {
const { isAuthenticated } = useAuth();
if (!isAuthenticated) {
return <Navigate to="/login" replace />;
}
return <>{children}</>;
}
export function RoleGuard({ roles, children }: { roles: string[]; children: React.ReactNode }) {
const { user } = useAuth();
if (!user || !roles.includes(user.role)) {
return <Navigate to="/" replace />;
}
return <>{children}</>;
}