diff --git a/dashboard/15-final/app/dashboard/layout.tsx b/dashboard/15-final/app/dashboard/layout.tsx
index 97101a6..03d4b88 100644
--- a/dashboard/15-final/app/dashboard/layout.tsx
+++ b/dashboard/15-final/app/dashboard/layout.tsx
@@ -1,8 +1,10 @@
+import SideNav from '../ui/dashboard-sidenav';
+
export default function Layout({ children }: { children: React.ReactNode }) {
- return (
-
-
Dashboard layout
-
{children}
-
- )
+ return (
+
+ );
}
diff --git a/dashboard/15-final/app/layout.tsx b/dashboard/15-final/app/layout.tsx
index 139fcc0..db09ef8 100644
--- a/dashboard/15-final/app/layout.tsx
+++ b/dashboard/15-final/app/layout.tsx
@@ -1,13 +1,12 @@
-import "./globals.css"
-import type { Metadata } from "next"
-import { Inter } from "next/font/google"
-
-const inter = Inter({ subsets: ["latin"] })
+import './globals.css';
+import type { Metadata } from 'next';
+import { Inter } from 'next/font/google';
+const inter = Inter({ subsets: ['latin'] });
export const metadata: Metadata = {
- title: "Create Next App",
- description: "Generated by create next app",
-}
+ title: 'Create Next App',
+ description: 'Generated by create next app'
+};
export default function RootLayout({
children,
diff --git a/dashboard/15-final/app/ui/dashboard-sidenav.tsx b/dashboard/15-final/app/ui/dashboard-sidenav.tsx
new file mode 100644
index 0000000..c200510
--- /dev/null
+++ b/dashboard/15-final/app/ui/dashboard-sidenav.tsx
@@ -0,0 +1,47 @@
+'use client';
+
+import { UserGroupIcon, HomeIcon, InboxIcon, PowerIcon } from '@heroicons/react/24/outline';
+import Link from 'next/link';
+import { usePathname } from 'next/navigation';
+
+import Image from 'next/image';
+
+export default function SideNav() {
+ const pathname = usePathname();
+
+ const tabs = [
+ { name: 'Home', href: '/dashboard', icon: HomeIcon },
+ { name: 'Customers', href: '/dashboard/customers', icon: UserGroupIcon },
+ { name: 'Invoices', href: '/dashboard/invoices', icon: InboxIcon }
+ ];
+
+ return (
+
+
+
+
+ {tabs.map((tab, i) => {
+ const TabIcon = tab.icon;
+ return (
+
+
+
{tab.name}
+
+ );
+ })}
+
+
+
Sign Out
+
+
+ );
+}
diff --git a/dashboard/15-final/package-lock.json b/dashboard/15-final/package-lock.json
index e4182fa..c357c8c 100644
--- a/dashboard/15-final/package-lock.json
+++ b/dashboard/15-final/package-lock.json
@@ -8,6 +8,7 @@
"name": "15-final",
"version": "0.1.0",
"dependencies": {
+ "@heroicons/react": "^2.0.18",
"@types/node": "20.5.7",
"@types/react": "18.2.21",
"@types/react-dom": "18.2.7",
@@ -108,6 +109,14 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
+ "node_modules/@heroicons/react": {
+ "version": "2.0.18",
+ "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.0.18.tgz",
+ "integrity": "sha512-7TyMjRrZZMBPa+/5Y8lN0iyvUU/01PeMGX2+RE7cQWpEUIcb4QotzUObFkJDejj/HUH4qjP/eQ0gzzKs2f+6Yw==",
+ "peerDependencies": {
+ "react": ">= 16"
+ }
+ },
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
@@ -4147,6 +4156,12 @@
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz",
"integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw=="
},
+ "@heroicons/react": {
+ "version": "2.0.18",
+ "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.0.18.tgz",
+ "integrity": "sha512-7TyMjRrZZMBPa+/5Y8lN0iyvUU/01PeMGX2+RE7cQWpEUIcb4QotzUObFkJDejj/HUH4qjP/eQ0gzzKs2f+6Yw==",
+ "requires": {}
+ },
"@humanwhocodes/config-array": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
diff --git a/dashboard/15-final/package.json b/dashboard/15-final/package.json
index cf05e6d..e2d852b 100644
--- a/dashboard/15-final/package.json
+++ b/dashboard/15-final/package.json
@@ -12,6 +12,7 @@
"lint": "next lint"
},
"dependencies": {
+ "@heroicons/react": "^2.0.18",
"@types/node": "20.5.7",
"@types/react": "18.2.21",
"@types/react-dom": "18.2.7",