feat(favorites): migrate to backend API

This commit is contained in:
zetaloop
2026-03-01 22:36:50 +08:00
parent eba8fc7e65
commit 505d9c0168
3 changed files with 120 additions and 111 deletions
+6 -90
View File
@@ -2,14 +2,8 @@ import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { Badge } from "@/components/ui/badge"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import {
getUserById,
listFavoritesByUser,
listPlayers,
listPostsByAuthor,
listShops,
} from "@/lib/api"
import { MessageSquare, Star, ThumbsUp } from "lucide-react"
import { getUserById, listPostsByAuthor } from "@/lib/api"
import { MessageSquare, ThumbsUp } from "lucide-react"
import Link from "next/link"
import { notFound } from "next/navigation"
@@ -21,20 +15,8 @@ export default async function UserProfilePage({ params }: { params: Promise<{ id
notFound()
}
const [userPosts, userFavorites, players, shops] = await Promise.all([
listPostsByAuthor(id),
listFavoritesByUser(user.id),
listPlayers(),
listShops(),
])
const favoritePlayers = userFavorites
.filter((f) => f.targetType === "player")
.map((f) => players.find((p) => p.id === f.targetId))
.filter((p): p is NonNullable<typeof p> => p != null)
const favoriteShops = userFavorites
.filter((f) => f.targetType === "shop")
.map((f) => shops.find((s) => s.id === f.targetId))
.filter((s): s is NonNullable<typeof s> => s != null)
const userPosts = await listPostsByAuthor(id)
const favoriteCountText = "—"
return (
<div className="container mx-auto max-w-4xl px-4 py-8 space-y-6">
@@ -48,7 +30,7 @@ export default async function UserProfilePage({ params }: { params: Promise<{ id
<p className="text-sm text-muted-foreground">{user.bio || "这个人很懒,什么都没写~"}</p>
<div className="flex gap-4 text-sm text-muted-foreground">
<span>{userPosts.length} </span>
<span>{userFavorites.length} </span>
<span>{favoriteCountText} </span>
</div>
</div>
</div>
@@ -95,73 +77,7 @@ export default async function UserProfilePage({ params }: { params: Promise<{ id
</TabsContent>
<TabsContent value="favorites" className="mt-4 space-y-6">
{favoritePlayers.length > 0 && (
<div>
<h3 className="text-sm font-medium text-muted-foreground mb-3"></h3>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
{favoritePlayers.map((player) => (
<Link key={player.id} href={`/player/${player.id}`}>
<Card>
<CardContent className="flex items-center gap-3 p-4">
<Avatar>
<AvatarImage src={player.user.avatar} />
<AvatarFallback>{player.user.nickname[0]}</AvatarFallback>
</Avatar>
<div className="flex-1 min-w-0">
<p className="font-medium truncate">{player.user.nickname}</p>
<div className="flex items-center gap-2 text-xs text-muted-foreground">
<Star className="h-3 w-3 fill-yellow-500 text-yellow-500" />
<span>{player.rating}</span>
<span>·</span>
<span>{player.totalOrders}</span>
</div>
</div>
<Badge
variant={player.status === "available" ? "default" : "secondary"}
className="text-xs shrink-0"
>
{player.status === "available" ? "可接单" : "忙碌"}
</Badge>
</CardContent>
</Card>
</Link>
))}
</div>
</div>
)}
{favoriteShops.length > 0 && (
<div>
<h3 className="text-sm font-medium text-muted-foreground mb-3"></h3>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
{favoriteShops.map((shop) => (
<Link key={shop.id} href={`/shop/${shop.id}`}>
<Card>
<CardContent className="flex items-center gap-3 p-4">
<Avatar>
<AvatarImage src={shop.owner.avatar} />
<AvatarFallback>{shop.name[0]}</AvatarFallback>
</Avatar>
<div className="flex-1 min-w-0">
<p className="font-medium truncate">{shop.name}</p>
<div className="flex items-center gap-2 text-xs text-muted-foreground">
<Star className="h-3 w-3 fill-yellow-500 text-yellow-500" />
<span>{shop.rating}</span>
<span>·</span>
<span>{shop.totalOrders}</span>
</div>
</div>
</CardContent>
</Card>
</Link>
))}
</div>
</div>
)}
{favoritePlayers.length === 0 && favoriteShops.length === 0 && (
<div className="text-center py-12 text-muted-foreground"></div>
)}
<div className="text-center py-12 text-muted-foreground"></div>
</TabsContent>
</Tabs>
</div>