admin dashbaord; started member managment ui
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { auth } from "@/server/auth";
|
||||
import Link from "next/link";
|
||||
import React from "react";
|
||||
|
||||
async function AdminNavbar() {
|
||||
const session = await auth();
|
||||
return (
|
||||
<div className="flex h-14 w-full items-center justify-between gap-4 border-b bg-sidebar px-4">
|
||||
<span>Admin Dashboard</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default AdminNavbar;
|
||||
@@ -0,0 +1,76 @@
|
||||
import * as React from "react";
|
||||
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarFooter,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarHeader,
|
||||
SidebarMenu,
|
||||
} from "@/components/ui/sidebar";
|
||||
import Link from "next/link";
|
||||
import SidebarLink from "@/components/layout/sidebar-link";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { LogOutIcon } from "lucide-react";
|
||||
import { appConfig } from "@/app.config";
|
||||
|
||||
const data = {
|
||||
navMain: [
|
||||
{
|
||||
title: "Benutzer",
|
||||
url: "/admin",
|
||||
items: [
|
||||
{
|
||||
title: "Team Mitglieder",
|
||||
url: "/admin/team",
|
||||
},
|
||||
{
|
||||
title: "Alle Benutzer",
|
||||
url: "/admin/benutzer",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export function AdminSidebar({
|
||||
...props
|
||||
}: React.ComponentProps<typeof Sidebar>) {
|
||||
return (
|
||||
<Sidebar {...props}>
|
||||
<SidebarHeader className="flex h-14 items-center justify-center border-b">
|
||||
<Link href={"/admin"}>
|
||||
<span className="text-2xl font-bold">{appConfig.name}</span>
|
||||
</Link>
|
||||
</SidebarHeader>
|
||||
<SidebarContent>
|
||||
{/* We create a SidebarGroup for each parent. */}
|
||||
{data.navMain.map((item) => (
|
||||
<SidebarGroup key={item.title}>
|
||||
<SidebarGroupLabel>{item.title}</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{item.items.map((item) => (
|
||||
<SidebarLink key={item.title} {...item} />
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
))}
|
||||
</SidebarContent>
|
||||
<SidebarFooter>
|
||||
<Button
|
||||
asChild
|
||||
variant={"destructive"}
|
||||
className="border-2 bg-sidebar text-foreground hover:text-destructive-foreground"
|
||||
>
|
||||
<Link href={"/"}>
|
||||
<LogOutIcon className="size-4 rotate-180" /> Verlassen
|
||||
</Link>
|
||||
</Button>
|
||||
</SidebarFooter>
|
||||
</Sidebar>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { hasPermission, Role } from "@/lib/validation/permissions";
|
||||
import { auth } from "@/server/auth";
|
||||
import { notFound } from "next/navigation";
|
||||
import React from "react";
|
||||
import AdminNavbar from "./_components/admin-navbar";
|
||||
import { SidebarProvider } from "@/components/ui/sidebar";
|
||||
import { AdminSidebar } from "./_components/admin-sidebar";
|
||||
|
||||
async function Layout({ children }: { children: React.ReactNode }) {
|
||||
const session = await auth();
|
||||
const isAdmin = session?.user
|
||||
? hasPermission(session.user.role, Role.ADMIN)
|
||||
: false;
|
||||
if (!isAdmin) return notFound();
|
||||
return (
|
||||
<SidebarProvider>
|
||||
<AdminSidebar />
|
||||
<div className="w-full">
|
||||
{/* <AdminNavbar /> */}
|
||||
<main className="space-y-4 p-4"> {children}</main>
|
||||
</div>
|
||||
</SidebarProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default Layout;
|
||||
@@ -0,0 +1,8 @@
|
||||
import { api } from "@/trpc/server";
|
||||
import React from "react";
|
||||
|
||||
async function Page() {
|
||||
return <div>Admin Dashboard</div>;
|
||||
}
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,50 @@
|
||||
"use client";
|
||||
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { getUserPermissions } from "@/lib/validation/permissions";
|
||||
import { ColumnDef } from "@tanstack/react-table";
|
||||
import { Plus } from "lucide-react";
|
||||
import { User } from "next-auth";
|
||||
|
||||
export const columns: ColumnDef<User>[] = [
|
||||
{
|
||||
accessorKey: "name",
|
||||
header: "Name",
|
||||
},
|
||||
{
|
||||
accessorKey: "email",
|
||||
header: "Email",
|
||||
},
|
||||
|
||||
{
|
||||
accessorKey: "role",
|
||||
header: "Rollen",
|
||||
cell: ({ row }) => {
|
||||
const roles = getUserPermissions(Number(row.getValue("role")));
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
{roles
|
||||
.filter(({ name }) => name !== "User")
|
||||
.map((role) => (
|
||||
<Badge
|
||||
key={role.name}
|
||||
variant={"outline"}
|
||||
className={`${Object.values(role.color).join(" ")}`}
|
||||
>
|
||||
{role.name}
|
||||
</Badge>
|
||||
))}
|
||||
<Button
|
||||
size={"icon"}
|
||||
variant={"outline"}
|
||||
className="size-max gap-1 bg-muted p-px text-muted-foreground"
|
||||
>
|
||||
<Plus className="size-3" />
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,22 @@
|
||||
import { api } from "@/trpc/server";
|
||||
import React from "react";
|
||||
import { DataTable } from "@/components/data-table";
|
||||
import { columns } from "./columns";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
async function Page() {
|
||||
const users = await api.users.getAll();
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<h1 className="text-2xl font-bold">Team Mitglieder</h1>
|
||||
<Button variant={"outline"}>Mitglied einladen</Button>
|
||||
</div>
|
||||
|
||||
<DataTable columns={columns} data={users} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default Page;
|
||||
Reference in New Issue
Block a user