feat: settings, wallet, notifications, and identity verification pages

This commit is contained in:
zetaloop
2026-02-20 15:34:15 +08:00
parent 6523556d8b
commit 5b21793ede
4 changed files with 464 additions and 9 deletions
+114 -3
View File
@@ -1,8 +1,119 @@
import { Bell, CheckCheck, MessageSquare, ShoppingBag } from "lucide-react"
import Link from "next/link"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Card, CardContent } from "@/components/ui/card"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { mockNotifications } from "@/lib/mock-data"
import type { Notification } from "@/lib/types"
const typeIcons: Record<Notification["type"], typeof Bell> = {
order: ShoppingBag,
community: MessageSquare,
system: Bell,
}
const typeLabels: Record<Notification["type"], string> = {
order: "订单",
community: "社区",
system: "系统",
}
function NotificationItem({ notification }: { notification: Notification }) {
const Icon = typeIcons[notification.type]
const content = (
<div className="flex items-start gap-3 rounded-md border p-3 hover:bg-muted/50 transition-colors">
<div className="h-8 w-8 rounded-full bg-muted flex items-center justify-center shrink-0 mt-0.5">
<Icon className="h-4 w-4" />
</div>
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2">
<span className="text-sm font-medium">{notification.title}</span>
{!notification.read && <span className="h-2 w-2 rounded-full bg-primary shrink-0" />}
</div>
<p className="text-sm text-muted-foreground mt-0.5">{notification.content}</p>
<p className="text-xs text-muted-foreground mt-1">
{new Date(notification.createdAt).toLocaleString("zh-CN")}
</p>
</div>
<Badge variant="outline" className="text-[10px] shrink-0">
{typeLabels[notification.type]}
</Badge>
</div>
)
return notification.link ? <Link href={notification.link}>{content}</Link> : content
}
export default function NotificationsPage() {
const unreadCount = mockNotifications.filter((n) => !n.read).length
const orderNotifs = mockNotifications.filter((n) => n.type === "order")
const communityNotifs = mockNotifications.filter((n) => n.type === "community")
const systemNotifs = mockNotifications.filter((n) => n.type === "system")
return (
<div>
<h1 className="text-2xl font-bold"></h1>
<p className="mt-2 text-muted-foreground"></p>
<div className="max-w-2xl space-y-6">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<h1 className="text-2xl font-bold"></h1>
{unreadCount > 0 && <Badge>{unreadCount} </Badge>}
</div>
<Button variant="outline" size="sm">
<CheckCheck className="mr-1 h-4 w-4" />
</Button>
</div>
<Tabs defaultValue="all">
<TabsList>
<TabsTrigger value="all"></TabsTrigger>
<TabsTrigger value="order"></TabsTrigger>
<TabsTrigger value="community"></TabsTrigger>
<TabsTrigger value="system"></TabsTrigger>
</TabsList>
<TabsContent value="all" className="space-y-2 mt-4">
{mockNotifications.map((n) => (
<NotificationItem key={n.id} notification={n} />
))}
</TabsContent>
<TabsContent value="order" className="space-y-2 mt-4">
{orderNotifs.length === 0 ? (
<Card>
<CardContent className="py-8 text-center text-sm text-muted-foreground">
</CardContent>
</Card>
) : (
orderNotifs.map((n) => <NotificationItem key={n.id} notification={n} />)
)}
</TabsContent>
<TabsContent value="community" className="space-y-2 mt-4">
{communityNotifs.length === 0 ? (
<Card>
<CardContent className="py-8 text-center text-sm text-muted-foreground">
</CardContent>
</Card>
) : (
communityNotifs.map((n) => <NotificationItem key={n.id} notification={n} />)
)}
</TabsContent>
<TabsContent value="system" className="space-y-2 mt-4">
{systemNotifs.length === 0 ? (
<Card>
<CardContent className="py-8 text-center text-sm text-muted-foreground">
</CardContent>
</Card>
) : (
systemNotifs.map((n) => <NotificationItem key={n.id} notification={n} />)
)}
</TabsContent>
</Tabs>
</div>
)
}