feat: Implement page routing using wouter and add simple mock-up pages
This commit is contained in:
@@ -12,14 +12,16 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@base-ui-components/react": "^1.0.0-beta.3",
|
"@base-ui-components/react": "^1.0.0-beta.3",
|
||||||
"@radix-ui/react-slot": "^1.2.3",
|
"@radix-ui/react-slot": "^1.2.3",
|
||||||
|
"@tabler/icons-react": "^3.35.0",
|
||||||
"@tailwindcss/vite": "^4.1.13",
|
"@tailwindcss/vite": "^4.1.13",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"lucide-react": "^0.543.0",
|
"lucide-react": "^0.544.0",
|
||||||
"react": "^19.1.1",
|
"react": "^19.1.1",
|
||||||
"react-dom": "^19.1.1",
|
"react-dom": "^19.1.1",
|
||||||
"tailwind-merge": "^3.3.1",
|
"tailwind-merge": "^3.3.1",
|
||||||
"tailwindcss": "^4.1.13",
|
"tailwindcss": "^4.1.13",
|
||||||
|
"wouter": "^3.7.1",
|
||||||
"zustand": "^5.0.8"
|
"zustand": "^5.0.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1,12 +1,22 @@
|
|||||||
|
import { Route, Switch } from 'wouter';
|
||||||
|
|
||||||
import Topbar from './Topbar';
|
import Topbar from './Topbar';
|
||||||
|
|
||||||
|
import Home from './pages/Home';
|
||||||
|
import Dashboard from './pages/Dashboard';
|
||||||
|
import Todos from './pages/Todos';
|
||||||
|
import NotFound from './pages/default/NotFound';
|
||||||
|
|
||||||
function PageContainer() {
|
function PageContainer() {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col flex-1">
|
<div className="flex flex-col flex-1">
|
||||||
<Topbar />
|
<Topbar />
|
||||||
<div className="p-4">
|
<Switch>
|
||||||
<h1 className="text-2xl font-bold">Main Content</h1>
|
<Route path="/" component={Home} />
|
||||||
</div>
|
<Route path="/dashboard" component={Dashboard} />
|
||||||
|
<Route path="/todos" component={Todos} />
|
||||||
|
<Route component={NotFound} />
|
||||||
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,40 @@
|
|||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { useLocation, Link } from 'wouter';
|
||||||
|
import {
|
||||||
|
IconHome,
|
||||||
|
IconCalendarWeekFilled,
|
||||||
|
IconLayoutCollage,
|
||||||
|
IconCheckupList,
|
||||||
|
} from '@tabler/icons-react';
|
||||||
|
|
||||||
|
// TODO: Add Sidebar Items(Pages, etc...) to Zustand Store
|
||||||
|
export const items = [
|
||||||
|
{ name: 'Home', href: '/', icon: IconHome },
|
||||||
|
{ name: 'Dashboard', href: '/dashboard', icon: IconLayoutCollage },
|
||||||
|
{ name: 'Todos', href: '/todos', icon: IconCheckupList },
|
||||||
|
{ name: 'Calendar', href: '/calendar', icon: IconCalendarWeekFilled },
|
||||||
|
];
|
||||||
|
|
||||||
function Sidebar() {
|
function Sidebar() {
|
||||||
|
const [location] = useLocation();
|
||||||
return (
|
return (
|
||||||
<nav className="flex justify-center min-w-[240px] max-w-[480px] bg-sidebar border">
|
<nav className="flex flex-col min-w-[240px] max-w-[480px] bg-sidebar border">
|
||||||
<p>Sidebar</p>
|
<div className="flex flex-col m-2 gap-2">
|
||||||
|
<p className="text-muted-foreground text-sm font-bold pl-2">Menus</p>
|
||||||
|
{items.map((item) => (
|
||||||
|
<Button
|
||||||
|
asChild
|
||||||
|
size="sm"
|
||||||
|
key={item.name}
|
||||||
|
variant={location === item.href ? 'secondary' : 'ghost'}
|
||||||
|
className="justify-start"
|
||||||
|
>
|
||||||
|
<Link href={item.href}>
|
||||||
|
<item.icon /> {item.name}
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { items } from './Sidebar';
|
||||||
|
import { useLocation } from 'wouter';
|
||||||
|
|
||||||
function Topbar() {
|
function Topbar() {
|
||||||
|
const [location] = useLocation();
|
||||||
return (
|
return (
|
||||||
<div className="flex bg-sidebar p-2 gap-2 border-t border-r border-b border-l-0">
|
<div className="flex bg-sidebar p-2 gap-2 border-t border-r border-b border-l-0">
|
||||||
<span>item 1</span>
|
<Button variant="ghost" size="sm" className="font-semibold">
|
||||||
<span>item 2</span>
|
{items.find((item) => item.href === location)?.name}
|
||||||
<span>item 3</span>
|
{/* TODO: Add Sidebar Items(Pages, etc...) to Zustand Store */}
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
9
src/components/pages/Dashboard.tsx
Normal file
9
src/components/pages/Dashboard.tsx
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
function Dashboard() {
|
||||||
|
return (
|
||||||
|
<div className="p-4">
|
||||||
|
<h1 className="text-2xl font-bold">Dashboard</h1>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Dashboard;
|
||||||
9
src/components/pages/Home.tsx
Normal file
9
src/components/pages/Home.tsx
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
function Home() {
|
||||||
|
return (
|
||||||
|
<div className="p-4">
|
||||||
|
<h1 className="text-2xl font-bold">Home</h1>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Home;
|
||||||
9
src/components/pages/Todos.tsx
Normal file
9
src/components/pages/Todos.tsx
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
function Todos() {
|
||||||
|
return (
|
||||||
|
<div className="p-4">
|
||||||
|
<h1 className="text-2xl font-bold">Todos</h1>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Todos;
|
||||||
9
src/components/pages/default/NotFound.tsx
Normal file
9
src/components/pages/default/NotFound.tsx
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
function NotFound() {
|
||||||
|
return (
|
||||||
|
<div className="p-4">
|
||||||
|
<h1 className="text-2xl font-bold">404 - Not Found!</h1>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NotFound;
|
||||||
@@ -9,16 +9,15 @@ const buttonVariants = cva(
|
|||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default:
|
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
||||||
'bg-primary text-primary-foreground shadow-xs hover:bg-primary/90',
|
|
||||||
destructive:
|
destructive:
|
||||||
'bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
|
'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
|
||||||
outline:
|
outline:
|
||||||
'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
|
'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
|
||||||
secondary:
|
secondary:
|
||||||
'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',
|
'bg-black/10 text-secondary-foreground hover:bg-black/5 dark:bg-secondary dark:hover:bg-secondary/80',
|
||||||
ghost:
|
ghost:
|
||||||
'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
|
'hover:bg-black/5 hover:text-accent-foreground dark:hover:bg-accent/50',
|
||||||
link: 'text-primary underline-offset-4 hover:underline',
|
link: 'text-primary underline-offset-4 hover:underline',
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
|
|||||||
59
yarn.lock
59
yarn.lock
@@ -866,6 +866,24 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@tabler/icons-react@npm:^3.35.0":
|
||||||
|
version: 3.35.0
|
||||||
|
resolution: "@tabler/icons-react@npm:3.35.0"
|
||||||
|
dependencies:
|
||||||
|
"@tabler/icons": "npm:3.35.0"
|
||||||
|
peerDependencies:
|
||||||
|
react: ">= 16"
|
||||||
|
checksum: 10c0/8d280fcdae00916b001142ba0800ea05d8fa2acdcbd82f88a299b4141fb941237be2e826b86b1af710e038b4f8bb6f76f452c3309c29fd62398b4d5789c2b3e0
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@tabler/icons@npm:3.35.0":
|
||||||
|
version: 3.35.0
|
||||||
|
resolution: "@tabler/icons@npm:3.35.0"
|
||||||
|
checksum: 10c0/93098828128ffed2cf412b39bd78992f93f25b22349a4e04523d2a018b7fe376ddeff105babcc3efedd707aa00b705425c7d9f598d6987552a563c62125795a2
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@tailwindcss/node@npm:4.1.13":
|
"@tailwindcss/node@npm:4.1.13":
|
||||||
version: 4.1.13
|
version: 4.1.13
|
||||||
resolution: "@tailwindcss/node@npm:4.1.13"
|
resolution: "@tailwindcss/node@npm:4.1.13"
|
||||||
@@ -1883,6 +1901,7 @@ __metadata:
|
|||||||
"@base-ui-components/react": "npm:^1.0.0-beta.3"
|
"@base-ui-components/react": "npm:^1.0.0-beta.3"
|
||||||
"@eslint/js": "npm:^9.33.0"
|
"@eslint/js": "npm:^9.33.0"
|
||||||
"@radix-ui/react-slot": "npm:^1.2.3"
|
"@radix-ui/react-slot": "npm:^1.2.3"
|
||||||
|
"@tabler/icons-react": "npm:^3.35.0"
|
||||||
"@tailwindcss/vite": "npm:^4.1.13"
|
"@tailwindcss/vite": "npm:^4.1.13"
|
||||||
"@types/node": "npm:^24.3.1"
|
"@types/node": "npm:^24.3.1"
|
||||||
"@types/react": "npm:^19.1.10"
|
"@types/react": "npm:^19.1.10"
|
||||||
@@ -1894,7 +1913,7 @@ __metadata:
|
|||||||
eslint-plugin-react-hooks: "npm:^5.2.0"
|
eslint-plugin-react-hooks: "npm:^5.2.0"
|
||||||
eslint-plugin-react-refresh: "npm:^0.4.20"
|
eslint-plugin-react-refresh: "npm:^0.4.20"
|
||||||
globals: "npm:^16.3.0"
|
globals: "npm:^16.3.0"
|
||||||
lucide-react: "npm:^0.543.0"
|
lucide-react: "npm:^0.544.0"
|
||||||
react: "npm:^19.1.1"
|
react: "npm:^19.1.1"
|
||||||
react-dom: "npm:^19.1.1"
|
react-dom: "npm:^19.1.1"
|
||||||
tailwind-merge: "npm:^3.3.1"
|
tailwind-merge: "npm:^3.3.1"
|
||||||
@@ -1903,6 +1922,7 @@ __metadata:
|
|||||||
typescript: "npm:~5.8.3"
|
typescript: "npm:~5.8.3"
|
||||||
typescript-eslint: "npm:^8.39.1"
|
typescript-eslint: "npm:^8.39.1"
|
||||||
vite: "npm:^7.1.2"
|
vite: "npm:^7.1.2"
|
||||||
|
wouter: "npm:^3.7.1"
|
||||||
zustand: "npm:^5.0.8"
|
zustand: "npm:^5.0.8"
|
||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
@@ -2328,12 +2348,12 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"lucide-react@npm:^0.543.0":
|
"lucide-react@npm:^0.544.0":
|
||||||
version: 0.543.0
|
version: 0.544.0
|
||||||
resolution: "lucide-react@npm:0.543.0"
|
resolution: "lucide-react@npm:0.544.0"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||||
checksum: 10c0/76bb54f9c602ff5d44ec66f2786c035d92aaabca1e1abb380b0c8101dfb3290e52c82fa4d630e286ef07c05b63696e187f0ca3ae186535d9c5b4de7aa8825bd3
|
checksum: 10c0/2503f8cf65e62915997073b6053423bf8091b9470cb397560b417ef2f1628ea162c49e821b787cf153afb86828482d941f051c3f2aa642a1fa58c3de227e0113
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -2476,6 +2496,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"mitt@npm:^3.0.1":
|
||||||
|
version: 3.0.1
|
||||||
|
resolution: "mitt@npm:3.0.1"
|
||||||
|
checksum: 10c0/3ab4fdecf3be8c5255536faa07064d05caa3dd332bd318ff02e04621f7b3069ca1de9106cfe8e7ced675abfc2bec2ce4c4ef321c4a1bb1fb29df8ae090741913
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"mkdirp@npm:^3.0.1":
|
"mkdirp@npm:^3.0.1":
|
||||||
version: 3.0.1
|
version: 3.0.1
|
||||||
resolution: "mkdirp@npm:3.0.1"
|
resolution: "mkdirp@npm:3.0.1"
|
||||||
@@ -2713,6 +2740,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"regexparam@npm:^3.0.0":
|
||||||
|
version: 3.0.0
|
||||||
|
resolution: "regexparam@npm:3.0.0"
|
||||||
|
checksum: 10c0/a6430d7b97d5a7d5518f37a850b6b73aab479029d02f46af4fa0e8e4a1d7aad05b7a0d2d10c86ded21a14d5f0fa4c68525f873a5fca2efeefcccd93c36627459
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"reselect@npm:^5.1.1":
|
"reselect@npm:^5.1.1":
|
||||||
version: 5.1.1
|
version: 5.1.1
|
||||||
resolution: "reselect@npm:5.1.1"
|
resolution: "reselect@npm:5.1.1"
|
||||||
@@ -3136,7 +3170,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"use-sync-external-store@npm:^1.5.0":
|
"use-sync-external-store@npm:^1.0.0, use-sync-external-store@npm:^1.5.0":
|
||||||
version: 1.5.0
|
version: 1.5.0
|
||||||
resolution: "use-sync-external-store@npm:1.5.0"
|
resolution: "use-sync-external-store@npm:1.5.0"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -3229,6 +3263,19 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"wouter@npm:^3.7.1":
|
||||||
|
version: 3.7.1
|
||||||
|
resolution: "wouter@npm:3.7.1"
|
||||||
|
dependencies:
|
||||||
|
mitt: "npm:^3.0.1"
|
||||||
|
regexparam: "npm:^3.0.0"
|
||||||
|
use-sync-external-store: "npm:^1.0.0"
|
||||||
|
peerDependencies:
|
||||||
|
react: ">=16.8.0"
|
||||||
|
checksum: 10c0/1974f32f425c1cf6412e6946936e37db3a283e6e6965acd336ce04d67bb36fbf2c40fc90a1bc4537930b326e370b5e053437e0f80554cb94d34ec8c354b86693
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
|
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
|
||||||
version: 7.0.0
|
version: 7.0.0
|
||||||
resolution: "wrap-ansi@npm:7.0.0"
|
resolution: "wrap-ansi@npm:7.0.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user