feat: route structure, providers, layouts, and placeholder pages
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
export default function AccountLayout({ children }: { children: React.ReactNode }) {
|
||||||
|
return (
|
||||||
|
<div className="flex min-h-screen">
|
||||||
|
<aside className="w-64 border-r bg-muted/30 p-4">
|
||||||
|
<h2 className="mb-4 text-lg font-semibold">账号设置</h2>
|
||||||
|
<nav className="space-y-2 text-sm text-muted-foreground">
|
||||||
|
<div>个人资料</div>
|
||||||
|
<div>钱包</div>
|
||||||
|
<div>通知</div>
|
||||||
|
<div>身份认证</div>
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
<main className="flex-1 p-6">{children}</main>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function NotificationsPage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 className="text-2xl font-bold">通知中心</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">订单通知、社区通知、系统通知</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function SettingsPage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 className="text-2xl font-bold">个人设置</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">资料编辑、身份切换、联系方式、通知偏好</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function VerifyPage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 className="text-2xl font-bold">身份认证</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">申请打手或店主身份认证</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function WalletPage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 className="text-2xl font-bold">钱包</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">充值、余额、支付记录、收入明细、提现</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
export default function AuthLayout({ children }: { children: React.ReactNode }) {
|
||||||
|
return (
|
||||||
|
<div className="flex min-h-screen items-center justify-center bg-muted/30">
|
||||||
|
<div className="w-full max-w-md rounded-lg border bg-background p-6 shadow-sm">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function LoginPage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 className="text-2xl font-bold">登录</h1>
|
||||||
|
<p className="mt-2 text-sm text-muted-foreground">登录你的聚玩账号</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function RegisterPage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 className="text-2xl font-bold">注册</h1>
|
||||||
|
<p className="mt-2 text-sm text-muted-foreground">创建你的聚玩账号</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function DashboardPage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 className="text-2xl font-bold">管理后台</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">根据当前身份显示对应的管理面板</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function NewServicePage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 className="text-2xl font-bold">发布服务</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">创建或编辑陪玩服务</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function ServicesPage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 className="text-2xl font-bold">服务管理</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">管理已发布的陪玩服务</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function EmployeesPage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 className="text-2xl font-bold">员工管理</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">邀请、移除打手,设置抽成</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function ShopManagementPage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 className="text-2xl font-bold">店铺管理</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">店铺信息、活动、订单总览、收入统计</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function ShopTemplatesPage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 className="text-2xl font-bold">店铺模板</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">编辑店铺主页模板组件</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
|
||||||
|
return (
|
||||||
|
<div className="flex min-h-screen">
|
||||||
|
<aside className="w-64 border-r bg-muted/30 p-4">
|
||||||
|
<h2 className="mb-4 text-lg font-semibold">管理后台</h2>
|
||||||
|
<nav className="space-y-2 text-sm text-muted-foreground">
|
||||||
|
<div>服务管理</div>
|
||||||
|
<div>店铺管理</div>
|
||||||
|
<div>员工管理</div>
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
<main className="flex-1 p-6">{children}</main>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function CommunityPage() {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto py-8 px-4">
|
||||||
|
<h1 className="text-2xl font-bold">社区</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">浏览帖子、秀单、讨论</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
export default function MainLayout({ children }: { children: React.ReactNode }) {
|
||||||
|
return (
|
||||||
|
<div className="flex min-h-screen flex-col">
|
||||||
|
<header className="border-b">
|
||||||
|
<nav className="container mx-auto flex h-16 items-center justify-between px-4">
|
||||||
|
<span className="text-xl font-bold">聚玩</span>
|
||||||
|
<div className="flex items-center gap-4">
|
||||||
|
<span className="text-sm text-muted-foreground">导航占位</span>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<main className="flex-1">{children}</main>
|
||||||
|
<footer className="border-t py-6">
|
||||||
|
<div className="container mx-auto px-4 text-center text-sm text-muted-foreground">
|
||||||
|
© 聚玩 - 游戏陪玩服务平台
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
export default function HomePage() {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto py-8 px-4">
|
||||||
|
<h1 className="text-3xl font-bold">聚玩</h1>
|
||||||
|
<p className="mt-2 text-lg text-muted-foreground">游戏陪玩服务平台</p>
|
||||||
|
<div className="mt-8 grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||||
|
<div className="rounded-lg border p-6">
|
||||||
|
<h2 className="font-semibold">游戏分类</h2>
|
||||||
|
<p className="mt-1 text-sm text-muted-foreground">按游戏浏览陪玩服务</p>
|
||||||
|
</div>
|
||||||
|
<div className="rounded-lg border p-6">
|
||||||
|
<h2 className="font-semibold">推荐打手</h2>
|
||||||
|
<p className="mt-1 text-sm text-muted-foreground">热门打手推荐</p>
|
||||||
|
</div>
|
||||||
|
<div className="rounded-lg border p-6">
|
||||||
|
<h2 className="font-semibold">热门店铺</h2>
|
||||||
|
<p className="mt-1 text-sm text-muted-foreground">优质店铺推荐</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function PlayerDetailPage({ params: _params }: { params: Promise<{ id: string }> }) {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto py-8 px-4">
|
||||||
|
<h1 className="text-2xl font-bold">打手详情</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">评分、服务列表、评价、所属店铺</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function PostDetailPage({ params: _params }: { params: Promise<{ id: string }> }) {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto py-8 px-4">
|
||||||
|
<h1 className="text-2xl font-bold">帖子详情</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">帖子内容、评论区</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function NewPostPage() {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto py-8 px-4">
|
||||||
|
<h1 className="text-2xl font-bold">发帖</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">发布普通帖、秀单帖或引用帖</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function SearchPage() {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto py-8 px-4">
|
||||||
|
<h1 className="text-2xl font-bold">搜索</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">搜索打手、店铺和服务</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function ShopDetailPage({ params: _params }: { params: Promise<{ id: string }> }) {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto py-8 px-4">
|
||||||
|
<h1 className="text-2xl font-bold">店铺详情</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">店铺主页、服务列表、打手列表</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function ChatDetailPage({ params: _params }: { params: Promise<{ id: string }> }) {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto py-8 px-4">
|
||||||
|
<h1 className="text-2xl font-bold">聊天</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">与打手沟通</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function ChatListPage() {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto py-8 px-4">
|
||||||
|
<h1 className="text-2xl font-bold">消息</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">咨询会话和订单会话</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function DisputePage({ params: _params }: { params: Promise<{ id: string }> }) {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto py-8 px-4">
|
||||||
|
<h1 className="text-2xl font-bold">争议仲裁</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">提交争议说明和证据</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export default function OrderLayout({ children }: { children: React.ReactNode }) {
|
||||||
|
return <div className="min-h-screen bg-muted/30">{children}</div>
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function OrderDetailPage({ params: _params }: { params: Promise<{ id: string }> }) {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto py-8 px-4">
|
||||||
|
<h1 className="text-2xl font-bold">订单详情</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">订单状态、聊天、评价、争议</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function OrderListPage() {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto py-8 px-4">
|
||||||
|
<h1 className="text-2xl font-bold">我的订单</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">查看和管理订单</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function ReviewPage({ params: _params }: { params: Promise<{ id: string }> }) {
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto py-8 px-4">
|
||||||
|
<h1 className="text-2xl font-bold">评价</h1>
|
||||||
|
<p className="mt-2 text-muted-foreground">对本次服务进行评价</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
+7
-4
@@ -1,5 +1,6 @@
|
|||||||
import type { Metadata } from "next"
|
import type { Metadata } from "next"
|
||||||
import { Geist, Geist_Mono } from "next/font/google"
|
import { Geist, Geist_Mono } from "next/font/google"
|
||||||
|
import { Providers } from "./providers"
|
||||||
import "./globals.css"
|
import "./globals.css"
|
||||||
|
|
||||||
const geistSans = Geist({
|
const geistSans = Geist({
|
||||||
@@ -13,8 +14,8 @@ const geistMono = Geist_Mono({
|
|||||||
})
|
})
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Create Next App",
|
title: "聚玩",
|
||||||
description: "Generated by create next app",
|
description: "游戏陪玩服务平台",
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
@@ -23,8 +24,10 @@ export default function RootLayout({
|
|||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="zh-CN">
|
||||||
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>{children}</body>
|
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
|
||||||
|
<Providers>{children}</Providers>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
import Image from "next/image"
|
|
||||||
|
|
||||||
export default function Home() {
|
|
||||||
return (
|
|
||||||
<div className="flex min-h-screen items-center justify-center bg-zinc-50 font-sans dark:bg-black">
|
|
||||||
<main className="flex min-h-screen w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
|
|
||||||
<Image
|
|
||||||
className="dark:invert"
|
|
||||||
src="/next.svg"
|
|
||||||
alt="Next.js logo"
|
|
||||||
width={100}
|
|
||||||
height={20}
|
|
||||||
priority
|
|
||||||
/>
|
|
||||||
<div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
|
|
||||||
<h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
|
|
||||||
To get started, edit the page.tsx file.
|
|
||||||
</h1>
|
|
||||||
<p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
|
|
||||||
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"
|
|
||||||
className="font-medium text-zinc-950 dark:text-zinc-50"
|
|
||||||
>
|
|
||||||
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"
|
|
||||||
className="font-medium text-zinc-950 dark:text-zinc-50"
|
|
||||||
>
|
|
||||||
Learning
|
|
||||||
</a>{" "}
|
|
||||||
center.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
|
|
||||||
<a
|
|
||||||
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
|
|
||||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
className="dark:invert"
|
|
||||||
src="/vercel.svg"
|
|
||||||
alt="Vercel logomark"
|
|
||||||
width={16}
|
|
||||||
height={16}
|
|
||||||
/>
|
|
||||||
Deploy Now
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
|
|
||||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
Documentation
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
|
||||||
|
import { useState } from "react"
|
||||||
|
|
||||||
|
export function Providers({ children }: { children: React.ReactNode }) {
|
||||||
|
const [queryClient] = useState(
|
||||||
|
() =>
|
||||||
|
new QueryClient({
|
||||||
|
defaultOptions: {
|
||||||
|
queries: {
|
||||||
|
staleTime: 60 * 1000,
|
||||||
|
refetchOnWindowFocus: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
||||||
|
}
|
||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
/// <reference types="next" />
|
/// <reference types="next" />
|
||||||
/// <reference types="next/image-types/global" />
|
/// <reference types="next/image-types/global" />
|
||||||
import "./.next/types/routes.d.ts"
|
import "./.next/types/routes.d.ts";
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
// NOTE: This file should not be edited
|
||||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { create } from "zustand"
|
||||||
|
|
||||||
|
export type UserRole = "consumer" | "player" | "owner"
|
||||||
|
|
||||||
|
interface AuthState {
|
||||||
|
isAuthenticated: boolean
|
||||||
|
currentRole: UserRole
|
||||||
|
switchRole: (role: UserRole) => void
|
||||||
|
login: () => void
|
||||||
|
logout: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useAuthStore = create<AuthState>((set) => ({
|
||||||
|
isAuthenticated: false,
|
||||||
|
currentRole: "consumer",
|
||||||
|
switchRole: (role) => set({ currentRole: role }),
|
||||||
|
login: () => set({ isAuthenticated: true }),
|
||||||
|
logout: () => set({ isAuthenticated: false, currentRole: "consumer" }),
|
||||||
|
}))
|
||||||
Reference in New Issue
Block a user