feat: search, player detail, shop detail, order flow, chat, review, and dispute pages
This commit is contained in:
@@ -1,8 +1,176 @@
|
||||
export default function DisputePage({ params: _params }: { params: Promise<{ id: string }> }) {
|
||||
"use client"
|
||||
|
||||
import { AlertTriangle, ArrowLeft, Clock, FileText } from "lucide-react"
|
||||
import Link from "next/link"
|
||||
import { use, 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 { Label } from "@/components/ui/label"
|
||||
import { Separator } from "@/components/ui/separator"
|
||||
import { Textarea } from "@/components/ui/textarea"
|
||||
import { mockDisputes, mockOrders } from "@/lib/mock-data"
|
||||
|
||||
const disputeStatusLabels: Record<string, string> = {
|
||||
open: "已提交",
|
||||
reviewing: "审核中",
|
||||
resolved: "已解决",
|
||||
appealed: "申诉中",
|
||||
}
|
||||
|
||||
export default function DisputePage({ params }: { params: Promise<{ id: string }> }) {
|
||||
const { id } = use(params)
|
||||
const order = mockOrders.find((o) => o.id === id)
|
||||
const existingDispute = mockDisputes.find((d) => d.orderId === id)
|
||||
const [reason, setReason] = useState("")
|
||||
const [submitted, setSubmitted] = useState(false)
|
||||
|
||||
if (!order) {
|
||||
return (
|
||||
<div className="container mx-auto py-8 px-4 text-center text-muted-foreground">
|
||||
订单不存在
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (existingDispute) {
|
||||
return (
|
||||
<div className="container mx-auto py-8 px-4 max-w-lg">
|
||||
<Link
|
||||
href={`/order/${id}`}
|
||||
className="inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground mb-4"
|
||||
>
|
||||
<ArrowLeft className="h-4 w-4" />
|
||||
返回订单
|
||||
</Link>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<div className="flex items-center justify-between">
|
||||
<CardTitle>争议详情</CardTitle>
|
||||
<Badge variant="outline">{disputeStatusLabels[existingDispute.status]}</Badge>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<FileText className="h-4 w-4 text-muted-foreground" />
|
||||
<span className="text-muted-foreground">发起人:</span>
|
||||
{existingDispute.initiatorName}
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<Clock className="h-4 w-4 text-muted-foreground" />
|
||||
<span className="text-muted-foreground">提交时间:</span>
|
||||
{new Date(existingDispute.createdAt).toLocaleString("zh-CN")}
|
||||
</div>
|
||||
</div>
|
||||
<Separator />
|
||||
<div>
|
||||
<Label className="text-muted-foreground">争议原因</Label>
|
||||
<p className="mt-1 text-sm">{existingDispute.reason}</p>
|
||||
</div>
|
||||
{existingDispute.evidence.length > 0 && (
|
||||
<div>
|
||||
<Label className="text-muted-foreground">证据截图</Label>
|
||||
<div className="mt-1 flex gap-2">
|
||||
{existingDispute.evidence.map((url) => (
|
||||
<div
|
||||
key={url}
|
||||
className="h-20 w-20 rounded border bg-muted flex items-center justify-center text-xs text-muted-foreground"
|
||||
>
|
||||
截图
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{existingDispute.result && (
|
||||
<>
|
||||
<Separator />
|
||||
<div>
|
||||
<Label className="text-muted-foreground">仲裁结果</Label>
|
||||
<p className="mt-1 text-sm font-medium">
|
||||
{existingDispute.result === "full_refund"
|
||||
? "全额退款"
|
||||
: existingDispute.result === "full_payment"
|
||||
? "全额支付给打手"
|
||||
: "部分退款"}
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (submitted) {
|
||||
return (
|
||||
<div className="container mx-auto py-8 px-4 max-w-lg text-center space-y-4">
|
||||
<AlertTriangle className="h-12 w-12 mx-auto text-yellow-500" />
|
||||
<h2 className="text-xl font-bold">争议已提交</h2>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
平台将在 3 个工作日内审核你的争议申请,期间聊天会话仍可使用。
|
||||
</p>
|
||||
<Button asChild>
|
||||
<Link href={`/order/${id}`}>返回订单</Link>
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container mx-auto py-8 px-4">
|
||||
<h1 className="text-2xl font-bold">争议仲裁</h1>
|
||||
<p className="mt-2 text-muted-foreground">提交争议说明和证据</p>
|
||||
<div className="container mx-auto py-8 px-4 max-w-lg">
|
||||
<Link
|
||||
href={`/order/${id}`}
|
||||
className="inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground mb-4"
|
||||
>
|
||||
<ArrowLeft className="h-4 w-4" />
|
||||
返回订单
|
||||
</Link>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<AlertTriangle className="h-5 w-5 text-yellow-500" />
|
||||
发起争议
|
||||
</CardTitle>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{order.service.title} · {order.playerName}
|
||||
</p>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="dispute-reason">争议原因</Label>
|
||||
<Textarea
|
||||
id="dispute-reason"
|
||||
placeholder="请详细描述你遇到的问题..."
|
||||
value={reason}
|
||||
onChange={(e) => setReason(e.target.value)}
|
||||
rows={4}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label>上传证据截图</Label>
|
||||
<div className="border-2 border-dashed rounded-md p-6 text-center text-sm text-muted-foreground">
|
||||
点击或拖拽上传截图(最多5张)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-md bg-muted/50 p-3 text-xs text-muted-foreground space-y-1">
|
||||
<p>· 提交争议后,订单资金将继续托管</p>
|
||||
<p>· 聊天记录将作为证据保留</p>
|
||||
<p>· 平台将在 3 个工作日内审核</p>
|
||||
<p>· 对仲裁结果不满可申诉一次</p>
|
||||
</div>
|
||||
|
||||
<Button className="w-full" disabled={!reason.trim()} onClick={() => setSubmitted(true)}>
|
||||
提交争议
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user