4820370b6a
- Add sticky header with book management nav links and logout button - Replace placeholder page components with real feature imports - Add login page route to router - Fix date-time formatting for consistent YYYY-MM-DD HH:mm output
97 lines
3.2 KiB
TypeScript
97 lines
3.2 KiB
TypeScript
import { Loader2Icon } from "lucide-react"
|
||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
||
import { Badge } from "@/components/ui/badge"
|
||
import { Button } from "@/components/ui/button"
|
||
import { Skeleton } from "@/components/ui/skeleton"
|
||
import { useMyBorrows, useReturnBook } from "./hooks"
|
||
import { formatDateTime } from "@/lib/formatters"
|
||
|
||
export default function MyBorrowsPage() {
|
||
const { data: records, isLoading, error } = useMyBorrows()
|
||
const returnBook = useReturnBook()
|
||
|
||
if (isLoading) return <MyBorrowsSkeleton />
|
||
|
||
if (error) {
|
||
return (
|
||
<div className="mx-auto max-w-[1200px] px-4 py-8">
|
||
<div className="rounded-lg border border-destructive/50 bg-destructive/10 px-4 py-3 text-sm text-destructive">
|
||
加载失败:{error instanceof Error ? error.message : "未知错误"}
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
const list = records ?? []
|
||
|
||
if (list.length === 0) {
|
||
return (
|
||
<div className="mx-auto max-w-[1200px] px-4 py-16 text-center text-muted-foreground">
|
||
<p className="text-lg">暂无借阅记录</p>
|
||
<p className="mt-1 text-sm">去书目页面借阅你感兴趣的图书吧</p>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
return (
|
||
<div className="mx-auto max-w-[1200px] px-4 py-8">
|
||
<h1 className="mb-4 text-xl font-semibold">我的借阅</h1>
|
||
<Table>
|
||
<TableHeader>
|
||
<TableRow>
|
||
<TableHead>书名</TableHead>
|
||
<TableHead>作者</TableHead>
|
||
<TableHead>借阅时间</TableHead>
|
||
<TableHead>归还时间</TableHead>
|
||
<TableHead>状态</TableHead>
|
||
<TableHead className="w-[100px]">操作</TableHead>
|
||
</TableRow>
|
||
</TableHeader>
|
||
<TableBody>
|
||
{list.map((r) => (
|
||
<TableRow key={r.id}>
|
||
<TableCell className="font-medium">{r.bookBorrowVo.name}</TableCell>
|
||
<TableCell>{r.bookBorrowVo.author}</TableCell>
|
||
<TableCell>{formatDateTime(r.borrowTime)}</TableCell>
|
||
<TableCell>
|
||
{r.returnTime ? formatDateTime(r.returnTime) : "-"}
|
||
</TableCell>
|
||
<TableCell>
|
||
<Badge variant={r.status === "BORROWED" ? "default" : "secondary"}>
|
||
{r.status === "BORROWED" ? "借阅中" : "已归还"}
|
||
</Badge>
|
||
</TableCell>
|
||
<TableCell>
|
||
{r.status === "BORROWED" && (
|
||
<Button
|
||
size="sm"
|
||
variant="outline"
|
||
disabled={returnBook.isPending}
|
||
onClick={() => returnBook.mutate(r.id)}
|
||
>
|
||
{returnBook.isPending && <Loader2Icon className="animate-spin" />}
|
||
归还
|
||
</Button>
|
||
)}
|
||
</TableCell>
|
||
</TableRow>
|
||
))}
|
||
</TableBody>
|
||
</Table>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
function MyBorrowsSkeleton() {
|
||
return (
|
||
<div className="mx-auto max-w-[1200px] px-4 py-8">
|
||
<Skeleton className="mb-4 h-7 w-24" />
|
||
<div className="space-y-2">
|
||
{Array.from({ length: 5 }).map((_, i) => (
|
||
<Skeleton key={i} className="h-10 w-full" />
|
||
))}
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|