Files
juwan-frontend/app/(account)/verify/page.tsx
T
2026-02-28 07:26:05 +08:00

238 lines
8.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client"
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 { Label } from "@/components/ui/label"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
import { Separator } from "@/components/ui/separator"
import { Textarea } from "@/components/ui/textarea"
import type { UserRole } from "@/lib/types"
import { useAuthStore } from "@/store/auth"
import { CheckCircle, Clock, ShieldCheck, Upload } from "lucide-react"
import { useEffect, useRef, useState } from "react"
export default function VerifyPage() {
const [verifyRole, setVerifyRole] = useState<UserRole | "">("")
const [realName, setRealName] = useState("")
const [idNumber, setIdNumber] = useState("")
const [gameProfile, setGameProfile] = useState("")
const verificationStatus = useAuthStore((state) => state.verificationStatus)
const verificationReasons = useAuthStore((state) => state.verificationReasons)
const verifiedRoles = useAuthStore((state) => state.verifiedRoles)
const submitVerification = useAuthStore((state) => state.submitVerification)
const approveVerification = useAuthStore((state) => state.approveVerification)
const timersRef = useRef<Map<UserRole, ReturnType<typeof setTimeout>>>(new Map())
useEffect(
() => () => {
timersRef.current.forEach((timer) => {
clearTimeout(timer)
})
timersRef.current.clear()
},
[],
)
const buildMaterials = () => {
const materials: Record<string, string> = {
realName,
idNumber,
gameProfile,
idCardFront: "mock://idCardFront",
idCardBack: "mock://idCardBack",
gameScreenshot: "mock://gameScreenshot",
}
return materials
}
const submitWithMockApproval = (role: UserRole) => {
submitVerification(role, buildMaterials())
const oldTimer = timersRef.current.get(role)
if (oldTimer) {
clearTimeout(oldTimer)
}
const timer = setTimeout(() => {
approveVerification(role)
timersRef.current.delete(role)
}, 3000)
timersRef.current.set(role, timer)
}
const roleMeta: { role: UserRole; label: string }[] = [
{ role: "player", label: "打手认证" },
{ role: "owner", label: "店主认证" },
]
return (
<div className="container mx-auto max-w-2xl px-4 py-8 space-y-6">
<h1 className="text-2xl font-bold"></h1>
<Card>
<CardHeader>
<CardTitle className="text-base"></CardTitle>
</CardHeader>
<CardContent className="space-y-3 text-sm text-muted-foreground">
<div className="flex items-start gap-2">
<ShieldCheck className="h-4 w-4 shrink-0 mt-0.5 text-primary" />
<span></span>
</div>
<div className="flex items-start gap-2">
<CheckCircle className="h-4 w-4 shrink-0 mt-0.5 text-primary" />
<span></span>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-base"></CardTitle>
</CardHeader>
<CardContent className="space-y-3">
{roleMeta.map((item) => {
const status = verificationStatus[item.role]
const reason = verificationReasons[item.role]
return (
<Card key={item.role} className="p-3 space-y-2 shadow-none">
<div className="flex items-center justify-between">
<span className="text-sm font-medium">{item.label}</span>
{status === "approved" || verifiedRoles.includes(item.role) ? (
<Badge
variant="outline"
className="text-green-700 border-green-200 bg-green-50"
>
</Badge>
) : status === "pending" ? (
<Badge variant="outline">
<Clock className="mr-1 h-3.5 w-3.5" />
</Badge>
) : status === "rejected" ? (
<Badge variant="outline" className="text-red-700 border-red-200 bg-red-50">
</Badge>
) : (
<Badge variant="secondary"></Badge>
)}
</div>
{status === "rejected" && (
<p className="text-xs text-muted-foreground">{reason}</p>
)}
{status === "rejected" && (
<Button
variant="outline"
size="sm"
onClick={() => submitWithMockApproval(item.role)}
>
</Button>
)}
</Card>
)
})}
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-base"></CardTitle>
</CardHeader>
<CardContent className="space-y-6">
<div className="space-y-2">
<Label></Label>
<Select value={verifyRole} onValueChange={(value) => setVerifyRole(value as UserRole)}>
<SelectTrigger>
<SelectValue placeholder="选择认证类型" />
</SelectTrigger>
<SelectContent>
<SelectItem value="player"></SelectItem>
<SelectItem value="owner"></SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label htmlFor="real-name"></Label>
<Input
id="real-name"
placeholder="请输入真实姓名"
value={realName}
onChange={(event) => setRealName(event.target.value)}
/>
</div>
<div className="space-y-2">
<Label htmlFor="id-number"></Label>
<Input
id="id-number"
placeholder="请输入身份证号"
value={idNumber}
onChange={(event) => setIdNumber(event.target.value)}
/>
</div>
<Separator />
<div className="space-y-2">
<Label></Label>
<Textarea
placeholder="请描述你的游戏经历、段位、擅长游戏等"
rows={3}
value={gameProfile}
onChange={(event) => setGameProfile(event.target.value)}
/>
</div>
<div className="space-y-2">
<Label></Label>
<div className="flex gap-2">
<div className="h-24 w-24 rounded-md border-2 border-dashed border-muted-foreground/25 flex flex-col items-center justify-center gap-1 text-muted-foreground cursor-pointer hover:border-muted-foreground/50 transition-colors">
<Upload className="h-5 w-5" />
<span className="text-[10px]"></span>
</div>
<div className="h-24 w-24 rounded-md border-2 border-dashed border-muted-foreground/25 flex flex-col items-center justify-center gap-1 text-muted-foreground cursor-pointer hover:border-muted-foreground/50 transition-colors">
<Upload className="h-5 w-5" />
<span className="text-[10px]"></span>
</div>
<div className="h-24 w-24 rounded-md border-2 border-dashed border-muted-foreground/25 flex flex-col items-center justify-center gap-1 text-muted-foreground cursor-pointer hover:border-muted-foreground/50 transition-colors">
<Upload className="h-5 w-5" />
<span className="text-[10px]"></span>
</div>
</div>
<p className="text-xs text-muted-foreground"> JPGPNG 5MB</p>
</div>
<Button
className="w-full"
disabled={
!verifyRole ||
verificationStatus[verifyRole] === "pending" ||
verificationStatus[verifyRole] === "approved"
}
onClick={() => {
if (!verifyRole) return
submitWithMockApproval(verifyRole)
}}
>
{verifyRole && verificationStatus[verifyRole] === "rejected"
? "重新提交认证申请"
: "提交认证申请"}
</Button>
</CardContent>
</Card>
</div>
)
}