diff --git a/app/(account)/wallet/page.tsx b/app/(account)/wallet/page.tsx index 3018b3a..f8e0eda 100644 --- a/app/(account)/wallet/page.tsx +++ b/app/(account)/wallet/page.tsx @@ -8,13 +8,15 @@ import { RefreshCw, Wallet, } from "lucide-react" +import { useState } from "react" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Input } from "@/components/ui/input" import { Separator } from "@/components/ui/separator" -import { mockTransactions, walletBalance } from "@/lib/mock" +import { notifySuccess } from "@/lib/toast" import { useAuthStore } from "@/store/auth" +import { useWalletStore } from "@/store/wallet" const typeLabels: Record = { topup: "充值", @@ -35,18 +37,42 @@ const typeIcons: Record = { export default function WalletPage() { const { currentRole } = useAuthStore() const isConsumer = currentRole === "consumer" + const balance = useWalletStore((state) => state.balance) + const transactions = useWalletStore((state) => state.transactions) + const topUp = useWalletStore((state) => state.topUp) + const withdraw = useWalletStore((state) => state.withdraw) + const [selectedAmount, setSelectedAmount] = useState(null) + const [customAmount, setCustomAmount] = useState("") + const [lastRefreshedAt, setLastRefreshedAt] = useState(null) - const filteredTransactions = mockTransactions.filter((tx) => { + const filteredTransactions = transactions.filter((tx) => { if (isConsumer) { return ["topup", "payment", "refund"].includes(tx.type) } return ["income", "withdrawal"].includes(tx.type) }) - const incomeBalance = mockTransactions - .filter((tx) => tx.type === "income") + const incomeBalance = transactions + .filter((tx) => ["income", "withdrawal"].includes(tx.type)) .reduce((acc, tx) => acc + tx.amount, 0) + const handleTopUp = (rawAmount?: number) => { + const amount = rawAmount ?? Number(customAmount) + if (!Number.isFinite(amount) || amount <= 0) return + topUp(amount) + notifySuccess(`充值成功 +¥${amount}`) + setCustomAmount("") + setSelectedAmount(null) + } + + const handleWithdraw = () => { + const amount = Number(customAmount || "0") || Number(incomeBalance.toFixed(2)) + if (!Number.isFinite(amount) || amount <= 0) return + withdraw(amount) + notifySuccess(`提现申请已提交 ¥${amount}`) + setCustomAmount("") + } + return (

钱包

@@ -59,19 +85,19 @@ export default function WalletPage() { {isConsumer ? "账户余额" : "收入余额"}

- ¥{isConsumer ? walletBalance.toFixed(2) : incomeBalance.toFixed(2)} + ¥{isConsumer ? balance.toFixed(2) : incomeBalance.toFixed(2)}

{isConsumer ? ( - ) : ( - @@ -88,15 +114,31 @@ export default function WalletPage() {
{[50, 100, 200, 500, 1000, 2000].map((amount) => ( - ))}
- - + { + setCustomAmount(event.target.value) + setSelectedAmount(null) + }} + /> +
@@ -127,12 +169,22 @@ export default function WalletPage() { 交易记录 - + {lastRefreshedAt && ( +

最近刷新:{lastRefreshedAt}

+ )} {filteredTransactions.length > 0 ? ( filteredTransactions.map((tx) => { const Icon = typeIcons[tx.type] diff --git a/app/(main)/post/new/page.tsx b/app/(main)/post/new/page.tsx index 1132ce8..468f59f 100644 --- a/app/(main)/post/new/page.tsx +++ b/app/(main)/post/new/page.tsx @@ -4,7 +4,7 @@ import { standardSchemaResolver } from "@hookform/resolvers/standard-schema" import { ArrowLeft, ImagePlus, X } from "lucide-react" import Link from "next/link" import { useRouter } from "next/navigation" -import { useState } from "react" +import { useEffect, useState } from "react" import { useForm } from "react-hook-form" import { z } from "zod" import { Badge } from "@/components/ui/badge" @@ -20,8 +20,10 @@ import { SelectValue, } from "@/components/ui/select" import { Textarea } from "@/components/ui/textarea" -import { mockOrders, mockPosts } from "@/lib/mock" +import { mockPosts } from "@/lib/mock" import { useRequireAuth } from "@/lib/use-require-auth" +import { useAuthStore } from "@/store/auth" +import { useOrderStore } from "@/store/orders" const postSchema = z.object({ title: z.string().min(2, "标题至少2个字符").max(50, "标题最多50个字符"), @@ -33,6 +35,9 @@ const tagOptions = ["英雄联盟", "王者荣耀", "CS2", "原神", "上分", " export default function NewPostPage() { const router = useRouter() const { isAuthenticated, requireAuth } = useRequireAuth() + const currentRole = useAuthStore((state) => state.currentRole) + const userId = useAuthStore((state) => state.user?.id) + const orders = useOrderStore((state) => state.orders) const [postType, setPostType] = useState("normal") const [selectedTags, setSelectedTags] = useState([]) const [imageCount, setImageCount] = useState(0) @@ -53,6 +58,16 @@ export default function NewPostPage() { ) } + useEffect(() => { + if (currentRole !== "consumer" && postType === "show_order") { + setPostType("normal") + } + }, [currentRole, postType]) + + const availableOrders = orders.filter( + (order) => order.status === "completed" && order.consumerId === userId, + ) + const onSubmit = async () => { if (!isAuthenticated) { requireAuth(() => undefined) @@ -87,7 +102,7 @@ export default function NewPostPage() { 普通帖 - 秀单帖 + {currentRole === "consumer" && 秀单帖} 引用帖 @@ -101,13 +116,11 @@ export default function NewPostPage() { - {mockOrders - .filter((order) => order.status === "completed") - .map((order) => ( - - {order.service.title} · {order.playerName} - - ))} + {availableOrders.map((order) => ( + + {order.service.title} · {order.playerName} + + ))}
diff --git a/app/(order)/order/new/page.tsx b/app/(order)/order/new/page.tsx index a079637..d5b8855 100644 --- a/app/(order)/order/new/page.tsx +++ b/app/(order)/order/new/page.tsx @@ -11,12 +11,13 @@ 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 { mockPlayers, mockServices, walletBalance } from "@/lib/mock" +import { mockPlayers, mockServices } from "@/lib/mock" import { notifySuccess } from "@/lib/toast" import { useRequireAuth } from "@/lib/use-require-auth" import { useAuthStore } from "@/store/auth" import { useChatStore } from "@/store/chat" import { useOrderStore } from "@/store/orders" +import { useWalletStore } from "@/store/wallet" export default function NewOrderPage() { const router = useRouter() @@ -24,6 +25,8 @@ export default function NewOrderPage() { const { requireAuth } = useRequireAuth() const createOrder = useOrderStore((state) => state.createOrder) const ensureOrderSession = useChatStore((state) => state.ensureOrderSession) + const balance = useWalletStore((state) => state.balance) + const deductBalance = useWalletStore((state) => state.deductBalance) const serviceId = searchParams.get("serviceId") const service = mockServices.find((s) => s.id === serviceId) @@ -163,9 +166,9 @@ export default function NewOrderPage() {
- 钱包余额: ¥{walletBalance} - {walletBalance < totalPrice && (余额不足)} - {walletBalance < totalPrice && ( + 钱包余额: ¥{balance.toFixed(2)} + {balance < totalPrice && (余额不足)} + {balance < totalPrice && ( @@ -181,7 +184,7 @@ export default function NewOrderPage() {