feat: add role-based wallet view for consumer vs player/owner

This commit is contained in:
zetaloop
2026-02-20 22:46:28 +08:00
parent 977d19ed5c
commit 86ece33c00
+104 -52
View File
@@ -1,3 +1,5 @@
"use client"
import {
ArrowDownLeft,
ArrowUpRight,
@@ -12,6 +14,7 @@ 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-data"
import { useAuthStore } from "@/store/auth"
const typeLabels: Record<string, string> = {
topup: "充值",
@@ -30,6 +33,20 @@ const typeIcons: Record<string, typeof ArrowUpRight> = {
}
export default function WalletPage() {
const { currentRole } = useAuthStore()
const isConsumer = currentRole === "consumer"
const filteredTransactions = mockTransactions.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")
.reduce((acc, tx) => acc + tx.amount, 0)
return (
<div className="max-w-2xl space-y-6">
<h1 className="text-2xl font-bold"></h1>
@@ -38,43 +55,74 @@ export default function WalletPage() {
<CardContent className="pt-6">
<div className="flex items-center justify-between">
<div>
<p className="text-sm text-muted-foreground"></p>
<p className="text-3xl font-bold mt-1">¥{walletBalance.toFixed(2)}</p>
<p className="text-sm text-muted-foreground">
{isConsumer ? "账户余额" : "收入余额"}
</p>
<p className="text-3xl font-bold mt-1">
¥{isConsumer ? walletBalance.toFixed(2) : incomeBalance.toFixed(2)}
</p>
</div>
<Wallet className="h-10 w-10 text-muted-foreground" />
</div>
<div className="flex gap-2 mt-4">
<Button>
<DollarSign className="mr-1 h-4 w-4" />
</Button>
<Button variant="outline">
<CreditCard className="mr-1 h-4 w-4" />
</Button>
{isConsumer ? (
<Button>
<DollarSign className="mr-1 h-4 w-4" />
</Button>
) : (
<Button variant="outline">
<CreditCard className="mr-1 h-4 w-4" />
</Button>
)}
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-base"></CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-3 gap-2">
{[50, 100, 200, 500, 1000, 2000].map((amount) => (
<Button key={`amount-${amount}`} variant="outline" className="h-12">
¥{amount}
</Button>
))}
</div>
<Separator />
<div className="flex gap-2">
<Input placeholder="自定义金额" type="number" />
<Button></Button>
</div>
</CardContent>
</Card>
{isConsumer ? (
<Card>
<CardHeader>
<CardTitle className="text-base"></CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-3 gap-2">
{[50, 100, 200, 500, 1000, 2000].map((amount) => (
<Button key={`amount-${amount}`} variant="outline" className="h-12">
¥{amount}
</Button>
))}
</div>
<Separator />
<div className="flex gap-2">
<Input placeholder="自定义金额" type="number" />
<Button></Button>
</div>
</CardContent>
</Card>
) : (
<Card>
<CardHeader>
<CardTitle className="text-base"></CardTitle>
</CardHeader>
<CardContent>
<div className="grid grid-cols-3 gap-4 text-center">
<div>
<p className="text-xs text-muted-foreground"></p>
<p className="text-lg font-bold">¥1,280.00</p>
</div>
<div>
<p className="text-xs text-muted-foreground"></p>
<p className="text-lg font-bold">¥320.00</p>
</div>
<div>
<p className="text-xs text-muted-foreground"></p>
<p className="text-lg font-bold">¥5,400.00</p>
</div>
</div>
</CardContent>
</Card>
)}
<Card>
<CardHeader className="flex flex-row items-center justify-between">
@@ -85,33 +133,37 @@ export default function WalletPage() {
</Button>
</CardHeader>
<CardContent className="space-y-3">
{mockTransactions.map((tx) => {
const Icon = typeIcons[tx.type]
const isIncome = tx.amount > 0
return (
<div key={tx.id} className="flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="h-8 w-8 rounded-full bg-muted flex items-center justify-center">
<Icon className="h-4 w-4" />
{filteredTransactions.length > 0 ? (
filteredTransactions.map((tx) => {
const Icon = typeIcons[tx.type]
const isIncome = tx.amount > 0
return (
<div key={tx.id} className="flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="h-8 w-8 rounded-full bg-muted flex items-center justify-center">
<Icon className="h-4 w-4" />
</div>
<div>
<p className="text-sm font-medium">{tx.description}</p>
<p className="text-xs text-muted-foreground">
{new Date(tx.createdAt).toLocaleString("zh-CN")}
</p>
</div>
</div>
<div>
<p className="text-sm font-medium">{tx.description}</p>
<p className="text-xs text-muted-foreground">
{new Date(tx.createdAt).toLocaleString("zh-CN")}
<div className="text-right">
<p className={`text-sm font-medium ${isIncome ? "text-green-600" : ""}`}>
{isIncome ? "+" : ""}¥{Math.abs(tx.amount).toFixed(2)}
</p>
<Badge variant="outline" className="text-[10px]">
{typeLabels[tx.type]}
</Badge>
</div>
</div>
<div className="text-right">
<p className={`text-sm font-medium ${isIncome ? "text-green-600" : ""}`}>
{isIncome ? "+" : ""}¥{Math.abs(tx.amount).toFixed(2)}
</p>
<Badge variant="outline" className="text-[10px]">
{typeLabels[tx.type]}
</Badge>
</div>
</div>
)
})}
)
})
) : (
<div className="text-center py-8 text-muted-foreground text-sm"></div>
)}
</CardContent>
</Card>
</div>