2025-05-22 20:42:10 +08:00

246 lines
8.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.

"use client"
import { MainNav } from "@/components/main-nav"
import { SearchBar } from "@/components/search-bar"
import { ThemeToggle } from "@/components/theme-toggle"
import { UserNav } from "@/components/user-nav"
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Separator } from "@/components/ui/separator"
import { useToast } from "@/components/ui/use-toast"
import { useAuth } from "@/context/auth-context"
import { CheckCircle, Package } from "lucide-react"
import { useRouter } from "next/navigation"
import { useEffect, useState, use } from "react"
import { fetchWithAuth } from "@/lib/api"
interface OrderItem {
orderItemId: number
bookId: number
bookTitle: string
quantity: number
unitPrice: number
}
interface Order {
orderId: number
readerId: number
readerName: string
orderDate: string
totalAmount: number
status: string
items: OrderItem[]
}
export default function OrderDetailPage({ params }: { params: Promise<{ id: string }> | { id: string } }) {
// 使用 React.use() 解包 params
const resolvedParams = "then" in params ? use(params) : params
const orderId = resolvedParams.id
const [order, setOrder] = useState<Order | null>(null)
const [loading, setLoading] = useState(true)
const { toast } = useToast()
const router = useRouter()
const { user } = useAuth()
useEffect(() => {
if (!user) {
toast({
title: "请先登录",
description: "您需要登录后才能查看订单",
variant: "destructive",
})
router.push("/login")
return
}
const fetchOrder = async () => {
try {
const response = await fetchWithAuth(`orders/${orderId}`)
const result = await response.json()
if (result.code === 0) {
setOrder(result.data)
} else {
toast({
variant: "destructive",
title: "获取订单失败",
description: result.msg || "无法获取订单信息",
})
}
} catch (error) {
toast({
variant: "destructive",
title: "获取订单失败",
description: "服务器连接错误,请稍后再试",
})
} finally {
setLoading(false)
}
}
fetchOrder()
}, [orderId, toast, router, user])
if (loading) {
return (
<div className="flex min-h-screen flex-col">
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="container flex h-16 items-center justify-between">
<MainNav />
<div className="flex items-center gap-4">
<SearchBar />
<ThemeToggle />
<UserNav />
</div>
</div>
</header>
<main className="flex-1 container py-8">
<div className="flex justify-center items-center h-[60vh]">
<div className="animate-pulse text-xl">...</div>
</div>
</main>
</div>
)
}
if (!order) {
return (
<div className="flex min-h-screen flex-col">
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="container flex h-16 items-center justify-between">
<MainNav />
<div className="flex items-center gap-4">
<SearchBar />
<ThemeToggle />
<UserNav />
</div>
</div>
</header>
<main className="flex-1 container py-8">
<div className="flex justify-center items-center h-[60vh]">
<div className="text-xl"></div>
</div>
</main>
</div>
)
}
return (
<div className="flex min-h-screen flex-col">
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="container flex h-16 items-center justify-between">
<MainNav />
<div className="flex items-center gap-4">
<SearchBar />
<ThemeToggle />
<UserNav />
</div>
</div>
</header>
<main className="flex-1">
<div className="container py-8">
<div className="flex flex-col space-y-8">
<div className="flex items-center space-x-2">
<Package className="h-6 w-6" />
<h1 className="text-3xl font-bold tracking-tight"></h1>
</div>
<div className="grid gap-8 md:grid-cols-3">
<div className="md:col-span-2 space-y-6">
<Card>
<CardHeader className="pb-4">
<CardTitle className="text-xl"></CardTitle>
</CardHeader>
<CardContent>
<div className="flex items-center gap-2 text-green-600 dark:text-green-400">
<CheckCircle className="h-5 w-5" />
<span className="font-medium">{order.status}</span>
</div>
</CardContent>
</Card>
<Card>
<CardHeader className="pb-4">
<CardTitle className="text-xl"></CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
{order.items.map((item) => (
<div key={item.orderItemId} className="flex items-center gap-4 py-2">
<div className="flex-1">
<h3 className="font-medium">{item.bookTitle}</h3>
<p className="text-sm text-muted-foreground">
: ¥{item.unitPrice.toFixed(2)} × {item.quantity}
</p>
</div>
<div className="text-right">¥{(item.unitPrice * item.quantity).toFixed(2)}</div>
</div>
))}
</div>
</CardContent>
</Card>
</div>
<div>
<Card className="sticky top-24">
<CardHeader>
<CardTitle></CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<div className="flex justify-between">
<span className="text-muted-foreground"></span>
<span>{order.orderId}</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground"></span>
<span>{new Date(order.orderDate).toLocaleString()}</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground"></span>
<span>{order.readerName}</span>
</div>
</div>
<Separator />
<div className="space-y-2">
<div className="flex justify-between">
<span className="text-muted-foreground"></span>
<span>¥{order.totalAmount.toFixed(2)}</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground"></span>
<span></span>
</div>
</div>
<Separator />
<div className="flex justify-between font-medium">
<span></span>
<span className="text-lg">¥{order.totalAmount.toFixed(2)}</span>
</div>
</CardContent>
</Card>
</div>
</div>
<div className="flex justify-center mt-8">
<Button onClick={() => router.push("/orders")}></Button>
</div>
</div>
</div>
</main>
<footer className="border-t py-6 md:py-0">
<div className="container flex flex-col items-center justify-between gap-4 md:h-24 md:flex-row">
<p className="text-center text-sm leading-loose text-muted-foreground md:text-left">
&copy; {new Date().getFullYear()} . .
</p>
</div>
</footer>
</div>
)
}