From 5f2504392351f00b0caeee5c248b858ef1928a0b Mon Sep 17 00:00:00 2001 From: zetaloop Date: Sun, 22 Feb 2026 06:43:24 +0800 Subject: [PATCH] fix: sync notification and shop dashboard state --- app/(account)/notifications/page.tsx | 20 +-- .../dashboard/shop/income/page.tsx | 27 +++- .../dashboard/shop/orders/page.tsx | 22 ++- app/(main)/community/page.tsx | 134 +++++++++++------- components/header.tsx | 7 +- store/notifications.ts | 16 +++ 6 files changed, 152 insertions(+), 74 deletions(-) create mode 100644 store/notifications.ts diff --git a/app/(account)/notifications/page.tsx b/app/(account)/notifications/page.tsx index 0cc410e..51e55ef 100644 --- a/app/(account)/notifications/page.tsx +++ b/app/(account)/notifications/page.tsx @@ -1,11 +1,13 @@ +"use client" + 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" import type { Notification } from "@/lib/types" +import { useNotificationStore } from "@/store/notifications" const typeIcons: Record = { order: ShoppingBag, @@ -46,10 +48,12 @@ function NotificationItem({ notification }: { notification: Notification }) { } 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") + const notifications = useNotificationStore((state) => state.notifications) + const markAllAsRead = useNotificationStore((state) => state.markAllAsRead) + const unreadCount = notifications.filter((notification) => !notification.read).length + const orderNotifs = notifications.filter((notification) => notification.type === "order") + const communityNotifs = notifications.filter((notification) => notification.type === "community") + const systemNotifs = notifications.filter((notification) => notification.type === "system") return (
@@ -58,7 +62,7 @@ export default function NotificationsPage() {

通知中心

{unreadCount > 0 && {unreadCount} 条未读}
- @@ -73,8 +77,8 @@ export default function NotificationsPage() { - {mockNotifications.map((n) => ( - + {notifications.map((notification) => ( + ))} diff --git a/app/(dashboard)/dashboard/shop/income/page.tsx b/app/(dashboard)/dashboard/shop/income/page.tsx index 783d910..c40893a 100644 --- a/app/(dashboard)/dashboard/shop/income/page.tsx +++ b/app/(dashboard)/dashboard/shop/income/page.tsx @@ -1,3 +1,5 @@ +"use client" + import { ArrowDownLeft, ArrowUpRight, CreditCard, DollarSign } from "lucide-react" import { Badge } from "@/components/ui/badge" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" @@ -9,10 +11,18 @@ import { TableHeader, TableRow, } from "@/components/ui/table" -import { mockOrders, mockTransactions } from "@/lib/mock" +import { mockTransactions } from "@/lib/mock" +import { useAuthStore } from "@/store/auth" +import { useOrderStore } from "@/store/orders" +import { useShopStore } from "@/store/shops" export default function ShopIncomePage() { - const completedOrders = mockOrders.filter((o) => o.status === "completed") + const userId = useAuthStore((state) => state.user?.id) + const shops = useShopStore((state) => state.shops) + const orders = useOrderStore((state) => state.orders) + const shop = shops.find((item) => item.owner.id === userId) ?? shops[0] + const shopOrders = orders.filter((order) => order.shopId === shop?.id) + const completedOrders = shopOrders.filter((o) => o.status === "completed") const totalIncome = completedOrders.reduce((acc, order) => acc + order.totalPrice, 0) const currentMonth = new Date().getMonth() @@ -20,10 +30,19 @@ export default function ShopIncomePage() { .filter((o) => new Date(o.completedAt || "").getMonth() === currentMonth) .reduce((acc, order) => acc + order.totalPrice, 0) - const pendingSettlement = mockOrders + const pendingSettlement = shopOrders .filter((o) => ["in_progress", "pending_close", "pending_review"].includes(o.status)) .reduce((acc, order) => acc + order.totalPrice, 0) + const shopOrderIds = new Set(shopOrders.map((order) => order.id)) + const relatedTransactions = mockTransactions.filter((transaction) => { + if (transaction.type === "withdrawal") return true + if (transaction.type !== "income") return false + const match = transaction.description.match(/ord\d+/) + if (!match) return false + return shopOrderIds.has(match[0]) + }) + return (

收入统计

@@ -73,7 +92,7 @@ export default function ShopIncomePage() { - {mockTransactions.map((transaction) => ( + {relatedTransactions.map((transaction) => (
diff --git a/app/(dashboard)/dashboard/shop/orders/page.tsx b/app/(dashboard)/dashboard/shop/orders/page.tsx index bde0bb0..f24710e 100644 --- a/app/(dashboard)/dashboard/shop/orders/page.tsx +++ b/app/(dashboard)/dashboard/shop/orders/page.tsx @@ -1,3 +1,5 @@ +"use client" + import { AlertCircle, CheckCircle, Clock, ListOrdered } from "lucide-react" import Link from "next/link" import { Badge } from "@/components/ui/badge" @@ -12,11 +14,19 @@ import { TableRow, } from "@/components/ui/table" import { statusLabels } from "@/lib/constants" -import { mockOrders } from "@/lib/mock" +import { useAuthStore } from "@/store/auth" +import { useOrderStore } from "@/store/orders" +import { useShopStore } from "@/store/shops" export default function ShopOrdersPage() { - const totalOrders = mockOrders.length - const activeOrders = mockOrders.filter((o) => + const userId = useAuthStore((state) => state.user?.id) + const shops = useShopStore((state) => state.shops) + const orders = useOrderStore((state) => state.orders) + const shop = shops.find((item) => item.owner.id === userId) ?? shops[0] + const shopOrders = orders.filter((order) => order.shopId === shop?.id) + + const totalOrders = shopOrders.length + const activeOrders = shopOrders.filter((o) => [ "pending_payment", "pending_accept", @@ -25,8 +35,8 @@ export default function ShopOrdersPage() { "pending_review", ].includes(o.status), ).length - const completedOrders = mockOrders.filter((o) => o.status === "completed").length - const disputedOrders = mockOrders.filter((o) => o.status === "disputed").length + const completedOrders = shopOrders.filter((o) => o.status === "completed").length + const disputedOrders = shopOrders.filter((o) => o.status === "disputed").length return (
@@ -91,7 +101,7 @@ export default function ShopOrdersPage() { - {mockOrders.map((order) => ( + {shopOrders.map((order) => ( {order.service.title} {order.consumerName} diff --git a/app/(main)/community/page.tsx b/app/(main)/community/page.tsx index a43b116..0b4ed2a 100644 --- a/app/(main)/community/page.tsx +++ b/app/(main)/community/page.tsx @@ -8,7 +8,7 @@ import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Card, CardContent, CardFooter, CardHeader } from "@/components/ui/card" import { roleLabels } from "@/lib/constants" -import { mockGames, mockPosts } from "@/lib/mock" +import { mockGames, mockOrders, mockPlayers, mockPosts } from "@/lib/mock" export default function CommunityPage() { const [sortMode, setSortMode] = useState<"latest" | "hot">("latest") @@ -74,61 +74,87 @@ export default function CommunityPage() {
- {filteredPosts.map((post) => ( - - - -
- - - {post.author.nickname[0]} - -
-
- {post.author.nickname} - - {roleLabels[post.authorRole]} - - {post.pinned && } + {filteredPosts.map((post) => + (() => { + const linkedOrder = post.linkedOrderId + ? mockOrders.find((order) => order.id === post.linkedOrderId) + : null + const linkedPlayer = linkedOrder + ? mockPlayers.find((player) => player.id === linkedOrder.playerId) + : null + + return ( + + + +
+ + + {post.author.nickname[0]} + +
+
+ {post.author.nickname} + + {roleLabels[post.authorRole]} + + {post.pinned && } +
+ + {new Date(post.createdAt).toLocaleDateString("zh-CN")} + +
- - {new Date(post.createdAt).toLocaleDateString("zh-CN")} +
+ +

{post.title}

+

{post.content}

+ {post.tags.length > 0 && ( +
+ {post.tags.map((tag) => ( + + {tag} + + ))} +
+ )} + {post.linkedOrderId && ( +
+
+ + 关联订单秀单 +
+ {linkedOrder && ( +
+

+ {linkedOrder.service.gameName} · {linkedOrder.service.title} +

+

+ {linkedOrder.playerName} + {linkedPlayer ? ` · ${linkedPlayer.rating}` : ""} +

+
+ )} +
+ )} +
+ + + + {post.likeCount} -
-
- - -

{post.title}

-

{post.content}

- {post.tags.length > 0 && ( -
- {post.tags.map((tag) => ( - - {tag} - - ))} -
- )} - {post.linkedOrderId && ( -
- - 关联订单秀单 -
- )} -
- - - - {post.likeCount} - - - - {post.commentCount} - - - - - ))} + + + {post.commentCount} + + + + + ) + })(), + )}
) diff --git a/components/header.tsx b/components/header.tsx index 6ab9a8c..c962781 100644 --- a/components/header.tsx +++ b/components/header.tsx @@ -29,10 +29,11 @@ import { } from "@/components/ui/dropdown-menu" import { Input } from "@/components/ui/input" import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from "@/components/ui/sheet" -import { currentUser, mockNotifications, mockShops } from "@/lib/mock" +import { currentUser, mockShops } from "@/lib/mock" import type { UserRole } from "@/lib/types" import { cn } from "@/lib/utils" import { useAuthStore } from "@/store/auth" +import { useNotificationStore } from "@/store/notifications" const roleLabels: Record = { consumer: "消费者", @@ -72,7 +73,9 @@ export function Header() { setMobileOpen(false) } - const unreadCount = mockNotifications.filter((n) => !n.read).length + const unreadCount = useNotificationStore( + (state) => state.notifications.filter((notification) => !notification.read).length, + ) const handleSearch = (e: React.FormEvent) => { e.preventDefault() diff --git a/store/notifications.ts b/store/notifications.ts new file mode 100644 index 0000000..20bd2fd --- /dev/null +++ b/store/notifications.ts @@ -0,0 +1,16 @@ +import { create } from "zustand" +import { mockNotifications } from "@/lib/mock" +import type { Notification } from "@/lib/types" + +interface NotificationState { + notifications: Notification[] + markAllAsRead: () => void +} + +export const useNotificationStore = create((set) => ({ + notifications: mockNotifications, + markAllAsRead: () => + set((state) => ({ + notifications: state.notifications.map((notification) => ({ ...notification, read: true })), + })), +}))