https://dev.kronoz.win/r/marzneshin.git
1import {
2 Header,
3 ResizableHandle,
4 ResizablePanel,
5 ResizablePanelGroup,
6 Toaster,
7 Loading,
8 HeaderLogo,
9 HeaderMenu,
10} from "@marzneshin/components";
11import { useAuth } from "@marzneshin/features/auth";
12import { DashboardSidebar, ToggleButton } from "@marzneshin/features/sidebar";
13import { usePanelToggle } from "@marzneshin/features/sidebar/use-panel-toggle";
14import { useScreenBreakpoint } from "@marzneshin/hooks/use-screen-breakpoint";
15import { cn } from "@marzneshin/utils";
16import { Suspense } from "react";
17import {
18 Outlet,
19 Link,
20 createFileRoute,
21 redirect
22} from "@tanstack/react-router";
23import { useGithubRepoStatsQuery, GithubRepo } from "@marzneshin/features/github-repo";
24import { CommandBox } from "@marzneshin/features/search-command";
25import { DashboardBottomMenu } from "@marzneshin/features/bottom-menu";
26import { VersionIndicator } from "@marzneshin/features/version-indicator";
27
28export const DashboardLayout = () => {
29 const isDesktop = useScreenBreakpoint("md");
30 const {
31 collapsed,
32 panelRef,
33 setCollapsed,
34 toggleCollapse,
35 } = usePanelToggle(isDesktop);
36 const { isSudo } = useAuth();
37 const { data: stats } = useGithubRepoStatsQuery()
38
39 return (
40 <div className="flex flex-col w-screen h-screen">
41 <Header
42 start={
43 <>
44 <Link to="/">
45 <HeaderLogo />
46 </Link>
47 {isDesktop && (
48
49 <ToggleButton
50 collapsed={collapsed}
51 onToggle={toggleCollapse}
52 />
53 )}
54 </>
55 }
56 center={<CommandBox />}
57 end={
58 <>
59 <GithubRepo {...stats} variant={isDesktop ? "full" : "mini"} />
60 <HeaderMenu />
61 </>
62 }
63 />
64 <div className="flex flex-1 overflow-hidden">
65 {isDesktop ? (
66 <ResizablePanelGroup direction="horizontal" className="flex h-full w-full">
67 <ResizablePanel
68 collapsible
69 collapsedSize={2}
70 onCollapse={() => setCollapsed(true)}
71 onExpand={() => setCollapsed(false)}
72 minSize={15}
73 className={cn("w-[120px] min-w-[70px]")}
74 defaultSize={20}
75 ref={panelRef}
76 maxSize={30}
77 >
78 <DashboardSidebar
79 collapsed={collapsed}
80 setCollapsed={setCollapsed}
81 />
82 </ResizablePanel>
83 <ResizableHandle withHandle className="w-[2px]" />
84 <ResizablePanel className="flex-col flex justify-between">
85 <main className="flex flex-col h-full">
86 <Suspense fallback={<Loading />}>
87 <Outlet />
88 </Suspense>
89 </main>
90 <footer className="h-10 py-2">
91 <VersionIndicator />
92 </footer>
93 </ResizablePanel>
94 </ResizablePanelGroup>
95 ) : (
96 <div className="flex flex-col h-full w-full">
97 <main className="flex flex-col h-full overflow-y-auto">
98 <Suspense fallback={<Loading />}>
99 <Outlet />
100 </Suspense>
101 <footer className="h-30 border-t-3 py-2 px-5">
102 <DashboardBottomMenu variant={isSudo() ? "sudo-admin" : "admin"} />
103 </footer>
104 </main>
105 </div>
106 )}
107 </div>
108 <Toaster position="top-center" />
109 </div>
110 );
111};
112
113export const Route = createFileRoute("/_dashboard")({
114 component: () => <DashboardLayout />,
115 beforeLoad: async () => {
116 const loggedIn = await useAuth.getState().isLoggedIn();
117 if (!loggedIn) {
118 throw redirect({
119 to: "/login",
120 });
121 }
122 },
123});