diff --git a/app/(account)/wallet/page.tsx b/app/(account)/wallet/page.tsx index 8ac288a..fb96530 100644 --- a/app/(account)/wallet/page.tsx +++ b/app/(account)/wallet/page.tsx @@ -6,7 +6,12 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Input } from "@/components/ui/input" import { Separator } from "@/components/ui/separator" import { requestWithAuth } from "@/lib/api" -import { getWalletBalance, listWalletTransactions } from "@/lib/api/transactions" +import { + getWalletBalance, + listWalletTransactions, + topUpWallet, + withdrawWallet, +} from "@/lib/api/transactions" import { toApiError } from "@/lib/errors" import { notifyInfo, notifySuccess } from "@/lib/toast" import type { WalletTransaction } from "@/lib/types" @@ -44,6 +49,7 @@ export default function WalletPage() { const [balance, setBalance] = useState(null) const [transactions, setTransactions] = useState([]) const [isLoading, setIsLoading] = useState(false) + const [isMutating, setIsMutating] = useState(false) const [loadError, setLoadError] = useState(null) const [selectedAmount, setSelectedAmount] = useState(null) @@ -59,6 +65,21 @@ export default function WalletPage() { }) }, [isConsumer, transactions]) + const incomeSummary = useMemo(() => { + const income = transactions + .filter((tx) => tx.type === "income") + .reduce((total, tx) => total + Number(tx.amount), 0) + const withdrawn = transactions + .filter((tx) => tx.type === "withdrawal") + .reduce((total, tx) => total + Number(tx.amount), 0) + + return { + income, + available: balance ?? 0, + withdrawn, + } + }, [balance, transactions]) + const loadWalletData = useCallback( async (options?: { showToast?: boolean; silent?: boolean }) => { if (!options?.silent) { @@ -122,17 +143,53 @@ export default function WalletPage() { } }, []) - const handleTopUp = (rawAmount?: number) => { + const handleTopUp = async (rawAmount?: number) => { const amount = rawAmount ?? Number(customAmount) - if (!Number.isFinite(amount) || amount <= 0) return - notifyInfo("充值暂未开放") - setCustomAmount("") - setSelectedAmount(null) + if (!Number.isFinite(amount) || amount <= 0) { + notifyInfo("请输入有效金额") + return + } + + setIsMutating(true) + try { + const res = await requestWithAuth(async () => { + await topUpWallet({ amount }) + await loadWalletData({ silent: true }) + return true + }) + if (!res) return + notifySuccess("充值成功") + setCustomAmount("") + setSelectedAmount(null) + } catch (error) { + notifyInfo(toApiError(error).msg) + } finally { + setIsMutating(false) + } } - const handleWithdraw = () => { - notifyInfo("提现暂未开放") - setCustomAmount("") + const handleWithdraw = async () => { + const amount = Number(customAmount) + if (!Number.isFinite(amount) || amount <= 0) { + notifyInfo("请输入有效金额") + return + } + + setIsMutating(true) + try { + const res = await requestWithAuth(async () => { + await withdrawWallet({ amount }) + await loadWalletData({ silent: true }) + return true + }) + if (!res) return + notifySuccess("提现成功") + setCustomAmount("") + } catch (error) { + notifyInfo(toApiError(error).msg) + } finally { + setIsMutating(false) + } } return ( @@ -159,12 +216,15 @@ export default function WalletPage() {
{isConsumer ? ( - ) : ( - @@ -205,7 +265,9 @@ export default function WalletPage() { setSelectedAmount(null) }} /> - +
@@ -217,18 +279,30 @@ export default function WalletPage() {
-

本月收入

-

¥1,280.00

+

累计收入

+

¥{incomeSummary.income.toFixed(2)}

-

待结算

-

¥320.00

+

可提现

+

¥{incomeSummary.available.toFixed(2)}

已提现

-

¥5,400.00

+

¥{incomeSummary.withdrawn.toFixed(2)}

+ +
+ setCustomAmount(event.target.value)} + /> + +
)} @@ -258,7 +332,7 @@ export default function WalletPage() { ) : filteredTransactions.length > 0 ? ( filteredTransactions.map((tx) => { const Icon = typeIcons[tx.type] - const isIncome = Number(tx.amount) > 0 + const isIncome = tx.type === "topup" || tx.type === "income" || tx.type === "refund" return (
diff --git a/app/(order)/order/new/page.tsx b/app/(order)/order/new/page.tsx index e5a6537..62800d3 100644 --- a/app/(order)/order/new/page.tsx +++ b/app/(order)/order/new/page.tsx @@ -7,12 +7,12 @@ import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Separator } from "@/components/ui/separator" import { Textarea } from "@/components/ui/textarea" -import { getPlayerById, getServiceById } from "@/lib/api" +import { getPlayerById, getServiceById, requestWithAuth } from "@/lib/api" import { createPaidOrder } from "@/lib/api/orders" -import { notifySuccess } from "@/lib/toast" +import { getWalletBalance } from "@/lib/api/transactions" +import { notifyInfo, notifySuccess } from "@/lib/toast" import type { Player, PlayerService } from "@/lib/types" import { useRequireAuth } from "@/lib/use-require-auth" -import { useWalletStore } from "@/store/wallet" import { ArrowLeft, CheckCircle, CreditCard, ShieldCheck } from "lucide-react" import Link from "next/link" import { useRouter, useSearchParams } from "next/navigation" @@ -22,11 +22,11 @@ export default function NewOrderPage() { const router = useRouter() const searchParams = useSearchParams() const { requireAuth } = useRequireAuth() - const balance = useWalletStore((state) => state.balance) const serviceId = searchParams.get("serviceId") const [service, setService] = useState(null) const [player, setPlayer] = useState(null) + const [balance, setBalance] = useState(null) const [loading, setLoading] = useState(true) useEffect(() => { @@ -72,6 +72,22 @@ export default function NewOrderPage() { } }, [serviceId]) + useEffect(() => { + let cancelled = false + + void requestWithAuth(() => getWalletBalance()) + .then((nextBalance) => { + if (!cancelled) setBalance(nextBalance ?? null) + }) + .catch(() => { + if (!cancelled) setBalance(null) + }) + + return () => { + cancelled = true + } + }, []) + const [quantity, setQuantity] = useState(1) const [note, setNote] = useState("") const [submitted, setSubmitted] = useState(false) @@ -213,9 +229,11 @@ export default function NewOrderPage() {
- 钱包余额: ¥{balance.toFixed(2)} - {balance < totalPrice && (余额不足)} - {balance < totalPrice && ( + 钱包余额: {balance === null ? "--" : `¥${balance.toFixed(2)}`} + {balance !== null && balance < totalPrice && ( + (余额不足) + )} + {balance !== null && balance < totalPrice && ( @@ -231,7 +249,7 @@ export default function NewOrderPage() {