feat: Integrate new dashboard design and components, remove old dashboard routes, and update dependencies.
This commit is contained in:
@@ -1,332 +0,0 @@
|
||||
import {
|
||||
AppShell,
|
||||
Avatar,
|
||||
Box,
|
||||
Burger,
|
||||
Group,
|
||||
Menu,
|
||||
NavLink,
|
||||
rem,
|
||||
ScrollArea,
|
||||
Stack,
|
||||
Text,
|
||||
Tooltip,
|
||||
} from "@mantine/core";
|
||||
import { useDisclosure } from "@mantine/hooks";
|
||||
import { modals } from "@mantine/modals";
|
||||
import {
|
||||
IconChevronRight,
|
||||
IconHome,
|
||||
IconKey,
|
||||
IconLogout,
|
||||
IconSettings,
|
||||
IconUser,
|
||||
IconUsers,
|
||||
} from "@tabler/icons-react";
|
||||
import {
|
||||
createFileRoute,
|
||||
Outlet,
|
||||
useLocation,
|
||||
useNavigate,
|
||||
} from "@tanstack/react-router";
|
||||
import { useSnapshot } from "valtio";
|
||||
import { ColorSchemeToggle } from "@/components/ColorSchemeToggle";
|
||||
import { protectedRouteMiddleware } from "@/middleware/authMiddleware";
|
||||
import { authClient } from "@/utils/auth-client";
|
||||
import { authStore } from "../../store/auth";
|
||||
|
||||
export const Route = createFileRoute("/dashboard")({
|
||||
component: DashboardLayout,
|
||||
beforeLoad: protectedRouteMiddleware,
|
||||
onEnter({ context }) {
|
||||
authStore.user = context?.user as any;
|
||||
authStore.session = context?.session as any;
|
||||
},
|
||||
});
|
||||
|
||||
function DashboardLayout() {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const snap = useSnapshot(authStore);
|
||||
const [mobileOpened, { toggle: toggleMobile }] = useDisclosure();
|
||||
const [desktopOpened, { toggle: toggleDesktop }] = useDisclosure(true);
|
||||
|
||||
const navItems = [
|
||||
{
|
||||
icon: IconHome,
|
||||
label: "Beranda",
|
||||
to: "/dashboard",
|
||||
description: "Ringkasan sistem & statistik",
|
||||
},
|
||||
{
|
||||
icon: IconUsers,
|
||||
label: "Pengguna",
|
||||
to: "/dashboard/users",
|
||||
description: "Kelola akun & hak akses",
|
||||
},
|
||||
{
|
||||
icon: IconKey,
|
||||
label: "API Key",
|
||||
to: "/dashboard/apikey",
|
||||
description: "Manajemen kunci akses API",
|
||||
},
|
||||
{
|
||||
icon: IconSettings,
|
||||
label: "Pengaturan",
|
||||
to: "/dashboard/settings",
|
||||
description: "Konfigurasi sistem",
|
||||
},
|
||||
];
|
||||
|
||||
const handleLogout = async () => {
|
||||
modals.openConfirmModal({
|
||||
title: "Konfirmasi Keluar",
|
||||
centered: true,
|
||||
children: (
|
||||
<Text size="sm">
|
||||
Apakah Anda yakin ingin keluar dari sistem? Sesi Anda akan berakhir.
|
||||
</Text>
|
||||
),
|
||||
labels: { confirm: "Keluar", cancel: "Batal" },
|
||||
confirmProps: { color: "red" },
|
||||
onConfirm: async () => {
|
||||
await authClient.signOut();
|
||||
navigate({ to: "/signin" });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const isActive = (path: string) => {
|
||||
const current = location.pathname;
|
||||
if (path === "/dashboard")
|
||||
return current === "/dashboard" || current === "/dashboard/";
|
||||
return current.startsWith(path);
|
||||
};
|
||||
|
||||
return (
|
||||
<AppShell
|
||||
header={{ height: 70 }}
|
||||
navbar={{
|
||||
width: 280,
|
||||
|
||||
breakpoint: "sm",
|
||||
|
||||
collapsed: { mobile: !mobileOpened, desktop: !desktopOpened },
|
||||
}}
|
||||
padding="md"
|
||||
transitionDuration={500}
|
||||
transitionTimingFunction="ease"
|
||||
>
|
||||
<AppShell.Header
|
||||
style={{
|
||||
backdropFilter: "blur(10px)",
|
||||
|
||||
borderBottom: "1px solid var(--mantine-color-default-border)",
|
||||
}}
|
||||
>
|
||||
<Group h="100%" px="md" justify="space-between">
|
||||
<Group gap="xs">
|
||||
<Burger
|
||||
opened={mobileOpened}
|
||||
onClick={toggleMobile}
|
||||
hiddenFrom="sm"
|
||||
size="sm"
|
||||
/>
|
||||
|
||||
<Burger
|
||||
opened={desktopOpened}
|
||||
onClick={toggleDesktop}
|
||||
visibleFrom="sm"
|
||||
size="sm"
|
||||
/>
|
||||
|
||||
<Box visibleFrom="xs" ml="xs">
|
||||
<Text
|
||||
fw={800}
|
||||
size="xl"
|
||||
c="orange.6"
|
||||
style={{ letterSpacing: "-0.5px" }}
|
||||
>
|
||||
ADMIN
|
||||
<Text span c="var(--mantine-color-text)">
|
||||
PANEL
|
||||
</Text>
|
||||
</Text>
|
||||
</Box>
|
||||
</Group>
|
||||
|
||||
<Group gap="md">
|
||||
<ColorSchemeToggle />
|
||||
|
||||
<Menu
|
||||
shadow="md"
|
||||
width={200}
|
||||
position="bottom-end"
|
||||
transitionProps={{ transition: "pop-top-right" }}
|
||||
>
|
||||
<Menu.Target>
|
||||
<Group
|
||||
gap="xs"
|
||||
style={{ cursor: "pointer" }}
|
||||
p="xs"
|
||||
className="hover:bg-gray-50 dark:hover:bg-white/5 rounded-md"
|
||||
>
|
||||
<div
|
||||
style={{ textAlign: "right" }}
|
||||
className="visible-from-sm"
|
||||
>
|
||||
<Text size="sm" fw={600}>
|
||||
{snap.user?.name}
|
||||
</Text>
|
||||
|
||||
<Text size="xs" c="dimmed">
|
||||
Administrator
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<Avatar
|
||||
src={snap.user?.image}
|
||||
radius="xl"
|
||||
size="md"
|
||||
style={{
|
||||
border: "2px solid var(--mantine-color-orange-filled)",
|
||||
}}
|
||||
>
|
||||
{snap.user?.name?.charAt(0)}
|
||||
</Avatar>
|
||||
</Group>
|
||||
</Menu.Target>
|
||||
|
||||
<Menu.Dropdown>
|
||||
<Menu.Label>Akun</Menu.Label>
|
||||
|
||||
<Menu.Item
|
||||
leftSection={
|
||||
<IconUser style={{ width: rem(14), height: rem(14) }} />
|
||||
}
|
||||
onClick={() => navigate({ to: "/profile" })}
|
||||
>
|
||||
Profil Saya
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item
|
||||
leftSection={
|
||||
<IconSettings style={{ width: rem(14), height: rem(14) }} />
|
||||
}
|
||||
onClick={() => navigate({ to: "/dashboard/settings" })}
|
||||
>
|
||||
Pengaturan
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Divider />
|
||||
|
||||
<Menu.Label>Bahaya</Menu.Label>
|
||||
|
||||
<Menu.Item
|
||||
color="red"
|
||||
leftSection={
|
||||
<IconLogout style={{ width: rem(14), height: rem(14) }} />
|
||||
}
|
||||
onClick={handleLogout}
|
||||
>
|
||||
Keluar Sistem
|
||||
</Menu.Item>
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
</Group>
|
||||
</Group>
|
||||
</AppShell.Header>
|
||||
|
||||
<AppShell.Navbar
|
||||
p="md"
|
||||
style={{ borderRight: "1px solid var(--mantine-color-default-border)" }}
|
||||
>
|
||||
<AppShell.Section grow component={ScrollArea} mx="-md" px="md">
|
||||
<Stack gap="xs" mt="md">
|
||||
{navItems.map((item) => (
|
||||
<Tooltip
|
||||
key={item.to}
|
||||
label={item.description}
|
||||
position="right"
|
||||
disabled={!desktopOpened}
|
||||
openDelay={500}
|
||||
>
|
||||
<NavLink
|
||||
onClick={() => {
|
||||
navigate({ to: item.to });
|
||||
|
||||
if (mobileOpened) toggleMobile();
|
||||
}}
|
||||
leftSection={
|
||||
<item.icon
|
||||
style={{ width: rem(20), height: rem(20) }}
|
||||
stroke={1.5}
|
||||
/>
|
||||
}
|
||||
label={
|
||||
<Box>
|
||||
<Text size="sm" fw={isActive(item.to) ? 700 : 500}>
|
||||
{item.label}
|
||||
</Text>
|
||||
</Box>
|
||||
}
|
||||
rightSection={<IconChevronRight size="0.8rem" stroke={1.5} />}
|
||||
active={isActive(item.to)}
|
||||
variant="light"
|
||||
color="orange"
|
||||
styles={{
|
||||
root: {
|
||||
borderRadius: rem(8),
|
||||
|
||||
marginBottom: rem(4),
|
||||
},
|
||||
|
||||
label: {
|
||||
fontSize: rem(14),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
))}
|
||||
</Stack>
|
||||
</AppShell.Section>
|
||||
|
||||
<AppShell.Section
|
||||
style={{ borderTop: "1px solid var(--mantine-color-default-border)" }}
|
||||
pt="md"
|
||||
>
|
||||
<NavLink
|
||||
label="Pusat Bantuan"
|
||||
leftSection={
|
||||
<IconSettings
|
||||
style={{ width: rem(18), height: rem(18) }}
|
||||
stroke={1.5}
|
||||
/>
|
||||
}
|
||||
styles={{ root: { borderRadius: rem(8) } }}
|
||||
/>
|
||||
|
||||
<NavLink
|
||||
label="Keluar"
|
||||
onClick={handleLogout}
|
||||
leftSection={
|
||||
<IconLogout
|
||||
style={{ width: rem(18), height: rem(18) }}
|
||||
stroke={1.5}
|
||||
color="red"
|
||||
/>
|
||||
}
|
||||
c="red"
|
||||
styles={{ root: { borderRadius: rem(8) } }}
|
||||
/>
|
||||
</AppShell.Section>
|
||||
</AppShell.Navbar>
|
||||
|
||||
<AppShell.Main>
|
||||
<Box p="lg" style={{ minHeight: "calc(100vh - 100px)" }}>
|
||||
<Outlet />
|
||||
</Box>
|
||||
</AppShell.Main>
|
||||
</AppShell>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user