sud-life-insurance/src/components/form/SchemaGuard.tsx
2026-07-03 14:52:45 +05:30

52 lines
2.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { ReactNode } from 'react';
import { Lock } from 'lucide-react';
/** True for a backend RBAC denial — so we can show a human line, not the raw
* "user N does not have permission for activity <uuid>". */
export function isPermissionError(msg?: string | null): boolean {
return !!msg && /permission|not authoriz|unauthoriz|forbidden|\b403\b/i.test(msg);
}
interface SchemaGuardProps {
loading: boolean;
error: string | null;
/** Verb phrase for the denial copy, e.g. "collect documents for this lead". */
action: string;
/** True when the schema loaded but yielded no usable fields. */
empty?: boolean;
children: ReactNode;
}
/** Gate any activity body on its form-screens fetch. Until the schema resolves
* cleanly we never render the form: an RBAC denial (or any load error) shows a
* human-readable card instead of a live-looking form that 403s only on submit.
* Bespoke bodies and the generic <ActivityForm> share this so the guard can't
* drift out of sync between them. */
export function SchemaGuard({ loading, error, action, empty, children }: SchemaGuardProps) {
if (loading) {
return <div className="py-6 text-sm text-faint">Loading form</div>;
}
if (error || empty) {
if (isPermissionError(error)) {
return (
<div className="flex items-start gap-2.5 rounded-md border border-amber-200 bg-amber-50 px-4 py-3.5 text-sm text-amber-800">
<Lock size={16} className="mt-0.5 shrink-0 text-amber-600" />
<div>
<div className="font-semibold">You dont have permission for this action</div>
<div className="mt-0.5 text-xs text-amber-700">
Your role cant {action}. Ask an admin to grant your role access to this activity, or
sign in as a role that can.
</div>
</div>
</div>
);
}
return (
<div className="py-4 text-sm text-amber-700">
{error ? `Couldnt load the form: ${error}` : 'This activity has no input fields.'}
</div>
);
}
return <>{children}</>;
}