gitscope
← marzneshin / Diff · c5c71ec → c5c71ec
Changes c5c71ec..c5c71ec
Patch commit
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 @@
+
+<link rel="preconnect" href="https://fonts.googleapis.com">
+<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+<link
+href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&family=Ubuntu:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&display=swap"
+rel="stylesheet">
+<title>Marzneshin</title>
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<unknown>
+
+const meta: Meta<typeof Header> = {
+ title: "Components/Header",
+ component: Header,
+ tags: ["autodocs"],
+ subcomponents: { HeaderMenuComponent }
+};
+
+export default meta;
+
+type Story = StoryObj<typeof Header>;
+
+
+export const HeaderAnatomy: Story = {
+ args: {
+ start: <h1>Start section</h1>,
+ center: <h1>Center section</h1>,
+ end: <h1>End section</h1>
+ }
+}
+
+export const HeaderWithMenu: Story = {
+ args: {
+ start: <h1>Start section</h1>,
+ center: <h1>Center section</h1>,
+ end: <HeaderMenu />
+ }
+}
+
+
+export const DashoardHeader: Story = {
+ args: {
+ start: <HeaderLogo />,
+ center: <CommandBox />,
+ end: <HeaderMenu />
+ }
+}
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<HeaderProps> = ({ start, center, end }) => (
+ <header className="h-[3.5rem]">
+ <div className="flex flex-row justify-between justify-items-stretch items-center lg:grid grid-cols-3 p-1 px-4 w-full h-full bg-primary text-primary-foreground dark:bg-primary-foreground">
+ <div className="flex flex-row gap-2 justify-center-start justify-start items-center">
+ {start}
+ </div>
+ <div className="justify-center justify-self-center">
+ {center}
+ </div>
+ <div className="flex flex-row gap-2 h-10 justify-end justify-self-end items-center">
+ {end}
+ </div>
+ </div>
+ </header>
+);
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<PropsWithChildren> = ({ children }) => {
- const isDesktop = useScreenBreakpoint("md");
-
- return (
- <div className="flex flex-row justify-between items-center p-1 px-4 w-full h-full bg-primary text-primary-foreground dark:bg-primary-foreground">
- <div className="flex flex-row gap-4 justify-center items-center">
- <Link to="/">
- <div className="flex flex-col justify-center items-center p-2 h-10 text-2xl font-bold bg-gray-800 rounded-lg font-header text-secondary border-accent dark:text-secondary-foreground">
- M
- </div>
- </Link>
- {children}
- <CommandBox />
- </div>
- <div className="flex flex-row gap-2 h-10">
- <GithubRepo variant={isDesktop ? "full" : "mini"} />
- <HeaderMenu />
- </div>
- </div>
- );
-};
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 <div className="flex flex-col justify-center items-center p-2 h-10 text-2xl font-bold bg-gray-800 rounded-lg font-header text-secondary border-accent dark:text-secondary-foreground">
+ M
+ </div>;
+}
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<PageProps> = ({ children }) => {
return (
- <ScrollArea style={{ height: `calc(100vh - 4.5rem)` }} className="sm:w-screen md:p-3 md:w-[100%]">
+ <ScrollArea style={{ height: `calc(100vh - 4.8rem)` }} className="sm:w-screen md:p-3 md:w-[100%]">
<div className="flex flex-col justify-center items-center h-full sm:w-screen md:w-[100%]">
{children}
</div>
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 (
+ <div className="size-full flex justify-center items-center dark:text-neutral-300 text-neutral-800">
+ v{packageJson.version} Marzneshin
+ </div>
+ )
+}
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 (
- <div className="flex flex-col w-screen h-screen">
- <header className="h-[3.5rem]">
- <Header>
- <ToggleButton
- isDesktop={isDesktop}
- collapsed={collapsed}
- open={open}
- onToggle={isDesktop ? toggleCollapse : toggleOpen}
- />
- </Header>
- </header>
- {isDesktop ? (
- <ResizablePanelGroup direction="horizontal" className="block sm:hidden">
- <ResizablePanel
- collapsible
- collapsedSize={2}
- onCollapse={() => setCollapsed(true)}
- onExpand={() => setCollapsed(false)}
- minSize={15}
- className={cn("w-[120px] min-w-[70px]")}
- defaultSize={20}
- ref={panelRef}
- maxSize={30}
- >
- <DashboardSidebar
- collapsed={collapsed}
- setCollapsed={setCollapsed}
+ return (
+ <div className="flex flex-col w-screen h-screen">
+ <Header
+ start={
+ <>
+ <Link to="/">
+ <HeaderLogo />
+ </Link>
+ <ToggleButton
+ isDesktop={isDesktop}
+ collapsed={collapsed}
+ open={open}
+ onToggle={isDesktop ? toggleCollapse : toggleOpen}
+ />
+ </>
+ }
+ center={
+ <CommandBox />
+ }
+ end={
+ <>
+ <GithubRepo variant={isDesktop ? "full" : "mini"} />
+ <HeaderMenu />
+ </>
+ }
/>
- </ResizablePanel>
- <ResizableHandle withHandle className="w-[2px]" />
- <ResizablePanel>
- <main>
- <Suspense fallback={<Loading />}>
- <Outlet />
- </Suspense>
- <Toaster position="top-center" />
- </main>
- </ResizablePanel>
- </ResizablePanelGroup>
- ) : (
- <div>
- <aside>
- <Drawer open={open} onOpenChange={setOpen}>
- <DrawerContent>
- <DashboardSidebar
- collapsed={collapsed}
- setCollapsed={setCollapsed}
- setOpen={setOpen}
- open={open}
- />
- </DrawerContent>
- </Drawer>
- </aside>
- <main className="sm:block">
- <Suspense fallback={<Loading />}>
- <Outlet />
- </Suspense>
- <Toaster position="top-center" />
- </main>
+ {isDesktop ? (
+ <ResizablePanelGroup direction="horizontal" className="block sm:hidden">
+ <ResizablePanel
+ collapsible
+ collapsedSize={2}
+ onCollapse={() => setCollapsed(true)}
+ onExpand={() => setCollapsed(false)}
+ minSize={15}
+ className={cn("w-[120px] min-w-[70px]")}
+ defaultSize={20}
+ ref={panelRef}
+ maxSize={30}
+ >
+ <DashboardSidebar
+ collapsed={collapsed}
+ setCollapsed={setCollapsed}
+ />
+ </ResizablePanel>
+ <ResizableHandle withHandle className="w-[2px]" />
+ <ResizablePanel>
+ <main className="flex flex-col items-center justify-center">
+ <Suspense fallback={<Loading />}>
+ <Outlet />
+ <DashboardFooter />
+ </Suspense>
+ <Toaster position="top-center" />
+ </main>
+ </ResizablePanel>
+ </ResizablePanelGroup>
+ ) : (
+ <div>
+ <aside>
+ <Drawer open={open} onOpenChange={setOpen}>
+ <DrawerContent>
+ <DashboardSidebar
+ collapsed={collapsed}
+ setCollapsed={setCollapsed}
+ setOpen={setOpen}
+ open={open}
+ />
+ </DrawerContent>
+ </Drawer>
+ </aside>
+ <main className="sm:block">
+ <Suspense fallback={<Loading />}>
+ <Outlet />
+ </Suspense>
+ <Toaster position="top-center" />
+ </main>
+ </div>
+ )}
</div>
- )}
- </div>
- );
+ );
};
export const Route = createFileRoute("/_dashboard")({
- component: () => <DashboardLayout />,
- beforeLoad: async () => {
- const loggedIn = await useAuth.getState().isLoggedIn();
- if (!loggedIn) {
- throw redirect({
- to: "/login",
- });
- }
- },
+ component: () => <DashboardLayout />,
+ beforeLoad: async () => {
+ const loggedIn = await useAuth.getState().isLoggedIn();
+ if (!loggedIn) {
+ throw redirect({
+ to: "/login",
+ });
+ }
+ },
});