ldc-groupe/resources/ts/back/Components/Layout/AppSidebar.tsx

303 lines
18 KiB
TypeScript

// * Packages
import { Link, usePage } from "@inertiajs/react";
import { useEffect, useRef } from "react";
import {
ChevronDown,
MoreHorizontal,
Home,
Users,
SquareArrowOutUpRight,
Telescope,
} from "lucide-react";
import { route } from "ziggy-js";
// * Components shadcn
import {
Sidebar,
SidebarHeader,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuAction,
useSidebar,
} from "@/components/ui/sidebar";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
Collapsible,
CollapsibleTrigger,
CollapsibleContent,
} from "@/components/ui/collapsible";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { Button } from "@/components/ui/button";
// * Other
import ApplicationLogo from "@/back/Components/ApplicationLogo";
import { Views } from "@/lib/utils";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { AppEnv, AuthProp } from "@/back/types/global";
export default function AppSidebar() {
const appMode = (usePage().props.appEnv as AppEnv).mode;
const { state } = useSidebar();
const prevStateRef = useRef(state);
const isCollapsed = state === "collapsed";
const auth = usePage().props.auth as AuthProp;
const navList = [
{
title: useTrans("back.pages"),
show: true,
links: [
{
title: useTrans("back.dashboard"),
model: "dashboard",
show: true,
icon: Home,
actions: [],
},
{
title: useTrans("back.your_website"),
link: route("front.homepage"),
show: true,
icon: SquareArrowOutUpRight,
actions: [],
},
],
},
{
title: useTrans("back.administration"),
show: auth.user.role === 1,
links: [
{
title: str(useTrans("models.classes.user"))
.ucFirst()
.plural()
.value(),
model: "users",
icon: Users,
show: auth.policies.users.viewAny,
actions: [Views.CREATION],
},
{
title: useTrans("back.telescope"),
link: route("telescope"),
icon: Telescope,
show: appMode === "local",
actions: [],
},
],
},
];
useEffect(() => {
if (prevStateRef.current !== state) {
const elmts = document.querySelectorAll(".sidebar-transition");
elmts.forEach((element) => {
element.classList.add("animation-transition");
setTimeout(() => {
element.classList.remove("animation-transition");
}, 400);
});
prevStateRef.current = state;
}
}, [state]);
const GetTranslation = (label: string) => {
return useTrans(`crud.actions.${label}`);
};
return (
<Sidebar collapsible="icon" className="z-30">
<SidebarHeader className="sidebar-transition">
<ApplicationLogo isCollapsed={isCollapsed} />
</SidebarHeader>
<SidebarContent
className={`sidebar-transition ${isCollapsed ? "pt-2" : ""}`}
>
{navList.map(
(navGroup) =>
navGroup.show && (
<Collapsible
key={navGroup.title}
className="group/collapsible"
defaultOpen
>
<SidebarGroup>
{!isCollapsed && (
<SidebarGroupLabel asChild>
<CollapsibleTrigger>
{navGroup.title}
<ChevronDown className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-180" />
</CollapsibleTrigger>
</SidebarGroupLabel>
)}
<CollapsibleContent>
<SidebarGroupContent>
<SidebarMenu>
{navGroup.links.map(
(navLink) => {
const sidebarButton = (
<SidebarMenuButton
className={`${
route().current(
`back.${navLink.model}.*`,
)
? "text-secondary-foreground"
: "text-primary-foreground"
}`}
asChild
>
{navLink.link ? (
<a
href={
navLink.link
}
target="_blank"
rel="noreferrer"
>
<navLink.icon />
{
navLink.title
}
</a>
) : (
<Link
href={route(
`back.${navLink.model}.index`,
)}
className="bg-transparent"
>
<navLink.icon />
{
navLink.title
}
</Link>
)}
</SidebarMenuButton>
);
return (
navLink.show && (
<SidebarMenuItem
className={`transition-colors rounded-md ${
route().current(
`back.${navLink.model}.*`,
)
? "bg-secondary text-secondary-foreground"
: "bg-opacity-0"
}`}
key={
navLink.title
}
>
{isCollapsed ? (
<Tooltip>
<TooltipTrigger
asChild
>
{
sidebarButton
}
</TooltipTrigger>
<TooltipContent side="right">
<p>
{
navLink.title
}
</p>
</TooltipContent>
</Tooltip>
) : (
sidebarButton
)}
{navLink
.actions
.length >
0 && (
<DropdownMenu>
<DropdownMenuTrigger
asChild
>
<SidebarMenuAction
className={`${
route().current(
`back.${navLink.model}.*`,
)
? "text-secondary-foreground"
: ""
} !top-0 !right-0 px-4 h-full`}
>
<MoreHorizontal />
</SidebarMenuAction>
</DropdownMenuTrigger>
<DropdownMenuContent
side="right"
align="start"
>
{navLink.actions.map(
(
action,
) =>
auth
.policies
.users[
action.policy as keyof typeof auth.policies.users
] && (
<DropdownMenuItem
className="p-0"
key={
action.label
}
>
<Button
variant="ghost"
asChild
>
<Link
href={route(
`back.${navLink.model}.${action.value}`,
)}
className="w-full"
>
<action.icon />
{str(
GetTranslation(
action.label,
),
)
.ucFirst()
.value()}
</Link>
</Button>
</DropdownMenuItem>
),
)}
</DropdownMenuContent>
</DropdownMenu>
)}
</SidebarMenuItem>
)
);
},
)}
</SidebarMenu>
</SidebarGroupContent>
</CollapsibleContent>
</SidebarGroup>
</Collapsible>
),
)}
</SidebarContent>
</Sidebar>
);
}