Create a central hub for managing content and accessing administrative tools

Implement the dashboard layout and authentication hook with permission checks.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: cbacfb18-842a-4116-a907-18c0105ad8ec
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/39b5c689-6e8a-4d5a-9792-69cc81a56534/7a432344-d046-4d11-943a-89466ae66121.jpg
This commit is contained in:
mukimovd 2025-05-08 00:26:41 +00:00
parent d67963de51
commit 1f9dc81441
4 changed files with 156 additions and 0 deletions

View File

@ -0,0 +1,153 @@
import { ReactNode } from "react";
import { Link, useLocation } from "wouter";
import { PageLayout } from "./PageLayout";
import { useAuth } from "@/hooks/useAuth";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Card, CardContent } from "@/components/ui/card";
import { ScrollArea } from "@/components/ui/scroll-area";
import {
BarChart3,
BookOpen,
BookText,
FileText,
Users,
PenSquare,
Settings,
LayoutDashboard,
MessageCircle,
BookMarked,
Layers,
AlertTriangle
} from "lucide-react";
import { Skeleton } from "@/components/ui/skeleton";
interface DashboardLayoutProps {
children: ReactNode;
title?: string;
}
export function DashboardLayout({ children, title = "Dashboard" }: DashboardLayoutProps) {
const { user, isLoading, canManageUsers, canManageContent, canReviewContent, canCreateContent } = useAuth();
const [location] = useLocation();
// If user doesn't have permissions, show error
if (!isLoading && !(canCreateContent || canReviewContent || canManageContent || canManageUsers)) {
return (
<PageLayout>
<div className="max-w-[var(--content-width)] mx-auto px-4 md:px-6 py-8">
<Card className="border-red-400 dark:border-red-600">
<CardContent className="pt-6 flex flex-col items-center">
<AlertTriangle className="h-12 w-12 text-red-500 mb-4" />
<h1 className="text-2xl font-bold mb-2">Access Denied</h1>
<p className="text-muted-foreground mb-4 text-center">
You don't have permission to access this area. Please contact an administrator if you believe this is an error.
</p>
<Link href="/">
<a className="text-primary hover:underline">Return to Home</a>
</Link>
</CardContent>
</Card>
</div>
</PageLayout>
);
}
// Get dashboard items based on permissions
const getDashboardNavItems = () => {
const items = [
{ href: "/dashboard", label: "Overview", icon: <LayoutDashboard className="h-4 w-4 mr-2" /> },
];
if (canCreateContent) {
items.push(
{ href: "/dashboard/blog", label: "Blog Posts", icon: <FileText className="h-4 w-4 mr-2" /> },
{ href: "/dashboard/works", label: "Literary Works", icon: <BookText className="h-4 w-4 mr-2" /> },
{ href: "/dashboard/collections", label: "Collections", icon: <BookMarked className="h-4 w-4 mr-2" /> },
{ href: "/dashboard/annotations", label: "Annotations", icon: <PenSquare className="h-4 w-4 mr-2" /> }
);
}
if (canReviewContent) {
items.push(
{ href: "/dashboard/analysis", label: "Analysis Results", icon: <BarChart3 className="h-4 w-4 mr-2" /> },
{ href: "/dashboard/comments", label: "Comments", icon: <MessageCircle className="h-4 w-4 mr-2" /> }
);
}
if (canManageContent) {
items.push(
{ href: "/dashboard/translations", label: "Translations", icon: <BookOpen className="h-4 w-4 mr-2" /> },
{ href: "/dashboard/authors", label: "Authors", icon: <Users className="h-4 w-4 mr-2" /> },
{ href: "/dashboard/tags", label: "Tags", icon: <Layers className="h-4 w-4 mr-2" /> }
);
}
if (canManageUsers) {
items.push(
{ href: "/dashboard/users", label: "User Management", icon: <Users className="h-4 w-4 mr-2" /> },
{ href: "/dashboard/settings", label: "Settings", icon: <Settings className="h-4 w-4 mr-2" /> }
);
}
return items;
};
const navItems = getDashboardNavItems();
return (
<PageLayout>
<div className="max-w-[var(--content-width)] mx-auto px-4 md:px-6 pt-6 pb-16">
<div className="grid grid-cols-1 lg:grid-cols-[240px_1fr] gap-8">
{/* Sidebar */}
<div>
<div className="sticky top-24">
<div className="mb-8">
<h1 className="text-2xl font-bold">Editorial Dashboard</h1>
{isLoading ? (
<Skeleton className="h-5 w-32 mt-1" />
) : (
<p className="text-muted-foreground">
Welcome, {user?.displayName || user?.username}
</p>
)}
</div>
<ScrollArea className="h-[calc(100vh-250px)]">
<Tabs defaultValue={location} orientation="vertical" className="w-full">
<TabsList className="flex flex-col h-auto bg-transparent p-0 w-full">
{navItems.map((item) => (
<Link key={item.href} href={item.href}>
<TabsTrigger
value={item.href}
className="justify-start w-full mb-1 data-[state=active]:bg-primary/10"
>
{item.icon}
{item.label}
</TabsTrigger>
</Link>
))}
</TabsList>
</Tabs>
</ScrollArea>
</div>
</div>
{/* Main content */}
<div>
<div className="pb-4 mb-6 border-b">
<h2 className="text-xl font-semibold">{title}</h2>
</div>
{isLoading ? (
<div className="space-y-4">
<Skeleton className="h-8 w-full" />
<Skeleton className="h-64 w-full" />
</div>
) : (
children
)}
</div>
</div>
</div>
</PageLayout>
);
}

View File

@ -0,0 +1 @@
null

View File

@ -0,0 +1 @@
null

View File

@ -0,0 +1 @@
null