diff --git a/app/(dashboard)/dashboard/shop/income/page.tsx b/app/(dashboard)/dashboard/shop/income/page.tsx index 5cd4a28..0dfda9e 100644 --- a/app/(dashboard)/dashboard/shop/income/page.tsx +++ b/app/(dashboard)/dashboard/shop/income/page.tsx @@ -10,30 +10,34 @@ import { TableHeader, TableRow, } from "@/components/ui/table" -import { requestWithAuth } from "@/lib/api" +import { getShopIncomeStats } from "@/lib/api" +import type { ShopIncomeStats } from "@/lib/api/shops" import { listWalletTransactions } from "@/lib/api/transactions" -import { isActiveOrder, isCompletedOrder } from "@/lib/domain/order-filters" -import { resolveOwnerShop } from "@/lib/domain/resolve-current-shop" import { toApiError } from "@/lib/errors" +import { useMyShop } from "@/lib/hooks/use-my-shop" import type { WalletTransaction } from "@/lib/types" -import { useAuthStore } from "@/store/auth" -import { useOrderStore } from "@/store/orders" -import { useShopStore } from "@/store/shops" import { ArrowDownLeft, ArrowUpRight, CreditCard, DollarSign } from "lucide-react" import { useEffect, useState } from "react" +const emptyStats: ShopIncomeStats = { + monthlyIncome: "0", + pendingSettlement: "0", + totalWithdrawn: "0", + totalOrders: 0, + completedOrders: 0, +} + export default function ShopIncomePage() { - const userId = useAuthStore((state) => state.user?.id) - const shops = useShopStore((state) => state.shops) - const orders = useOrderStore((state) => state.orders) - const shop = resolveOwnerShop(userId, shops) + const { shop, loading, error } = useMyShop() const [transactions, setTransactions] = useState([]) + const [stats, setStats] = useState(emptyStats) const [isLoading, setIsLoading] = useState(false) const [loadError, setLoadError] = useState(null) useEffect(() => { if (!shop) return + const shopId = shop.id let cancelled = false @@ -41,14 +45,13 @@ export default function ShopIncomePage() { setIsLoading(true) setLoadError(null) try { - const res = await requestWithAuth(() => listWalletTransactions({ offset: 0, limit: 1000 })) + const [nextStats, nextTransactions] = await Promise.all([ + getShopIncomeStats(shopId), + listWalletTransactions({ offset: 0, limit: 1000 }), + ]) if (cancelled) return - if (!res) { - setLoadError("请先登录") - setTransactions([]) - return - } - setTransactions(res) + setStats(nextStats) + setTransactions(nextTransactions) } catch (error) { if (cancelled) return setLoadError(toApiError(error).msg) @@ -63,34 +66,21 @@ export default function ShopIncomePage() { } }, [shop]) + if (loading) { + return
加载中...
+ } + + if (error) { + return
{error}
+ } + if (!shop) { return
当前账号没有可管理的店铺
} - const shopOrders = orders.filter((order) => order.shopId === shop?.id) - const completedOrders = shopOrders.filter((o) => isCompletedOrder(o.status)) - const totalIncome = completedOrders.reduce((acc, order) => acc + order.totalPrice, 0) - - const currentMonth = new Date().getMonth() - const thisMonthIncome = completedOrders - .filter((o) => new Date(o.completedAt || "").getMonth() === currentMonth) - .reduce((acc, order) => acc + order.totalPrice, 0) - - const pendingSettlement = shopOrders - .filter( - (o) => - isActiveOrder(o.status) && o.status !== "pending_payment" && o.status !== "pending_accept", - ) - .reduce((acc, order) => acc + order.totalPrice, 0) - - const shopOrderIds = new Set(shopOrders.map((order) => order.id)) - const relatedTransactions = transactions.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]) - }) + const relatedTransactions = transactions.filter( + (transaction) => transaction.type === "income" || transaction.type === "withdrawal", + ) return (
@@ -99,29 +89,29 @@ export default function ShopIncomePage() {
- 总收入 + 本月收入 -
¥{totalIncome.toFixed(2)}
-
-
- - - 本月收入 - - - -
¥{thisMonthIncome.toFixed(2)}
+
¥{stats.monthlyIncome}
待结算 + + + +
¥{stats.pendingSettlement}
+
+
+ + + 累计提现 -
¥{pendingSettlement.toFixed(2)}
+
¥{stats.totalWithdrawn}
diff --git a/app/(dashboard)/dashboard/shop/orders/page.tsx b/app/(dashboard)/dashboard/shop/orders/page.tsx index 077373f..457c499 100644 --- a/app/(dashboard)/dashboard/shop/orders/page.tsx +++ b/app/(dashboard)/dashboard/shop/orders/page.tsx @@ -11,27 +11,62 @@ import { TableHeader, TableRow, } from "@/components/ui/table" +import { listOrders } from "@/lib/api" import { statusLabels } from "@/lib/constants" import { isActiveOrder, isCompletedOrder, isDisputedOrder } from "@/lib/domain/order-filters" -import { resolveOwnerShop } from "@/lib/domain/resolve-current-shop" -import { useAuthStore } from "@/store/auth" -import { useOrderStore } from "@/store/orders" -import { useShopStore } from "@/store/shops" +import { toApiError } from "@/lib/errors" +import { useMyShop } from "@/lib/hooks/use-my-shop" +import { notifyInfo } from "@/lib/toast" import { AlertCircle, CheckCircle, Clock, ListOrdered } from "lucide-react" import Link from "next/link" +import { useEffect, useMemo, useState } from "react" export default function ShopOrdersPage() { - const userId = useAuthStore((state) => state.user?.id) - const shops = useShopStore((state) => state.shops) - const orders = useOrderStore((state) => state.orders) - const shop = resolveOwnerShop(userId, shops) + const { shop, loading, error } = useMyShop() + const [orders, setOrders] = useState>>([]) + const [ordersLoading, setOrdersLoading] = useState(true) + + useEffect(() => { + if (!shop) return + + let cancelled = false + + listOrders({ role: "owner" }) + .then((items) => { + if (cancelled) return + setOrders(items) + }) + .catch((error) => { + if (cancelled) return + notifyInfo(toApiError(error).msg) + }) + .finally(() => { + if (cancelled) return + setOrdersLoading(false) + }) + + return () => { + cancelled = true + } + }, [shop]) + + const shopOrders = useMemo( + () => (shop ? orders.filter((order) => order.shopId === shop.id) : []), + [orders, shop], + ) + + if (loading) { + return
加载中...
+ } + + if (error) { + return
{error}
+ } if (!shop) { return
当前账号没有可管理的店铺
} - const shopOrders = orders.filter((order) => order.shopId === shop?.id) - const totalOrders = shopOrders.length const activeOrders = shopOrders.filter((o) => isActiveOrder(o.status)).length const completedOrders = shopOrders.filter((o) => isCompletedOrder(o.status)).length @@ -100,23 +135,37 @@ export default function ShopOrdersPage() { - {shopOrders.map((order) => ( - - {order.service.title} - {order.consumerId} - {order.playerId} - - {statusLabels[order.status]} - - ¥{order.totalPrice} - {new Date(order.createdAt).toLocaleDateString()} - - + {ordersLoading ? ( + + + 加载中... - ))} + ) : shopOrders.length === 0 ? ( + + + 暂无订单 + + + ) : ( + shopOrders.map((order) => ( + + {order.service.title} + {order.consumerId} + {order.playerId} + + {statusLabels[order.status]} + + ¥{order.totalPrice} + {new Date(order.createdAt).toLocaleDateString()} + + + + + )) + )}