202 lines
7.2 KiB
TypeScript
202 lines
7.2 KiB
TypeScript
"use client"
|
||
|
||
import { ArrowLeft, CheckCircle, CreditCard, ShieldCheck } from "lucide-react"
|
||
import Link from "next/link"
|
||
import { useRouter, useSearchParams } from "next/navigation"
|
||
import { useState } from "react"
|
||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
|
||
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 { Separator } from "@/components/ui/separator"
|
||
import { Textarea } from "@/components/ui/textarea"
|
||
import { mockOrders, mockPlayers, mockServices, walletBalance } from "@/lib/mock"
|
||
import { useRequireAuth } from "@/lib/use-require-auth"
|
||
|
||
function showFeedback(message: string) {
|
||
if (typeof window === "undefined") return
|
||
window.alert(message)
|
||
}
|
||
|
||
export default function NewOrderPage() {
|
||
const router = useRouter()
|
||
const searchParams = useSearchParams()
|
||
const { requireAuth } = useRequireAuth()
|
||
const serviceId = searchParams.get("serviceId")
|
||
|
||
const service = mockServices.find((s) => s.id === serviceId)
|
||
const player = service ? mockPlayers.find((p) => p.id === service.playerId) : null
|
||
|
||
const [quantity, setQuantity] = useState(1)
|
||
const [note, setNote] = useState("")
|
||
const [submitted, setSubmitted] = useState(false)
|
||
|
||
if (!service || !player) {
|
||
return (
|
||
<div className="container mx-auto py-8 px-4 text-center text-muted-foreground">
|
||
服务不存在
|
||
</div>
|
||
)
|
||
}
|
||
|
||
const totalPrice = service.price * quantity
|
||
const redirectOrderId =
|
||
mockOrders.find((order) => order.service.id === service.id)?.id ?? mockOrders[0]?.id
|
||
|
||
if (submitted) {
|
||
return (
|
||
<div className="container mx-auto py-8 px-4 max-w-lg text-center space-y-4">
|
||
<CheckCircle className="h-12 w-12 mx-auto text-green-500" />
|
||
<h2 className="text-xl font-bold">下单成功</h2>
|
||
<p className="text-sm text-muted-foreground">
|
||
订单已创建,等待打手接单。你可以在订单列表中查看进度。
|
||
</p>
|
||
<div className="flex gap-2 justify-center">
|
||
<Button asChild>
|
||
<Link href="/orders">查看订单</Link>
|
||
</Button>
|
||
<Button variant="outline" asChild>
|
||
<Link href={`/player/${player.id}`}>返回打手主页</Link>
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
return (
|
||
<div className="container mx-auto py-8 px-4 max-w-2xl">
|
||
<Link
|
||
href={`/player/${player.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>
|
||
|
||
<h1 className="text-2xl font-bold mb-6">确认下单</h1>
|
||
|
||
<div className="space-y-6">
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle className="text-base">服务信息</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="space-y-4">
|
||
<div className="flex items-center gap-3">
|
||
<Avatar className="h-10 w-10">
|
||
<AvatarImage src={player.user.avatar} />
|
||
<AvatarFallback>{player.user.nickname[0]}</AvatarFallback>
|
||
</Avatar>
|
||
<div>
|
||
<p className="font-medium">{player.user.nickname}</p>
|
||
<p className="text-xs text-muted-foreground">
|
||
{player.shopName ? `${player.shopName} · ` : ""}
|
||
{service.gameName}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<Separator />
|
||
<div className="space-y-2 text-sm">
|
||
<div className="flex justify-between">
|
||
<span className="text-muted-foreground">服务</span>
|
||
<span>{service.title}</span>
|
||
</div>
|
||
<div className="flex justify-between">
|
||
<span className="text-muted-foreground">单价</span>
|
||
<span>
|
||
¥{service.price}/{service.unit}
|
||
</span>
|
||
</div>
|
||
{service.rankRange && (
|
||
<div className="flex justify-between">
|
||
<span className="text-muted-foreground">段位范围</span>
|
||
<span>{service.rankRange}</span>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle className="text-base">订单信息</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="space-y-4">
|
||
<div className="space-y-2">
|
||
<Label htmlFor="quantity">数量({service.unit})</Label>
|
||
<Input
|
||
id="quantity"
|
||
type="number"
|
||
min={1}
|
||
max={99}
|
||
value={quantity}
|
||
onChange={(e) => setQuantity(Math.max(1, Number.parseInt(e.target.value, 10) || 1))}
|
||
/>
|
||
</div>
|
||
<div className="space-y-2">
|
||
<Label htmlFor="note">备注(可选)</Label>
|
||
<Textarea
|
||
id="note"
|
||
placeholder="例如:希望晚上8点后开始"
|
||
value={note}
|
||
onChange={(e) => setNote(e.target.value)}
|
||
rows={3}
|
||
/>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle className="text-base">支付信息</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="space-y-3">
|
||
<div className="flex justify-between text-sm">
|
||
<span className="text-muted-foreground">
|
||
{service.title} × {quantity}
|
||
</span>
|
||
<span>¥{totalPrice}</span>
|
||
</div>
|
||
<Separator />
|
||
<div className="flex justify-between font-medium">
|
||
<span>应付金额</span>
|
||
<span className="text-lg text-primary">¥{totalPrice}</span>
|
||
</div>
|
||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||
<CreditCard className="h-4 w-4" />
|
||
<span>钱包余额: ¥{walletBalance}</span>
|
||
{walletBalance < totalPrice && <span className="text-destructive">(余额不足)</span>}
|
||
</div>
|
||
<div className="flex items-center gap-2 text-xs text-muted-foreground">
|
||
<ShieldCheck className="h-3.5 w-3.5" />
|
||
<span>资金由平台托管,服务完成后支付给打手</span>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
<Button
|
||
className="w-full"
|
||
size="lg"
|
||
disabled={walletBalance < totalPrice}
|
||
onClick={() =>
|
||
requireAuth(async () => {
|
||
await new Promise((resolve) => setTimeout(resolve, 500))
|
||
setSubmitted(true)
|
||
showFeedback("下单成功")
|
||
if (redirectOrderId) {
|
||
setTimeout(() => {
|
||
router.push(`/order/${redirectOrderId}`)
|
||
}, 800)
|
||
return
|
||
}
|
||
router.push("/orders")
|
||
})
|
||
}
|
||
>
|
||
确认支付 ¥{totalPrice}
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|