|
|
@@ -0,0 +1,78 @@
|
|
|
+"use client";
|
|
|
+
|
|
|
+import React from "react";
|
|
|
+import Link from "next/link";
|
|
|
+
|
|
|
+import { useAuth } from "@/components/auth/authContext";
|
|
|
+import { branchPath, homePath } from "@/lib/frontend/routes";
|
|
|
+
|
|
|
+import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert";
|
|
|
+import { Button } from "@/components/ui/button";
|
|
|
+import {
|
|
|
+ Card,
|
|
|
+ CardHeader,
|
|
|
+ CardTitle,
|
|
|
+ CardDescription,
|
|
|
+ CardContent,
|
|
|
+ CardFooter,
|
|
|
+} from "@/components/ui/card";
|
|
|
+
|
|
|
+/**
|
|
|
+ * ForbiddenView (RHL-021)
|
|
|
+ *
|
|
|
+ * A reusable UI block for "you are authenticated, but not allowed here".
|
|
|
+ *
|
|
|
+ * It relies on AuthContext when available to render the best CTA:
|
|
|
+ * - branch users -> link to their own branch root
|
|
|
+ * - admin/dev -> link to home (later: could link to a branch list)
|
|
|
+ */
|
|
|
+export default function ForbiddenView({ attemptedBranch = null }) {
|
|
|
+ const { status, user } = useAuth();
|
|
|
+
|
|
|
+ const isAuthed = status === "authenticated" && user;
|
|
|
+ const isBranchUser = isAuthed && user.role === "branch" && user.branchId;
|
|
|
+
|
|
|
+ const primaryHref = isBranchUser ? branchPath(user.branchId) : homePath();
|
|
|
+ const primaryLabel = isBranchUser ? "Go to my branch" : "Go to home";
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Card>
|
|
|
+ <CardHeader>
|
|
|
+ <CardTitle>Access denied</CardTitle>
|
|
|
+ <CardDescription>
|
|
|
+ You are not allowed to access this resource.
|
|
|
+ </CardDescription>
|
|
|
+ </CardHeader>
|
|
|
+
|
|
|
+ <CardContent className="space-y-4">
|
|
|
+ <Alert variant="destructive">
|
|
|
+ <AlertTitle>Forbidden</AlertTitle>
|
|
|
+ <AlertDescription>
|
|
|
+ {attemptedBranch ? (
|
|
|
+ <span>
|
|
|
+ Your account is not permitted to access branch{" "}
|
|
|
+ <strong>{attemptedBranch}</strong>.
|
|
|
+ </span>
|
|
|
+ ) : (
|
|
|
+ <span>Your account is not permitted to access this page.</span>
|
|
|
+ )}
|
|
|
+ </AlertDescription>
|
|
|
+ </Alert>
|
|
|
+
|
|
|
+ <p className="text-sm text-muted-foreground">
|
|
|
+ If you believe this is a mistake, please contact your administrator.
|
|
|
+ </p>
|
|
|
+ </CardContent>
|
|
|
+
|
|
|
+ <CardFooter className="flex flex-col gap-2 sm:flex-row sm:justify-end">
|
|
|
+ <Button variant="outline" asChild>
|
|
|
+ <Link href={homePath()}>Home</Link>
|
|
|
+ </Button>
|
|
|
+
|
|
|
+ <Button asChild>
|
|
|
+ <Link href={primaryHref}>{primaryLabel}</Link>
|
|
|
+ </Button>
|
|
|
+ </CardFooter>
|
|
|
+ </Card>
|
|
|
+ );
|
|
|
+}
|