feat(ui): refine public discovery pages
This commit is contained in:
@@ -4,6 +4,7 @@ import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
|
|||||||
import { Badge } from "@/components/ui/badge"
|
import { Badge } from "@/components/ui/badge"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Card, CardContent, CardFooter, CardHeader } from "@/components/ui/card"
|
import { Card, CardContent, CardFooter, CardHeader } from "@/components/ui/card"
|
||||||
|
import { EmptyState } from "@/components/ui/empty-state"
|
||||||
import { listGames, listPosts } from "@/lib/api"
|
import { listGames, listPosts } from "@/lib/api"
|
||||||
import { roleLabels } from "@/lib/constants"
|
import { roleLabels } from "@/lib/constants"
|
||||||
import type { Game, Post } from "@/lib/types"
|
import type { Game, Post } from "@/lib/types"
|
||||||
@@ -86,14 +87,15 @@ export default function CommunityPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2">
|
||||||
{games.map((game) => (
|
{games.map((game) => (
|
||||||
<Badge
|
<Button
|
||||||
key={game.id}
|
key={game.id}
|
||||||
variant={selectedGame === game.name ? "default" : "outline"}
|
variant={selectedGame === game.name ? "default" : "outline"}
|
||||||
className="cursor-pointer hover:bg-primary/80 transition-colors px-3 py-1"
|
size="sm"
|
||||||
|
className="h-7 rounded-full px-3"
|
||||||
onClick={() => setSelectedGame(selectedGame === game.name ? null : game.name)}
|
onClick={() => setSelectedGame(selectedGame === game.name ? null : game.name)}
|
||||||
>
|
>
|
||||||
{game.name}
|
{game.name}
|
||||||
</Badge>
|
</Button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -102,11 +104,11 @@ export default function CommunityPage() {
|
|||||||
{postsLoading ? (
|
{postsLoading ? (
|
||||||
<div className="text-center py-12 text-muted-foreground">加载中...</div>
|
<div className="text-center py-12 text-muted-foreground">加载中...</div>
|
||||||
) : filteredPosts.length === 0 ? (
|
) : filteredPosts.length === 0 ? (
|
||||||
<div className="text-center py-12 text-muted-foreground">暂无帖子</div>
|
<EmptyState title="暂无帖子" description="此分类下暂未找到相关的讨论内容" />
|
||||||
) : (
|
) : (
|
||||||
filteredPosts.map((post) => (
|
filteredPosts.map((post) => (
|
||||||
<Link key={post.id} href={`/post/${post.id}`} className="block">
|
<Link key={post.id} href={`/post/${post.id}`} className="block">
|
||||||
<Card className="hover:shadow-md transition-shadow gap-4">
|
<Card className="shadow-sm border-border/80 gap-4">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Avatar className="h-9 w-9">
|
<Avatar className="h-9 w-9">
|
||||||
@@ -142,7 +144,9 @@ export default function CommunityPage() {
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
<CardFooter className="text-sm text-muted-foreground gap-4">
|
<CardFooter className="text-sm text-muted-foreground gap-4">
|
||||||
<span className="flex items-center gap-1">
|
<span className="flex items-center gap-1">
|
||||||
<Heart className={`h-4 w-4 ${post.liked ? "fill-red-500 text-red-500" : ""}`} />
|
<Heart
|
||||||
|
className={`h-4 w-4 ${post.liked ? "fill-destructive text-destructive" : ""}`}
|
||||||
|
/>
|
||||||
{post.likeCount}
|
{post.likeCount}
|
||||||
</span>
|
</span>
|
||||||
<span className="flex items-center gap-1">
|
<span className="flex items-center gap-1">
|
||||||
|
|||||||
+18
-19
@@ -5,6 +5,7 @@ import { Badge } from "@/components/ui/badge"
|
|||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
|
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
|
||||||
import { IconInput } from "@/components/ui/icon-input"
|
import { IconInput } from "@/components/ui/icon-input"
|
||||||
|
import { StatusBadge } from "@/components/ui/status-badge"
|
||||||
import { listGames, listPlayers, listShops } from "@/lib/api"
|
import { listGames, listPlayers, listShops } from "@/lib/api"
|
||||||
import { toApiError } from "@/lib/errors"
|
import { toApiError } from "@/lib/errors"
|
||||||
import { GameIcon } from "@/lib/game-icons"
|
import { GameIcon } from "@/lib/game-icons"
|
||||||
@@ -55,10 +56,7 @@ export default function HomePage() {
|
|||||||
<section className="pb-8 pt-12 lg:pb-12 lg:pt-20 text-center">
|
<section className="pb-8 pt-12 lg:pb-12 lg:pt-20 text-center">
|
||||||
<div className="space-y-8 max-w-3xl mx-auto">
|
<div className="space-y-8 max-w-3xl mx-auto">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<h1
|
<h1 className="mb-3 text-3xl font-bold tracking-tight text-foreground lg:text-5xl">
|
||||||
className="mb-3 text-3xl font-bold tracking-tight text-foreground lg:text-5xl"
|
|
||||||
style={{ fontFamily: "'Space Grotesk', sans-serif" }}
|
|
||||||
>
|
|
||||||
找到你的<span className="text-primary">游戏搭档</span>
|
找到你的<span className="text-primary">游戏搭档</span>
|
||||||
</h1>
|
</h1>
|
||||||
<p className="mb-8 text-base text-muted-foreground lg:text-lg">
|
<p className="mb-8 text-base text-muted-foreground lg:text-lg">
|
||||||
@@ -74,7 +72,7 @@ export default function HomePage() {
|
|||||||
type="text"
|
type="text"
|
||||||
name="q"
|
name="q"
|
||||||
placeholder="搜索陪玩、店铺、游戏..."
|
placeholder="搜索陪玩、店铺、游戏..."
|
||||||
className="w-full border-border bg-card shadow-card transition-shadow focus:shadow-card-hover"
|
className="w-full border-border bg-card shadow-sm transition-shadow focus-visible:shadow-md"
|
||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -140,10 +138,7 @@ export default function HomePage() {
|
|||||||
{/* Players */}
|
{/* Players */}
|
||||||
{!loading && !loadingError
|
{!loading && !loadingError
|
||||||
? players.map((player) => (
|
? players.map((player) => (
|
||||||
<Card
|
<Card key={player.id} className="flex flex-col h-full border-border/80 shadow-sm">
|
||||||
key={player.id}
|
|
||||||
className="hover:shadow-md transition-shadow flex flex-col h-full border-muted/60"
|
|
||||||
>
|
|
||||||
<CardHeader className="flex flex-row items-center gap-3 space-y-0 pb-3">
|
<CardHeader className="flex flex-row items-center gap-3 space-y-0 pb-3">
|
||||||
<Avatar className="h-12 w-12">
|
<Avatar className="h-12 w-12">
|
||||||
<AvatarImage src={player.user.avatar} />
|
<AvatarImage src={player.user.avatar} />
|
||||||
@@ -153,22 +148,29 @@ export default function HomePage() {
|
|||||||
<CardTitle className="text-base">{player.user.nickname}</CardTitle>
|
<CardTitle className="text-base">{player.user.nickname}</CardTitle>
|
||||||
<div className="flex items-center gap-2 mt-1">
|
<div className="flex items-center gap-2 mt-1">
|
||||||
<div className="flex items-center text-sm">
|
<div className="flex items-center text-sm">
|
||||||
<Star className="h-3.5 w-3.5 fill-primary text-primary mr-0.5" />
|
<Star className="h-3.5 w-3.5 fill-warning text-warning mr-0.5" />
|
||||||
{player.rating}
|
{player.rating}
|
||||||
</div>
|
</div>
|
||||||
<span className="text-xs text-muted-foreground">
|
<span className="text-xs text-muted-foreground">
|
||||||
{player.totalOrders} 单
|
{player.totalOrders} 单
|
||||||
</span>
|
</span>
|
||||||
<Badge
|
<StatusBadge
|
||||||
variant={player.status === "available" ? "default" : "secondary"}
|
status={
|
||||||
|
player.status === "available"
|
||||||
|
? "success"
|
||||||
|
: player.status === "busy"
|
||||||
|
? "warning"
|
||||||
|
: "neutral"
|
||||||
|
}
|
||||||
className="text-[10px] px-1.5 py-0 font-normal"
|
className="text-[10px] px-1.5 py-0 font-normal"
|
||||||
|
icon={false}
|
||||||
>
|
>
|
||||||
{player.status === "available"
|
{player.status === "available"
|
||||||
? "可接单"
|
? "可接单"
|
||||||
: player.status === "busy"
|
: player.status === "busy"
|
||||||
? "忙碌"
|
? "忙碌"
|
||||||
: "离线"}
|
: "离线"}
|
||||||
</Badge>
|
</StatusBadge>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
@@ -208,7 +210,7 @@ export default function HomePage() {
|
|||||||
: null}
|
: null}
|
||||||
|
|
||||||
{/* Community Teaser */}
|
{/* Community Teaser */}
|
||||||
<Card className="hover:shadow-md transition-shadow flex flex-col h-full border-muted/60">
|
<Card className="flex flex-col h-full border-border/80 shadow-sm">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="text-lg">逛逛社区</CardTitle>
|
<CardTitle className="text-lg">逛逛社区</CardTitle>
|
||||||
<p className="text-sm text-muted-foreground">发现更多有趣的游戏日常和讨论</p>
|
<p className="text-sm text-muted-foreground">发现更多有趣的游戏日常和讨论</p>
|
||||||
@@ -228,10 +230,7 @@ export default function HomePage() {
|
|||||||
{/* Shops */}
|
{/* Shops */}
|
||||||
{!loading && !loadingError
|
{!loading && !loadingError
|
||||||
? shops.map((shop) => (
|
? shops.map((shop) => (
|
||||||
<Card
|
<Card key={shop.id} className="flex flex-col h-full border-border/80 shadow-sm">
|
||||||
key={shop.id}
|
|
||||||
className="hover:shadow-md transition-shadow flex flex-col h-full border-muted/60"
|
|
||||||
>
|
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="text-lg">{shop.name}</CardTitle>
|
<CardTitle className="text-lg">{shop.name}</CardTitle>
|
||||||
<p className="text-sm text-muted-foreground">{shop.description}</p>
|
<p className="text-sm text-muted-foreground">{shop.description}</p>
|
||||||
@@ -239,7 +238,7 @@ export default function HomePage() {
|
|||||||
<CardContent className="flex-grow">
|
<CardContent className="flex-grow">
|
||||||
<div className="flex items-center gap-4 text-sm">
|
<div className="flex items-center gap-4 text-sm">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<Star className="h-3.5 w-3.5 fill-primary text-primary mr-0.5" />
|
<Star className="h-3.5 w-3.5 fill-warning text-warning mr-0.5" />
|
||||||
{shop.rating}
|
{shop.rating}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center text-muted-foreground">
|
<div className="flex items-center text-muted-foreground">
|
||||||
|
|||||||
+46
-68
@@ -5,6 +5,7 @@ import { Badge } from "@/components/ui/badge"
|
|||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Card, CardContent, CardFooter, CardHeader } from "@/components/ui/card"
|
import { Card, CardContent, CardFooter, CardHeader } from "@/components/ui/card"
|
||||||
import { Checkbox } from "@/components/ui/checkbox"
|
import { Checkbox } from "@/components/ui/checkbox"
|
||||||
|
import { EmptyState } from "@/components/ui/empty-state"
|
||||||
import { IconInput } from "@/components/ui/icon-input"
|
import { IconInput } from "@/components/ui/icon-input"
|
||||||
import { Input } from "@/components/ui/input"
|
import { Input } from "@/components/ui/input"
|
||||||
import { Label } from "@/components/ui/label"
|
import { Label } from "@/components/ui/label"
|
||||||
@@ -26,6 +27,7 @@ import {
|
|||||||
SheetTitle,
|
SheetTitle,
|
||||||
SheetTrigger,
|
SheetTrigger,
|
||||||
} from "@/components/ui/sheet"
|
} from "@/components/ui/sheet"
|
||||||
|
import { StatusBadge } from "@/components/ui/status-badge"
|
||||||
import { Switch } from "@/components/ui/switch"
|
import { Switch } from "@/components/ui/switch"
|
||||||
import { listGames } from "@/lib/api"
|
import { listGames } from "@/lib/api"
|
||||||
import { searchCatalog } from "@/lib/api/search"
|
import { searchCatalog } from "@/lib/api/search"
|
||||||
@@ -33,18 +35,7 @@ import { GameIcon } from "@/lib/game-icons"
|
|||||||
import type { SearchResponse, SearchResultItem, SearchSort } from "@/lib/search/types"
|
import type { SearchResponse, SearchResultItem, SearchSort } from "@/lib/search/types"
|
||||||
import type { Game, Player } from "@/lib/types"
|
import type { Game, Player } from "@/lib/types"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import {
|
import { Filter, Gamepad2, Search, SlidersHorizontal, Star, Store, User } from "lucide-react"
|
||||||
CheckCircle2,
|
|
||||||
Clock,
|
|
||||||
Filter,
|
|
||||||
Gamepad2,
|
|
||||||
Search,
|
|
||||||
SlidersHorizontal,
|
|
||||||
Star,
|
|
||||||
Store,
|
|
||||||
User,
|
|
||||||
XCircle,
|
|
||||||
} from "lucide-react"
|
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
import { useRouter, useSearchParams } from "next/navigation"
|
import { useRouter, useSearchParams } from "next/navigation"
|
||||||
import { Suspense, useCallback, useEffect, useState } from "react"
|
import { Suspense, useCallback, useEffect, useState } from "react"
|
||||||
@@ -70,34 +61,6 @@ function resetPagination(params: URLSearchParams) {
|
|||||||
params.set("offset", "0")
|
params.set("offset", "0")
|
||||||
}
|
}
|
||||||
|
|
||||||
function StatusBadge({ status }: { status: Player["status"] }) {
|
|
||||||
switch (status) {
|
|
||||||
case "available":
|
|
||||||
return (
|
|
||||||
<Badge variant="outline" className="bg-green-50 text-green-700 border-green-200 gap-1">
|
|
||||||
<CheckCircle2 className="w-3 h-3" />
|
|
||||||
可接单
|
|
||||||
</Badge>
|
|
||||||
)
|
|
||||||
case "busy":
|
|
||||||
return (
|
|
||||||
<Badge variant="outline" className="bg-yellow-50 text-yellow-700 border-yellow-200 gap-1">
|
|
||||||
<Clock className="w-3 h-3" />
|
|
||||||
忙碌中
|
|
||||||
</Badge>
|
|
||||||
)
|
|
||||||
case "offline":
|
|
||||||
return (
|
|
||||||
<Badge variant="outline" className="bg-gray-50 text-gray-500 border-gray-200 gap-1">
|
|
||||||
<XCircle className="w-3 h-3" />
|
|
||||||
离线
|
|
||||||
</Badge>
|
|
||||||
)
|
|
||||||
default:
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function PlayerCard({ player }: { player: Player }) {
|
function PlayerCard({ player }: { player: Player }) {
|
||||||
const minPrice =
|
const minPrice =
|
||||||
!player.services || player.services.length === 0
|
!player.services || player.services.length === 0
|
||||||
@@ -111,7 +74,7 @@ function PlayerCard({ player }: { player: Player }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Link href={`/player/${player.id}`} className="block h-full">
|
<Link href={`/player/${player.id}`} className="block h-full">
|
||||||
<Card className="h-full overflow-hidden flex flex-col p-0 gap-0">
|
<Card className="h-full overflow-hidden flex flex-col p-0 gap-0 shadow-sm border-border/80">
|
||||||
<CardHeader className="p-4 pb-2 flex flex-row items-start justify-between space-y-0">
|
<CardHeader className="p-4 pb-2 flex flex-row items-start justify-between space-y-0">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Avatar className="h-12 w-12 border-2 border-background shadow-sm">
|
<Avatar className="h-12 w-12 border-2 border-background shadow-sm">
|
||||||
@@ -122,26 +85,43 @@ function PlayerCard({ player }: { player: Player }) {
|
|||||||
<h3 className="font-semibold text-base leading-none mb-1">{player.user.nickname}</h3>
|
<h3 className="font-semibold text-base leading-none mb-1">{player.user.nickname}</h3>
|
||||||
<div className="flex items-center gap-1 text-xs text-muted-foreground">
|
<div className="flex items-center gap-1 text-xs text-muted-foreground">
|
||||||
{player.shopName ? (
|
{player.shopName ? (
|
||||||
<span className="flex items-center gap-0.5 text-blue-600 bg-blue-50 px-1.5 py-0.5 rounded-full">
|
<Badge variant="info" className="gap-0.5 px-1.5 py-0.5 rounded-full font-normal">
|
||||||
<Store className="w-3 h-3" />
|
<Store className="w-3 h-3" />
|
||||||
{player.shopName}
|
{player.shopName}
|
||||||
</span>
|
</Badge>
|
||||||
) : (
|
) : (
|
||||||
<span className="flex items-center gap-0.5 text-gray-600 bg-gray-100 px-1.5 py-0.5 rounded-full">
|
<Badge
|
||||||
|
variant="neutral"
|
||||||
|
className="gap-0.5 px-1.5 py-0.5 rounded-full font-normal"
|
||||||
|
>
|
||||||
<User className="w-3 h-3" />
|
<User className="w-3 h-3" />
|
||||||
个人
|
个人
|
||||||
</span>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<StatusBadge status={player.status} />
|
<StatusBadge
|
||||||
|
status={
|
||||||
|
player.status === "available"
|
||||||
|
? "success"
|
||||||
|
: player.status === "busy"
|
||||||
|
? "warning"
|
||||||
|
: "neutral"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{player.status === "available"
|
||||||
|
? "可接单"
|
||||||
|
: player.status === "busy"
|
||||||
|
? "忙碌中"
|
||||||
|
: "离线"}
|
||||||
|
</StatusBadge>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<CardContent className="p-4 pt-2 flex-grow">
|
<CardContent className="p-4 pt-2 flex-grow">
|
||||||
<div className="flex items-center gap-4 mb-3 text-sm">
|
<div className="flex items-center gap-4 mb-3 text-sm">
|
||||||
<div className="flex items-center gap-1 text-yellow-500 font-medium">
|
<div className="flex items-center gap-1 text-warning font-medium">
|
||||||
<Star className="w-4 h-4 fill-current" />
|
<Star className="w-4 h-4 fill-warning text-warning" />
|
||||||
{player.rating.toFixed(1)}
|
{player.rating.toFixed(1)}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-muted-foreground">接单 {player.totalOrders}</div>
|
<div className="text-muted-foreground">接单 {player.totalOrders}</div>
|
||||||
@@ -194,7 +174,7 @@ type ShopSearchItem = Extract<SearchResultItem, { type: "shop" }>
|
|||||||
function ShopCard({ item }: { item: ShopSearchItem }) {
|
function ShopCard({ item }: { item: ShopSearchItem }) {
|
||||||
return (
|
return (
|
||||||
<Link href={`/shop/${item.shop.id}`} className="block h-full">
|
<Link href={`/shop/${item.shop.id}`} className="block h-full">
|
||||||
<Card className="h-full overflow-hidden flex flex-col p-0 gap-0">
|
<Card className="h-full overflow-hidden flex flex-col p-0 gap-0 shadow-sm border-border/80">
|
||||||
<CardHeader className="p-4 pb-2 flex flex-row items-start justify-between space-y-0">
|
<CardHeader className="p-4 pb-2 flex flex-row items-start justify-between space-y-0">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Avatar className="h-12 w-12 border-2 border-background shadow-sm">
|
<Avatar className="h-12 w-12 border-2 border-background shadow-sm">
|
||||||
@@ -204,20 +184,22 @@ function ShopCard({ item }: { item: ShopSearchItem }) {
|
|||||||
<div>
|
<div>
|
||||||
<h3 className="font-semibold text-base leading-none mb-1">{item.shop.name}</h3>
|
<h3 className="font-semibold text-base leading-none mb-1">{item.shop.name}</h3>
|
||||||
<div className="flex items-center gap-1 text-xs text-muted-foreground">
|
<div className="flex items-center gap-1 text-xs text-muted-foreground">
|
||||||
<span className="flex items-center gap-0.5 text-blue-600 bg-blue-50 px-1.5 py-0.5 rounded-full">
|
<Badge variant="info" className="gap-0.5 px-1.5 py-0.5 rounded-full font-normal">
|
||||||
<Store className="w-3 h-3" />
|
<Store className="w-3 h-3" />
|
||||||
店铺
|
店铺
|
||||||
</span>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<StatusBadge status={item.hasAvailable ? "available" : "busy"} />
|
<StatusBadge status={item.hasAvailable ? "success" : "warning"}>
|
||||||
|
{item.hasAvailable ? "可接单" : "忙碌中"}
|
||||||
|
</StatusBadge>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<CardContent className="p-4 pt-2 flex-grow">
|
<CardContent className="p-4 pt-2 flex-grow">
|
||||||
<div className="flex items-center gap-4 mb-3 text-sm">
|
<div className="flex items-center gap-4 mb-3 text-sm">
|
||||||
<div className="flex items-center gap-1 text-yellow-500 font-medium">
|
<div className="flex items-center gap-1 text-warning font-medium">
|
||||||
<Star className="w-4 h-4 fill-current" />
|
<Star className="w-4 h-4 fill-warning text-warning" />
|
||||||
{item.shop.rating}
|
{item.shop.rating}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-muted-foreground">接单 {item.shop.totalOrders}</div>
|
<div className="text-muted-foreground">接单 {item.shop.totalOrders}</div>
|
||||||
@@ -585,7 +567,7 @@ function SearchPageContent() {
|
|||||||
icon={<Search />}
|
icon={<Search />}
|
||||||
type="search"
|
type="search"
|
||||||
placeholder="搜索陪玩、游戏、标签..."
|
placeholder="搜索陪玩、游戏、标签..."
|
||||||
className="border-border bg-card shadow-card transition-shadow focus:shadow-card-hover"
|
className="border-border bg-card shadow-sm transition-shadow focus-visible:shadow-md"
|
||||||
value={searchQuery}
|
value={searchQuery}
|
||||||
onChange={(e) => setSearchQuery(e.target.value)}
|
onChange={(e) => setSearchQuery(e.target.value)}
|
||||||
/>
|
/>
|
||||||
@@ -730,24 +712,20 @@ function SearchPageContent() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-center py-20 bg-muted/30 rounded-lg border border-dashed">
|
<EmptyState
|
||||||
<div className="mx-auto w-12 h-12 rounded-full bg-muted flex items-center justify-center mb-4">
|
icon={Search}
|
||||||
<Search className="w-6 h-6 text-muted-foreground" />
|
title="未找到相关陪玩"
|
||||||
</div>
|
description={error ? "请求失败,请稍后重试" : "尝试调整筛选条件或更换搜索关键词"}
|
||||||
<h3 className="text-lg font-medium">未找到相关陪玩</h3>
|
action={
|
||||||
<p className="text-muted-foreground mt-1 max-w-sm mx-auto">
|
|
||||||
{error ? "请求失败,请稍后重试" : "尝试调整筛选条件或更换搜索关键词"}
|
|
||||||
</p>
|
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="mt-4 rounded-full"
|
className="rounded-full"
|
||||||
onClick={() => {
|
onClick={() => clearAllFilters()}
|
||||||
clearAllFilters()
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
清除所有筛选
|
清除所有筛选
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{canLoadMore && (
|
{canLoadMore && (
|
||||||
|
|||||||
Reference in New Issue
Block a user