43 lines
1.2 KiB
TypeScript
43 lines
1.2 KiB
TypeScript
"use client";
|
|||
|
|
import { useEffect } from "react";
|
||
|
|
import { useRouter } from "next/navigation";
|
||
|
|
import { useFeatureAccess, type ModuleKey } from "@/lib/useFeatureAccess";
|
||
|
|
|
||
|
|
interface FeatureGateProps {
|
||
|
|
module: ModuleKey;
|
||
|
|
children: React.ReactNode;
|
||
|
|
fallback?: React.ReactNode;
|
||
|
|
}
|
||
|
|
|
||
|
|
export function FeatureGate({ module, children, fallback }: FeatureGateProps) {
|
||
|
|
const { modules, loading } = useFeatureAccess();
|
||
|
|
const router = useRouter();
|
||
|
|
const allowed = modules.includes(module);
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
if (!loading && !allowed) {
|
||
|
|
router.replace("/");
|
||
|
|
}
|
||
|
|
}, [loading, allowed, router]);
|
||
|
|
|
||
|
|
if (loading) {
|
||
|
|
return (
|
||
|
|
<div className="flex items-center justify-center py-16">
|
||
|
|
<div className="h-8 w-8 animate-spin rounded-full border-2 border-accent border-t-transparent" />
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!allowed) {
|
||
|
|
if (fallback) return <>{fallback}</>;
|
||
|
|
return (
|
||
|
|
<div className="flex flex-col items-center justify-center py-16 space-y-4">
|
||
|
|
<p className="text-lg font-medium text-fg">Access Restricted</p>
|
||
|
|
<p className="text-sm text-fg-muted">You don't have access to this module.</p>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
return <>{children}</>;
|
||
|
|
}
|