Untitled
unknown
plain_text
7 months ago
8.5 kB
5
Indexable
"use client"
import * as React from "react"
import {
Home,
Image,
Trophy,
BarChart,
HelpCircle,
Settings,
ArrowUpDown,
LineChart,
Grid,
Archive,
BookOpen,
Moon,
Sun,
Trash2
} from 'lucide-react'
import { useTheme } from "next-themes"
import { useSettings } from "@/hooks/useSettings"
import { useTranslation, type SupportedLanguages } from "@/utils/translations"
import { usePathname } from "next/navigation"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarHeader,
SidebarMenu,
SidebarMenuItem,
SidebarMenuButton,
SidebarMenuSub,
SidebarMenuSubItem,
SidebarMenuSubButton,
SidebarRail,
SidebarSeparator
} from "@/components/ui/sidebar"
import { Button } from "@/components/ui/button"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
const { theme } = useTheme()
const { settings, updateSettings } = useSettings()
const { t } = useTranslation(settings?.language as SupportedLanguages || 'EN')
const pathname = usePathname()
const navData = React.useMemo(() => ({
navMain: [
{
title: t('navigation.home'),
url: "/",
icon: Home,
isDirectLink: true,
},
{
title: t('navigation.gallery'),
url: "/gallery",
icon: Image,
isDirectLink: true,
},
{
title: t('navigation.achievements'),
url: "/achievements",
icon: Trophy,
isDirectLink: true,
},
{
title: t('navigation.statistics'),
url: "#",
icon: BarChart,
items: [
{
title: t('navigation.sorting'),
url: "/sorting",
icon: ArrowUpDown,
},
{
title: t('navigation.impact'),
url: "/impact",
icon: LineChart,
},
{
title: t('navigation.patterns'),
url: "/patterns",
icon: Grid,
},
{
title: t('navigation.bins'),
url: "/bins",
icon: Archive,
},
],
},
{
title: t('navigation.help'),
url: "#",
icon: HelpCircle,
items: [
{
title: t('navigation.guide'),
url: "/guide",
icon: BookOpen,
},
],
},
{
title: t('navigation.settings'),
url: "#",
icon: Settings,
items: [
{
title: t('navigation.placeholder'),
url: "#",
icon: Settings,
},
{
title: t('navigation.placeholder'),
url: "#",
icon: Settings,
},
{
title: t('navigation.placeholder'),
url: "#",
icon: Settings,
},
],
},
],
}), [t]);
const handleThemeToggle = () => {
const newDarkMode = theme === "light" ? 1 : 0;
updateSettings({ dark_mode: newDarkMode });
};
const handleLanguageChange = (value: string) => {
updateSettings({ language: value });
};
// Check if a menu item is active
const isActive = (url: string) => {
if (url === "/" && pathname === "/") return true;
if (url !== "/" && pathname.startsWith(url)) return true;
return false;
};
// Function to check if any sub-item in a section is active
const isSectionActive = (items: Array<{ url: string }>) => {
return items?.some(item => isActive(item.url));
};
return (
<Sidebar {...props}>
<SidebarHeader className="border-b p-4 mb-2">
<div className="flex items-center gap-3 px-2">
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-blue-600 text-white">
<Trash2 className="h-6 w-6" />
</div>
<div className="flex flex-col">
<span className="text-lg font-semibold text-sidebar-foreground">SortiMate</span>
<span className="text-xs text-sidebar-foreground/60">
{t('common.aiAssistant')}
</span>
</div>
</div>
</SidebarHeader>
<SidebarContent className="px-1">
<SidebarGroup>
<SidebarMenu className="space-y-1">
{navData.navMain.map((item, index) => (
item.isDirectLink ? (
<SidebarMenuItem key={item.title} className="my-1">
<SidebarMenuButton
asChild
isActive={isActive(item.url)}
className={`group flex items-center py-2.5 ${isActive(item.url) ? 'bg-sidebar-accent/30 text-sidebar-foreground font-medium' : ''}`}
>
<a href={item.url} className="flex items-center w-full">
<item.icon className="h-5 w-5 mx-3" />
<span>{item.title}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
) : (
<React.Fragment key={item.title}>
<div className="group mt-1">
<SidebarMenuItem>
<SidebarMenuButton
className={`flex items-center py-2.5 ${isSectionActive(item.items || []) ? 'text-sidebar-foreground font-medium' : 'text-sidebar-foreground/80'}`}
>
<item.icon className="h-5 w-5 mx-3" />
<span className="text-[15px]">{item.title}</span>
</SidebarMenuButton>
</SidebarMenuItem>
{item.items?.length ? (
<SidebarMenuSub className="mt-0.5 space-y-0.5">
{item.items.map((subItem) => (
<SidebarMenuSubItem key={subItem.title}>
<SidebarMenuSubButton
asChild
isActive={isActive(subItem.url)}
className={`py-2 ${isActive(subItem.url) ? 'bg-sidebar-accent/20 text-sidebar-foreground font-medium' : 'text-sidebar-foreground/70'}`}
>
<a href={subItem.url} className="flex items-center">
<subItem.icon className="h-4 w-4 mx-4" />
<span className="text-[14px]">{subItem.title}</span>
</a>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
))}
</SidebarMenuSub>
) : null}
</div>
{index < navData.navMain.length - 1 && (
<SidebarSeparator className="my-2 opacity-20" />
)}
</React.Fragment>
)
))}
</SidebarMenu>
</SidebarGroup>
</SidebarContent>
<div className="mt-auto border-t border-sidebar-border/30 p-4 space-y-3">
<Button
variant="ghost"
size="sm"
className="w-full justify-between text-sidebar-foreground/90"
onClick={handleThemeToggle}
>
<span className="text-sm">{t('common.theme')}</span>
<div className="flex items-center">
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
</div>
</Button>
<Select
value={settings?.language || "DE"}
onValueChange={handleLanguageChange}
>
<SelectTrigger className="w-full text-sidebar-foreground/90">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="EN">{t('common.english')}</SelectItem>
<SelectItem value="DE">{t('common.german')}</SelectItem>
</SelectContent>
</Select>
</div>
<SidebarRail />
</Sidebar>
);
}Editor is loading...
Leave a Comment