From 52b0f09440def213c0fbc3dd27c4f0001f19ec64 Mon Sep 17 00:00:00 2001 From: Sianida26 Date: Mon, 22 Jan 2024 00:35:43 +0700 Subject: [PATCH] Added base appshell --- package.json | 94 +++++++++--------- pnpm-lock.yaml | 50 ++++++---- src/app/components/AppNavbar/Navbar.tsx | 8 -- src/app/dashboard/layout.tsx | 26 ++--- src/assets/logos/logo-dsg.png | Bin 0 -> 14581 bytes src/{app => }/components/AppHeader/Header.tsx | 15 +-- src/{app => }/components/AppHeader/index.ts | 0 src/components/AppNavbar/Navbar.tsx | 19 ++++ .../AppNavbar/_components/ChildMenu.tsx | 23 +++++ .../AppNavbar/_components/MenuItem.tsx | 71 +++++++++++++ .../_components/childMenu.module.css | 16 +++ .../AppNavbar/_components/menuItem.module.css | 17 ++++ src/components/AppNavbar/_data/allMenu.ts | 31 ++++++ src/{app => }/components/AppNavbar/index.ts | 0 .../DashboardLayout/DashboardLayout.tsx | 35 +++++++ src/components/DashboardLayout/index.ts | 3 + 16 files changed, 311 insertions(+), 97 deletions(-) delete mode 100644 src/app/components/AppNavbar/Navbar.tsx create mode 100644 src/assets/logos/logo-dsg.png rename src/{app => }/components/AppHeader/Header.tsx (57%) rename src/{app => }/components/AppHeader/index.ts (100%) create mode 100644 src/components/AppNavbar/Navbar.tsx create mode 100644 src/components/AppNavbar/_components/ChildMenu.tsx create mode 100644 src/components/AppNavbar/_components/MenuItem.tsx create mode 100644 src/components/AppNavbar/_components/childMenu.module.css create mode 100644 src/components/AppNavbar/_components/menuItem.module.css create mode 100644 src/components/AppNavbar/_data/allMenu.ts rename src/{app => }/components/AppNavbar/index.ts (100%) create mode 100644 src/components/DashboardLayout/DashboardLayout.tsx create mode 100644 src/components/DashboardLayout/index.ts diff --git a/package.json b/package.json index be8dbee..89f72bb 100644 --- a/package.json +++ b/package.json @@ -1,47 +1,49 @@ { - "name": "dashboard-template", - "version": "0.1.0", - "private": true, - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint" - }, - "dependencies": { - "@auth/prisma-adapter": "^1.0.14", - "@mantine/core": "^7.4.0", - "@mantine/form": "^7.4.0", - "@mantine/hooks": "^7.4.0", - "@prisma/client": "5.7.1", - "@tanstack/react-query": "^4.36.1", - "@tanstack/react-query-devtools": "^4.36.1", - "@trpc/client": "^10.45.0", - "@trpc/next": "^10.45.0", - "@trpc/react-query": "^10.45.0", - "@trpc/server": "^10.45.0", - "@types/bcrypt": "^5.0.2", - "@types/jsonwebtoken": "^9.0.5", - "bcrypt": "^5.1.1", - "jsonwebtoken": "^9.0.2", - "next": "14.0.4", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "superjson": "^2.2.1", - "zod": "^3.22.4" - }, - "devDependencies": { - "@types/node": "^20.10.6", - "@types/react": "^18.2.47", - "@types/react-dom": "^18.2.18", - "autoprefixer": "^10.4.16", - "eslint": "^8.56.0", - "eslint-config-next": "14.0.4", - "postcss": "^8.4.33", - "postcss-preset-mantine": "^1.12.3", - "postcss-simple-vars": "^7.0.1", - "prisma": "^5.7.1", - "tailwindcss": "^3.4.1", - "typescript": "^5.3.3" - } -} + "name": "dashboard-template", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "@auth/prisma-adapter": "^1.0.14", + "@mantine/core": "^7.4.0", + "@mantine/form": "^7.4.0", + "@mantine/hooks": "^7.4.0", + "@prisma/client": "5.7.1", + "@tanstack/react-query": "^4.36.1", + "@tanstack/react-query-devtools": "^4.36.1", + "@trpc/client": "^10.45.0", + "@trpc/next": "^10.45.0", + "@trpc/react-query": "^10.45.0", + "@trpc/server": "^10.45.0", + "@types/bcrypt": "^5.0.2", + "@types/jsonwebtoken": "^9.0.5", + "bcrypt": "^5.1.1", + "jsonwebtoken": "^9.0.2", + "next": "14.0.4", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-icons": "^5.0.1", + "sass": "^1.70.0", + "superjson": "^2.2.1", + "zod": "^3.22.4" + }, + "devDependencies": { + "@types/node": "^20.10.6", + "@types/react": "^18.2.47", + "@types/react-dom": "^18.2.18", + "autoprefixer": "^10.4.16", + "eslint": "^8.56.0", + "eslint-config-next": "14.0.4", + "postcss": "^8.4.33", + "postcss-preset-mantine": "^1.12.3", + "postcss-simple-vars": "^7.0.1", + "prisma": "^5.7.1", + "tailwindcss": "^3.4.1", + "typescript": "^5.3.3" + } +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c59a4e0..a45aa2f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -52,13 +52,19 @@ dependencies: version: 9.0.2 next: specifier: 14.0.4 - version: 14.0.4(react-dom@18.2.0)(react@18.2.0) + version: 14.0.4(react-dom@18.2.0)(react@18.2.0)(sass@1.70.0) react: specifier: ^18.2.0 version: 18.2.0 react-dom: specifier: ^18.2.0 version: 18.2.0(react@18.2.0) + react-icons: + specifier: ^5.0.1 + version: 5.0.1(react@18.2.0) + sass: + specifier: ^1.70.0 + version: 1.70.0 superjson: specifier: ^2.2.1 version: 2.2.1 @@ -594,7 +600,7 @@ packages: '@trpc/client': 10.45.0(@trpc/server@10.45.0) '@trpc/react-query': 10.45.0(@tanstack/react-query@4.36.1)(@trpc/client@10.45.0)(@trpc/server@10.45.0)(react-dom@18.2.0)(react@18.2.0) '@trpc/server': 10.45.0 - next: 14.0.4(react-dom@18.2.0)(react@18.2.0) + next: 14.0.4(react-dom@18.2.0)(react@18.2.0)(sass@1.70.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -798,7 +804,6 @@ packages: dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 - dev: true /aproba@2.0.0: resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} @@ -970,7 +975,6 @@ packages: /binary-extensions@2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} - dev: true /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -989,7 +993,6 @@ packages: engines: {node: '>=8'} dependencies: fill-range: 7.0.1 - dev: true /browserslist@4.22.2: resolution: {integrity: sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==} @@ -1055,7 +1058,6 @@ packages: readdirp: 3.6.0 optionalDependencies: fsevents: 2.3.3 - dev: true /chownr@2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} @@ -1666,7 +1668,6 @@ packages: engines: {node: '>=8'} dependencies: to-regex-range: 5.0.1 - dev: true /find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} @@ -1722,7 +1723,6 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] requiresBuild: true - dev: true optional: true /function-bind@1.1.2: @@ -1791,7 +1791,6 @@ packages: engines: {node: '>= 6'} dependencies: is-glob: 4.0.3 - dev: true /glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} @@ -1934,6 +1933,10 @@ packages: engines: {node: '>= 4'} dev: true + /immutable@4.3.4: + resolution: {integrity: sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==} + dev: false + /import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -1997,7 +2000,6 @@ packages: engines: {node: '>=8'} dependencies: binary-extensions: 2.2.0 - dev: true /is-boolean-object@1.1.2: resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} @@ -2028,7 +2030,6 @@ packages: /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - dev: true /is-finalizationregistry@1.0.2: resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} @@ -2052,7 +2053,6 @@ packages: engines: {node: '>=0.10.0'} dependencies: is-extglob: 2.1.1 - dev: true /is-map@2.0.2: resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} @@ -2073,7 +2073,6 @@ packages: /is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - dev: true /is-path-inside@3.0.3: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} @@ -2437,7 +2436,7 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true - /next@14.0.4(react-dom@18.2.0)(react@18.2.0): + /next@14.0.4(react-dom@18.2.0)(react@18.2.0)(sass@1.70.0): resolution: {integrity: sha512-qbwypnM7327SadwFtxXnQdGiKpkuhaRLE2uq62/nRul9cj9KhQ5LhHmlziTNqUidZotw/Q1I9OjirBROdUJNgA==} engines: {node: '>=18.17.0'} hasBin: true @@ -2460,6 +2459,7 @@ packages: postcss: 8.4.31 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + sass: 1.70.0 styled-jsx: 5.1.1(react@18.2.0) watchpack: 2.4.0 optionalDependencies: @@ -2508,7 +2508,6 @@ packages: /normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} - dev: true /normalize-range@0.1.2: resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} @@ -2674,7 +2673,6 @@ packages: /picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - dev: true /pify@2.3.0: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} @@ -2853,6 +2851,14 @@ packages: scheduler: 0.23.0 dev: false + /react-icons@5.0.1(react@18.2.0): + resolution: {integrity: sha512-WqLZJ4bLzlhmsvme6iFdgO8gfZP17rfjYEJ2m9RsZjZ+cc4k1hTzknEz63YS1MeT50kVzoa1Nz36f4BEx+Wigw==} + peerDependencies: + react: '*' + dependencies: + react: 18.2.0 + dev: false + /react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} @@ -2960,7 +2966,6 @@ packages: engines: {node: '>=8.10.0'} dependencies: picomatch: 2.3.1 - dev: true /reflect.getprototypeof@1.0.4: resolution: {integrity: sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==} @@ -3056,6 +3061,16 @@ packages: is-regex: 1.1.4 dev: true + /sass@1.70.0: + resolution: {integrity: sha512-uUxNQ3zAHeAx5nRFskBnrWzDUJrrvpCPD5FNAoRvTi0WwremlheES3tg+56PaVtCs5QDRX5CBLxxKMDJMEa1WQ==} + engines: {node: '>=14.0.0'} + hasBin: true + dependencies: + chokidar: 3.5.3 + immutable: 4.3.4 + source-map-js: 1.0.2 + dev: false + /scheduler@0.23.0: resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} dependencies: @@ -3364,7 +3379,6 @@ packages: engines: {node: '>=8.0'} dependencies: is-number: 7.0.0 - dev: true /tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} diff --git a/src/app/components/AppNavbar/Navbar.tsx b/src/app/components/AppNavbar/Navbar.tsx deleted file mode 100644 index 7f92b56..0000000 --- a/src/app/components/AppNavbar/Navbar.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { AppShell } from '@mantine/core' -import React from 'react' - -export default function AppNavbar() { - return ( - a - ) -} diff --git a/src/app/dashboard/layout.tsx b/src/app/dashboard/layout.tsx index 83b3d49..18c2d96 100644 --- a/src/app/dashboard/layout.tsx +++ b/src/app/dashboard/layout.tsx @@ -1,33 +1,21 @@ -"use client" import { AppShell, AppShellHeader, Burger } from '@mantine/core' import { useDisclosure } from '@mantine/hooks' import Image from 'next/image' import React from 'react' import logo from "@/assets/logos/logo.png" -import AppHeader from '../components/AppHeader' -import AppNavbar from '../components/AppNavbar' +import AppHeader from '../../components/AppHeader' +import AppNavbar from '../../components/AppNavbar' +import DashboardLayout from '@/components/DashboardLayout' interface Props { children: React.ReactNode } -export default function layout(props: Props) { - - const [openNavbar, { toggle }] = useDisclosure(false) +export default function Layout(props: Props) { return ( - - {/* Header */} - - - {/* Navbar */} - - - {props.children} - + + {props.children} + ) } diff --git a/src/assets/logos/logo-dsg.png b/src/assets/logos/logo-dsg.png new file mode 100644 index 0000000000000000000000000000000000000000..c65edc6b4eb91fb0fb1683d4d2372586930dab15 GIT binary patch literal 14581 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 lVST%7bA8z1UY2K(wmosG7p}%jxO void +} - const [openNavbar, { toggle }] = useDisclosure() +export default function AppHeader(props: Props) { return ( - + ) diff --git a/src/app/components/AppHeader/index.ts b/src/components/AppHeader/index.ts similarity index 100% rename from src/app/components/AppHeader/index.ts rename to src/components/AppHeader/index.ts diff --git a/src/components/AppNavbar/Navbar.tsx b/src/components/AppNavbar/Navbar.tsx new file mode 100644 index 0000000..6c09465 --- /dev/null +++ b/src/components/AppNavbar/Navbar.tsx @@ -0,0 +1,19 @@ +import { AppShell, ScrollArea } from '@mantine/core' +import React from 'react' +import allMenu from './_data/allMenu' +import MenuItem from './_components/MenuItem' + +export default function AppNavbar() { + + const menus = allMenu.map((menu, i) => ) + + return ( + + +
+ {menus} +
+
+
+ ) +} diff --git a/src/components/AppNavbar/_components/ChildMenu.tsx b/src/components/AppNavbar/_components/ChildMenu.tsx new file mode 100644 index 0000000..69fcf15 --- /dev/null +++ b/src/components/AppNavbar/_components/ChildMenu.tsx @@ -0,0 +1,23 @@ +import { Text } from "@mantine/core"; +import React from "react"; + +import classNames from "./childMenu.module.css"; +import { MenuItem } from "../_data/allMenu"; +import { isNotEmpty } from "@mantine/form"; + +interface Props { + item: NonNullable[number]; +} + +export default function ChildMenu(props: Props) { + return ( + + component="a" + className={classNames.link} + href={props.item.link} + onClick={(e) => e.preventDefault()} + > + {props.item.label} + + ); +} diff --git a/src/components/AppNavbar/_components/MenuItem.tsx b/src/components/AppNavbar/_components/MenuItem.tsx new file mode 100644 index 0000000..05f0bab --- /dev/null +++ b/src/components/AppNavbar/_components/MenuItem.tsx @@ -0,0 +1,71 @@ +import React, { useState } from "react"; +import { + Box, + Collapse, + Group, + ThemeIcon, + UnstyledButton, + rem, +} from "@mantine/core"; +import { MenuItem } from "../_data/allMenu"; +import { TbChevronRight } from "react-icons/tb"; + +import classNames from "./menuItem.module.css"; +import ChildMenu from "./ChildMenu"; + +interface Props { + menu: MenuItem; +} + +export default function MenuItem({ menu }: Props) { + const hasChildren = Array.isArray(menu.children); + + const [opened, setOpened] = useState(false); + + const toggleOpenMenu = () => { + setOpened((prev) => !prev); + }; + + const subItems = (hasChildren ? menu.children! : []).map((child, i) => ( + + )); + + return ( + <> + {/* Main Section */} + + + {/* Left Section */} + + {/* Icon */} + + + + + {/* Label */} + {menu.label} + + + {/* Right Section (Chevron if available) */} + {hasChildren && ( + + )} + + + {hasChildren ? {subItems} : null} + + ); +} diff --git a/src/components/AppNavbar/_components/childMenu.module.css b/src/components/AppNavbar/_components/childMenu.module.css new file mode 100644 index 0000000..43fe7a7 --- /dev/null +++ b/src/components/AppNavbar/_components/childMenu.module.css @@ -0,0 +1,16 @@ +.link { + font-weight: 500; + display: block; + text-decoration: none; + padding: var(--mantine-spacing-xs) var(--mantine-spacing-md); + padding-left: var(--mantine-spacing-md); + margin-left: var(--mantine-spacing-xl); + font-size: var(--mantine-font-size-sm); + color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-0)); + border-left: 1px solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4)); + + @mixin hover { + background-color: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-7)); + color: light-dark(var(--mantine-color-black), var(--mantine-color-dark-0)); + } + } \ No newline at end of file diff --git a/src/components/AppNavbar/_components/menuItem.module.css b/src/components/AppNavbar/_components/menuItem.module.css new file mode 100644 index 0000000..aab6b80 --- /dev/null +++ b/src/components/AppNavbar/_components/menuItem.module.css @@ -0,0 +1,17 @@ +.control { + font-weight: 500; + display: block; + width: 100%; + padding: var(--mantine-spacing-xs) var(--mantine-spacing-md); + color: var(--mantine-color-text); + font-size: var(--mantine-font-size-sm); + + @mixin hover { + background-color: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-7)); + color: light-dark(var(--mantine-color-black), var(--mantine-color-dark-0)); + } + } + + .chevron { + transition: transform 200ms ease; + } \ No newline at end of file diff --git a/src/components/AppNavbar/_data/allMenu.ts b/src/components/AppNavbar/_data/allMenu.ts new file mode 100644 index 0000000..2793aec --- /dev/null +++ b/src/components/AppNavbar/_data/allMenu.ts @@ -0,0 +1,31 @@ +import React from "react"; +import { TbLayoutDashboard, TbUsers } from "react-icons/tb"; + +export interface MenuItem { + label: string, + icon: React.FC, + children?: { + label: string, + link: string, + }[], + color?: string, +} + +const allMenu: MenuItem[] = [ + { + label: "Dashboard", + icon: TbLayoutDashboard, + }, + { + label: "Users", + icon: TbUsers, + color: "green", + children: [ + { label: "Users", link: "#"}, + { label: "Roles", link: "#"}, + { label: "Permissions", link: "#"}, + ] + }, +]; + +export default allMenu; diff --git a/src/app/components/AppNavbar/index.ts b/src/components/AppNavbar/index.ts similarity index 100% rename from src/app/components/AppNavbar/index.ts rename to src/components/AppNavbar/index.ts diff --git a/src/components/DashboardLayout/DashboardLayout.tsx b/src/components/DashboardLayout/DashboardLayout.tsx new file mode 100644 index 0000000..cc35aa2 --- /dev/null +++ b/src/components/DashboardLayout/DashboardLayout.tsx @@ -0,0 +1,35 @@ +"use client"; +import React from "react"; +import { AppShell, AppShellHeader, Burger } from "@mantine/core"; +import AppHeader from "../AppHeader"; +import AppNavbar from "../AppNavbar"; + +import { useDisclosure } from "@mantine/hooks"; + +interface Props { + children: React.ReactNode; +} + +export default function DashboardLayout(props: Props) { + const [openNavbar, { toggle }] = useDisclosure(false); + + return ( + + {/* Header */} + + + {/* Navbar */} + + + {props.children} + + ); +} diff --git a/src/components/DashboardLayout/index.ts b/src/components/DashboardLayout/index.ts new file mode 100644 index 0000000..66b1c0a --- /dev/null +++ b/src/components/DashboardLayout/index.ts @@ -0,0 +1,3 @@ +import DashboardLayout from "./DashboardLayout"; + +export default DashboardLayout;