feat(ui): 构建 dashboard 基础布局与路由重定向
This commit is contained in:
parent
8563d0385c
commit
9d4af9a817
40
app/dashboard/layout.tsx
Normal file
40
app/dashboard/layout.tsx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { LayoutGrid, Wallet, ArrowLeftRight } from 'lucide-react';
|
||||||
|
import { ThemeToggle } from '@/components/theme-toggle';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
|
||||||
|
export default function DashboardLayout({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen flex">
|
||||||
|
<aside className="w-64 border-r border-border bg-card p-4 flex flex-col">
|
||||||
|
<div className="flex items-center gap-2 mb-8">
|
||||||
|
<span className="text-xl font-bold">Omniledger</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav className="flex flex-col gap-2 flex-1">
|
||||||
|
<Button variant="ghost" className="justify-start gap-2">
|
||||||
|
<LayoutGrid className="h-4 w-4" />
|
||||||
|
总览 (Overview)
|
||||||
|
</Button>
|
||||||
|
<Button variant="ghost" className="justify-start gap-2">
|
||||||
|
<Wallet className="h-4 w-4" />
|
||||||
|
资产 (Assets)
|
||||||
|
</Button>
|
||||||
|
<Button variant="ghost" className="justify-start gap-2">
|
||||||
|
<ArrowLeftRight className="h-4 w-4" />
|
||||||
|
流水 (Transactions)
|
||||||
|
</Button>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div className="mt-auto flex justify-end">
|
||||||
|
<ThemeToggle />
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<main className="flex-1 p-6">{children}</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
14
app/dashboard/page.tsx
Normal file
14
app/dashboard/page.tsx
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function DashboardPage() {
|
||||||
|
return (
|
||||||
|
<Card className="max-w-md">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>欢迎来到 Omniledger</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<p className="text-muted-foreground">您的跨界记账中枢。</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
67
app/page.tsx
67
app/page.tsx
@ -1,66 +1,5 @@
|
|||||||
import Image from "next/image";
|
import { redirect } from 'next/navigation';
|
||||||
import styles from "./page.module.css";
|
|
||||||
|
|
||||||
export default function Home() {
|
export default function HomePage() {
|
||||||
return (
|
redirect('/dashboard');
|
||||||
<div className={styles.page}>
|
|
||||||
<main className={styles.main}>
|
|
||||||
<Image
|
|
||||||
className={styles.logo}
|
|
||||||
src="/next.svg"
|
|
||||||
alt="Next.js logo"
|
|
||||||
width={100}
|
|
||||||
height={20}
|
|
||||||
priority
|
|
||||||
/>
|
|
||||||
<div className={styles.intro}>
|
|
||||||
<h1>To get started, edit the page.tsx file.</h1>
|
|
||||||
<p>
|
|
||||||
Looking for a starting point or more instructions? Head over to{" "}
|
|
||||||
<a
|
|
||||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
Templates
|
|
||||||
</a>{" "}
|
|
||||||
or the{" "}
|
|
||||||
<a
|
|
||||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
Learning
|
|
||||||
</a>{" "}
|
|
||||||
center.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className={styles.ctas}>
|
|
||||||
<a
|
|
||||||
className={styles.primary}
|
|
||||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
className={styles.logo}
|
|
||||||
src="/vercel.svg"
|
|
||||||
alt="Vercel logomark"
|
|
||||||
width={16}
|
|
||||||
height={16}
|
|
||||||
/>
|
|
||||||
Deploy Now
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
className={styles.secondary}
|
|
||||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
Documentation
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
21
src/components/theme-toggle.tsx
Normal file
21
src/components/theme-toggle.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useTheme } from 'next-themes';
|
||||||
|
import { Moon, Sun } from 'lucide-react';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
|
||||||
|
export function ThemeToggle() {
|
||||||
|
const { theme, setTheme } = useTheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
|
||||||
|
>
|
||||||
|
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
||||||
|
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
||||||
|
<span className="sr-only">切换主题</span>
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user