diff --git a/dashboard/.storybook/preview-head.html b/dashboard/.storybook/preview-head.html
new file mode 100644
index 0000000..3f47c99
--- /dev/null
+++ b/dashboard/.storybook/preview-head.html
@@ -0,0 +1,7 @@
+
+
+
+
+
Marzneshin
diff --git a/dashboard/package.json b/dashboard/package.json
index c298722..efe969e 100644
--- a/dashboard/package.json
+++ b/dashboard/package.json
@@ -1,7 +1,7 @@
{
"name": "marzneshin-dashboard",
"private": true,
- "version": "0.0.0",
+ "version": "0.3.0",
"type": "module",
"scripts": {
"dev": "vite",
diff --git a/dashboard/src/components/header/header.stories.tsx b/dashboard/src/components/header/header.stories.tsx
new file mode 100644
index 0000000..84c8b7d
--- /dev/null
+++ b/dashboard/src/components/header/header.stories.tsx
@@ -0,0 +1,44 @@
+import { HeaderMenu, Header } from ".";
+import { CommandBox } from "@marzneshin/features/search-command";
+import { HeaderLogo } from "@marzneshin/components";
+import React from "react";
+import type { Meta, StoryObj } from "@storybook/react";
+
+const HeaderMenuComponent = HeaderMenu as React.FC
+
+const meta: Meta = {
+ title: "Components/Header",
+ component: Header,
+ tags: ["autodocs"],
+ subcomponents: { HeaderMenuComponent }
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+
+export const HeaderAnatomy: Story = {
+ args: {
+ start: Start section
,
+ center: Center section
,
+ end: End section
+ }
+}
+
+export const HeaderWithMenu: Story = {
+ args: {
+ start: Start section
,
+ center: Center section
,
+ end:
+ }
+}
+
+
+export const DashoardHeader: Story = {
+ args: {
+ start: ,
+ center: ,
+ end:
+ }
+}
diff --git a/dashboard/src/components/header/header.tsx b/dashboard/src/components/header/header.tsx
new file mode 100644
index 0000000..cc07c84
--- /dev/null
+++ b/dashboard/src/components/header/header.tsx
@@ -0,0 +1,24 @@
+import type { FC } from "react";
+
+
+interface HeaderProps {
+ start?: React.ReactNode;
+ center?: React.ReactNode;
+ end?: React.ReactNode;
+}
+
+export const Header: FC = ({ start, center, end }) => (
+
+
+
+ {start}
+
+
+ {center}
+
+
+ {end}
+
+
+
+);
diff --git a/dashboard/src/components/header/index.ts b/dashboard/src/components/header/index.ts
new file mode 100644
index 0000000..4177746
--- /dev/null
+++ b/dashboard/src/components/header/index.ts
@@ -0,0 +1,2 @@
+export * from "./menu";
+export * from "./header";
diff --git a/dashboard/src/components/header/index.tsx b/dashboard/src/components/header/index.tsx
deleted file mode 100644
index edaa44c..0000000
--- a/dashboard/src/components/header/index.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import { HeaderMenu } from "./menu";
-import { GithubRepo } from "@marzneshin/features/github-repo";
-import { Link } from "@tanstack/react-router";
-import { CommandBox } from "@marzneshin/features/search-command";
-import type { FC, PropsWithChildren } from "react";
-import { useScreenBreakpoint } from "@marzneshin/hooks/use-screen-breakpoint";
-
-export const Header: FC = ({ children }) => {
- const isDesktop = useScreenBreakpoint("md");
-
- return (
-
-
-
-
- M
-
-
- {children}
-
-
-
-
-
-
-
- );
-};
diff --git a/dashboard/src/components/index.ts b/dashboard/src/components/index.ts
index 4a48089..fc31852 100644
--- a/dashboard/src/components/index.ts
+++ b/dashboard/src/components/index.ts
@@ -14,3 +14,4 @@ export * from "./charts";
export * from "./support-us";
export * from "./loading";
export * from "./entity-field-card";
+export * from "./logo";
diff --git a/dashboard/src/components/logo/index.tsx b/dashboard/src/components/logo/index.tsx
new file mode 100644
index 0000000..0fc6666
--- /dev/null
+++ b/dashboard/src/components/logo/index.tsx
@@ -0,0 +1,5 @@
+export const HeaderLogo = () => {
+ return
+ M
+
;
+}
diff --git a/dashboard/src/components/page/index.tsx b/dashboard/src/components/page/index.tsx
index 61027d2..cabbeae 100644
--- a/dashboard/src/components/page/index.tsx
+++ b/dashboard/src/components/page/index.tsx
@@ -10,7 +10,7 @@ interface PageProps extends PropsWithChildren { }
export const Page: FC = ({ children }) => {
return (
-
+
{children}
diff --git a/dashboard/src/features/footer/index.tsx b/dashboard/src/features/footer/index.tsx
new file mode 100644
index 0000000..d73adbe
--- /dev/null
+++ b/dashboard/src/features/footer/index.tsx
@@ -0,0 +1,9 @@
+import packageJson from '@marzneshin/../package.json' assert { type: 'json' };
+
+export const DashboardFooter = () => {
+ return (
+
+ v{packageJson.version} Marzneshin
+
+ )
+}
diff --git a/dashboard/src/routes/_dashboard.tsx b/dashboard/src/routes/_dashboard.tsx
index b33a568..9e0c7e1 100644
--- a/dashboard/src/routes/_dashboard.tsx
+++ b/dashboard/src/routes/_dashboard.tsx
@@ -1,12 +1,14 @@
import {
- Drawer,
- DrawerContent,
- Header,
- ResizableHandle,
- ResizablePanel,
- ResizablePanelGroup,
- Toaster,
- Loading
+ Drawer,
+ DrawerContent,
+ Header,
+ ResizableHandle,
+ ResizablePanel,
+ ResizablePanelGroup,
+ Toaster,
+ Loading,
+ HeaderLogo,
+ HeaderMenu,
} from "@marzneshin/components";
import { useAuth } from "@marzneshin/features/auth";
import { DashboardSidebar, ToggleButton } from "@marzneshin/features/sidebar";
@@ -15,97 +17,117 @@ import { useScreenBreakpoint } from "@marzneshin/hooks/use-screen-breakpoint";
import { cn } from "@marzneshin/utils";
import { Suspense } from "react";
import {
- Outlet,
- createFileRoute,
- redirect
+ Outlet,
+ Link,
+ createFileRoute,
+ redirect
} from "@tanstack/react-router";
+import { GithubRepo } from "@marzneshin/features/github-repo";
+import { CommandBox } from "@marzneshin/features/search-command";
+import { DashboardFooter } from "@marzneshin/features/footer";
+
export const DashboardLayout = () => {
- const isDesktop = useScreenBreakpoint("md");
- const {
- collapsed,
- panelRef,
- open,
- setCollapsed,
- setOpen,
- toggleCollapse,
- toggleOpen,
- } = usePanelToggle(isDesktop);
+ const isDesktop = useScreenBreakpoint("md");
+ const {
+ collapsed,
+ panelRef,
+ open,
+ setCollapsed,
+ setOpen,
+ toggleCollapse,
+ toggleOpen,
+ } = usePanelToggle(isDesktop);
- return (
-
-
- {isDesktop ? (
-
- setCollapsed(true)}
- onExpand={() => setCollapsed(false)}
- minSize={15}
- className={cn("w-[120px] min-w-[70px]")}
- defaultSize={20}
- ref={panelRef}
- maxSize={30}
- >
-
+
+
+
+
+
+ >
+ }
+ center={
+
+ }
+ end={
+ <>
+
+
+ >
+ }
/>
-
-
-
-
- }>
-
-
-
-
-
-
- ) : (
-
-
-
- }>
-
-
-
-
+ {isDesktop ? (
+
+ setCollapsed(true)}
+ onExpand={() => setCollapsed(false)}
+ minSize={15}
+ className={cn("w-[120px] min-w-[70px]")}
+ defaultSize={20}
+ ref={panelRef}
+ maxSize={30}
+ >
+
+
+
+
+
+ }>
+
+
+
+
+
+
+
+ ) : (
+
+ )}
- )}
-
- );
+ );
};
export const Route = createFileRoute("/_dashboard")({
- component: () => ,
- beforeLoad: async () => {
- const loggedIn = await useAuth.getState().isLoggedIn();
- if (!loggedIn) {
- throw redirect({
- to: "/login",
- });
- }
- },
+ component: () => ,
+ beforeLoad: async () => {
+ const loggedIn = await useAuth.getState().isLoggedIn();
+ if (!loggedIn) {
+ throw redirect({
+ to: "/login",
+ });
+ }
+ },
});