Files
erika/components/form-admin-sidebar.tsx
T

164 lines
4.6 KiB
TypeScript

"use client";
import { usePathname } from "next/navigation";
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarHeader,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
} from "@/components/ui/sidebar";
import {
ArrowLeft,
ClipboardList,
Eye,
FilePenLine,
LayoutDashboard,
Settings,
} from "lucide-react";
import { ThemeToggle } from "@/components/theme-toggle";
import {
DropdownMenuAvatar,
type DiscordMemberProfile,
} from "@/components/dropdown-menu-avatar";
import { GuardedLink } from "@/components/guarded-link";
import { Badge } from "@/components/ui/badge";
export function FormAdminSidebar({
formId,
formTitle,
isOpen,
userName,
userImage,
profile,
}: {
formId: string;
formTitle: string;
isOpen: boolean;
userName?: string;
userImage?: string;
profile?: DiscordMemberProfile | null;
}) {
const pathname = usePathname();
const currentSection = pathname.startsWith(`/admin/form/${formId}/result`)
? "Responses"
: pathname.startsWith(`/admin/form/${formId}/extra`)
? "Settings"
: pathname.startsWith(`/admin/form/${formId}/preview`)
? "Preview"
: "Editor";
const items = [
{
href: `/admin/form/${formId}`,
label: "Editor",
icon: LayoutDashboard,
active: pathname === `/admin/form/${formId}`,
},
{
href: `/admin/form/${formId}/result`,
label: "Responses",
icon: ClipboardList,
active: pathname.startsWith(`/admin/form/${formId}/result`),
},
{
href: `/admin/form/${formId}/extra`,
label: "Settings",
icon: Settings,
active: pathname.startsWith(`/admin/form/${formId}/extra`),
},
{
href: `/admin/form/${formId}/preview`,
label: "Preview",
icon: Eye,
active: pathname.startsWith(`/admin/form/${formId}/preview`),
},
];
return (
<Sidebar variant="sidebar" collapsible="icon">
<SidebarHeader className="border-b p-2">
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton
asChild
size="lg"
tooltip={`${formTitle} · ${isOpen ? "Open" : "Closed"}`}
className="h-auto min-h-14"
>
<GuardedLink
href={`/admin/form/${formId}`}
aria-label={`${formTitle}, ${isOpen ? "open" : "closed"}. Open editor`}
>
<FilePenLine />
<div className="min-w-0 flex-1">
<div className="flex min-w-0 items-center gap-2">
<span className="min-w-0 flex-1 truncate font-medium">
{formTitle}
</span>
<Badge
variant={isOpen ? "default" : "secondary"}
className="shrink-0"
>
{isOpen ? "Open" : "Closed"}
</Badge>
</div>
<span className="mt-1 block text-xs text-muted-foreground">
{currentSection}
</span>
</div>
</GuardedLink>
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton asChild>
<GuardedLink href="/admin/form">
<ArrowLeft />
<span>All forms</span>
</GuardedLink>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Workspace</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{items.map(({ href, label, icon: Icon, active }) => (
<SidebarMenuItem key={href}>
<SidebarMenuButton asChild isActive={active}>
<GuardedLink href={href}>
<Icon />
<span>{label}</span>
</GuardedLink>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
<SidebarFooter className="border-t p-4">
<div className="flex items-center gap-1">
{(userName || profile) && (
<DropdownMenuAvatar
userName={userName || ""}
userImage={userImage || ""}
profile={profile || null}
showName
/>
)}
<div className="ml-auto">
<ThemeToggle />
</div>
</div>
</SidebarFooter>
</Sidebar>
);
}