Update fun module configuration and enhance CSS styles
- Added 'enabled' property to FunConfigSchema with a default value of true for better configuration management. - Refactored getFunConfig to return a complete default configuration when no data is found. - Improved globals.css by expanding CSS variables for light and dark themes, enhancing styling consistency across the application.
This commit is contained in:
86
apps/webui/src/components/layout/sidebar.tsx
Normal file
86
apps/webui/src/components/layout/sidebar.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
'use client';
|
||||
|
||||
import { DASHBOARD_MODULES, type DashboardModuleGroup } from '@nexumi/shared';
|
||||
import { LayoutGrid, Settings, ShieldCheck, SlidersHorizontal } from 'lucide-react';
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { useTranslations } from '@/components/locale-provider';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const MODULE_GROUP_ORDER: DashboardModuleGroup[] = [
|
||||
'moderation',
|
||||
'engagement',
|
||||
'community',
|
||||
'utility',
|
||||
'integrations'
|
||||
];
|
||||
|
||||
interface SidebarProps {
|
||||
guildId: string;
|
||||
}
|
||||
|
||||
function NavLink({ href, active, children }: { href: string; active: boolean; children: React.ReactNode }) {
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
className={cn(
|
||||
'flex items-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors',
|
||||
active
|
||||
? 'bg-accent text-accent-foreground'
|
||||
: 'text-muted-foreground hover:bg-accent/60 hover:text-foreground'
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
export function Sidebar({ guildId }: SidebarProps) {
|
||||
const pathname = usePathname();
|
||||
const t = useTranslations();
|
||||
const base = `/dashboard/${guildId}`;
|
||||
|
||||
const groups = MODULE_GROUP_ORDER.map((group) => ({
|
||||
group,
|
||||
modules: DASHBOARD_MODULES.filter((module) => module.group === group)
|
||||
}));
|
||||
|
||||
return (
|
||||
<nav className="flex h-full w-60 flex-col gap-6 overflow-y-auto border-r border-border px-3 py-4">
|
||||
<div className="flex flex-col gap-1">
|
||||
<NavLink href={base} active={pathname === base}>
|
||||
<LayoutGrid className="size-4" />
|
||||
{t('nav.overview')}
|
||||
</NavLink>
|
||||
<NavLink href={`${base}/settings`} active={pathname === `${base}/settings`}>
|
||||
<Settings className="size-4" />
|
||||
{t('nav.settings')}
|
||||
</NavLink>
|
||||
<NavLink href={`${base}/modules`} active={pathname === `${base}/modules`}>
|
||||
<SlidersHorizontal className="size-4" />
|
||||
{t('nav.modules')}
|
||||
</NavLink>
|
||||
<NavLink href={`${base}/access`} active={pathname === `${base}/access`}>
|
||||
<ShieldCheck className="size-4" />
|
||||
{t('nav.access')}
|
||||
</NavLink>
|
||||
</div>
|
||||
|
||||
{groups.map(({ group, modules }) => (
|
||||
<div key={group} className="flex flex-col gap-1">
|
||||
<p className="px-3 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
||||
{t(`moduleGroups.${group}`)}
|
||||
</p>
|
||||
{modules.map((module) => {
|
||||
const href = `${base}/${module.href}`;
|
||||
return (
|
||||
<NavLink key={module.id} href={href} active={pathname === href}>
|
||||
{t(`modules.${module.id}.label`)}
|
||||
</NavLink>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
))}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user