Files
juwan-frontend/app/(order)/order/[id]/page.tsx
T

202 lines
7.7 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.
import { ArrowLeft, CheckCircle, Clock, Star } from "lucide-react"
import Link from "next/link"
import { notFound } from "next/navigation"
import OrderActions from "@/components/order-actions"
import { Badge } from "@/components/ui/badge"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Separator } from "@/components/ui/separator"
import { statusLabels } from "@/lib/constants"
import { mockChatSessions, mockOrders, mockReviews } from "@/lib/mock"
import type { OrderStatus } from "@/lib/types"
const statusSteps: OrderStatus[] = [
"pending_payment",
"pending_accept",
"in_progress",
"pending_close",
"pending_review",
"completed",
]
export default async function OrderDetailPage({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params
const order = mockOrders.find((o) => o.id === id)
if (!order) notFound()
const reviews = mockReviews.filter((r) => r.orderId === id)
const chatSession = mockChatSessions.find((s) => s.orderId === id)
const currentStepIndex = statusSteps.indexOf(order.status)
return (
<div className="container mx-auto py-8 px-4 max-w-3xl">
<Link
href="/orders"
className="inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground mb-4"
>
<ArrowLeft className="h-4 w-4" />
</Link>
<div className="flex items-center justify-between mb-6">
<h1 className="text-2xl font-bold"></h1>
<Badge variant="outline">{statusLabels[order.status]}</Badge>
</div>
{order.status !== "disputed" && order.status !== "cancelled" && (
<Card className="mb-6">
<CardContent className="pt-6">
<div className="flex items-center justify-between">
{statusSteps.map((step, i) => {
const isActive = i <= currentStepIndex
const isCurrent = i === currentStepIndex
return (
<div key={step} className="flex flex-col items-center gap-1 flex-1">
<div
className={`h-8 w-8 rounded-full flex items-center justify-center text-xs font-medium ${
isCurrent
? "bg-primary text-primary-foreground"
: isActive
? "bg-primary/20 text-primary"
: "bg-muted text-muted-foreground"
}`}
>
{isActive ? <CheckCircle className="h-4 w-4" /> : i + 1}
</div>
<span className="text-[10px] text-muted-foreground text-center">
{statusLabels[step]}
</span>
</div>
)
})}
</div>
</CardContent>
</Card>
)}
<Card className="mb-6">
<CardHeader>
<CardTitle className="text-base"></CardTitle>
</CardHeader>
<CardContent className="space-y-3">
<div className="flex justify-between text-sm">
<span className="text-muted-foreground"></span>
<span>{order.service.title}</span>
</div>
<div className="flex justify-between text-sm">
<span className="text-muted-foreground"></span>
<span>{order.service.gameName}</span>
</div>
<div className="flex justify-between text-sm">
<span className="text-muted-foreground"></span>
<span>
¥{order.service.price}/{order.service.unit}
</span>
</div>
<Separator />
<div className="flex justify-between text-sm">
<span className="text-muted-foreground"></span>
<Link href={`/player/${order.playerId}`} className="text-primary hover:underline">
{order.playerName}
</Link>
</div>
{order.shopName && (
<div className="flex justify-between text-sm">
<span className="text-muted-foreground"></span>
<Link href={`/shop/${order.shopId}`} className="text-primary hover:underline">
{order.shopName}
</Link>
</div>
)}
<Separator />
<div className="flex justify-between text-sm font-medium">
<span></span>
<span className="text-lg">¥{order.totalPrice}</span>
</div>
{order.note && (
<div className="text-sm">
<span className="text-muted-foreground">: </span>
{order.note}
</div>
)}
</CardContent>
</Card>
<Card className="mb-6">
<CardHeader>
<CardTitle className="text-base">线</CardTitle>
</CardHeader>
<CardContent className="space-y-2 text-sm">
<div className="flex items-center gap-2">
<Clock className="h-3.5 w-3.5 text-muted-foreground" />
<span className="text-muted-foreground">:</span>
{new Date(order.createdAt).toLocaleString("zh-CN")}
</div>
{order.acceptedAt && (
<div className="flex items-center gap-2">
<CheckCircle className="h-3.5 w-3.5 text-green-500" />
<span className="text-muted-foreground">:</span>
{new Date(order.acceptedAt).toLocaleString("zh-CN")}
</div>
)}
{order.closedAt && (
<div className="flex items-center gap-2">
<CheckCircle className="h-3.5 w-3.5 text-green-500" />
<span className="text-muted-foreground">:</span>
{new Date(order.closedAt).toLocaleString("zh-CN")}
</div>
)}
{order.completedAt && (
<div className="flex items-center gap-2">
<CheckCircle className="h-3.5 w-3.5 text-green-500" />
<span className="text-muted-foreground">:</span>
{new Date(order.completedAt).toLocaleString("zh-CN")}
</div>
)}
</CardContent>
</Card>
{reviews.length > 0 && (
<Card className="mb-6">
<CardHeader>
<CardTitle className="text-base"></CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{reviews.map((review) => (
<div key={review.id} className="space-y-1">
<div className="flex items-center gap-2">
<span className="text-sm font-medium">{review.fromUserName}</span>
<div className="flex">
{[1, 2, 3, 4, 5].map((star) => (
<Star
key={`star-${star}`}
className={`h-3.5 w-3.5 ${star <= review.rating ? "fill-yellow-400 text-yellow-400" : "text-muted"}`}
/>
))}
</div>
</div>
{review.sealed ? (
<p className="text-sm text-muted-foreground"></p>
) : (
review.content && (
<p className="text-sm text-muted-foreground">{review.content}</p>
)
)}
<p className="text-xs text-muted-foreground">
{new Date(review.createdAt).toLocaleDateString("zh-CN")}
</p>
</div>
))}
</CardContent>
</Card>
)}
<OrderActions
orderId={order.id}
initialStatus={order.status}
chatSessionId={chatSession?.id}
serviceId={order.service.id}
/>
</div>
)
}