fix(ui): unify layout wrappers and simplify player/shop detail pages
This commit is contained in:
+18
-10
@@ -14,7 +14,7 @@ import {
|
||||
} from "lucide-react"
|
||||
import Link from "next/link"
|
||||
import { useRouter, useSearchParams } from "next/navigation"
|
||||
import { Suspense, useEffect, useMemo, useState } from "react"
|
||||
import { Suspense, useEffect, useMemo, useState, useDeferredValue } from "react"
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Button } from "@/components/ui/button"
|
||||
@@ -309,7 +309,14 @@ function FilterSection({
|
||||
<Separator />
|
||||
|
||||
<div className="space-y-3">
|
||||
<h3 className="font-medium text-sm">价格区间 (元)</h3>
|
||||
<h3 className="font-medium text-sm flex items-center gap-2">
|
||||
价格区间 (元)
|
||||
{(priceRange.min || priceRange.max) && (
|
||||
<Badge variant="secondary" className="text-[10px] px-1.5 py-0 font-normal">
|
||||
¥{priceRange.min || "-"} - ¥{priceRange.max || "-"}
|
||||
</Badge>
|
||||
)}
|
||||
</h3>
|
||||
<div className="flex items-center gap-2">
|
||||
<Input
|
||||
type="number"
|
||||
@@ -381,6 +388,7 @@ function SearchPageContent() {
|
||||
min: "",
|
||||
max: "",
|
||||
})
|
||||
const deferredPriceRange = useDeferredValue(priceRange)
|
||||
const [onlyOnline, setOnlyOnline] = useState(false)
|
||||
const [minRating, setMinRating] = useState("0")
|
||||
const [sortBy, setSortBy] = useState("composite")
|
||||
@@ -445,12 +453,12 @@ function SearchPageContent() {
|
||||
if (!hasGame) return false
|
||||
}
|
||||
|
||||
const minP = priceRange.min ? Number(priceRange.min) : 0
|
||||
const maxP = priceRange.max ? Number(priceRange.max) : Infinity
|
||||
const minP = deferredPriceRange.min ? Number(deferredPriceRange.min) : 0
|
||||
const maxP = deferredPriceRange.max ? Number(deferredPriceRange.max) : Infinity
|
||||
const playerMinPrice = Math.min(...player.services.map((s) => s.price))
|
||||
|
||||
if (playerMinPrice < minP) return false
|
||||
if (priceRange.max && playerMinPrice > maxP) return false
|
||||
if (deferredPriceRange.max && playerMinPrice > maxP) return false
|
||||
|
||||
if (onlyOnline && player.status !== "available") return false
|
||||
|
||||
@@ -458,7 +466,7 @@ function SearchPageContent() {
|
||||
|
||||
return true
|
||||
})
|
||||
}, [minRating, onlyOnline, players, priceRange, searchQuery, selectedGames])
|
||||
}, [minRating, onlyOnline, players, deferredPriceRange, searchQuery, selectedGames])
|
||||
|
||||
const filteredShops = useMemo(() => {
|
||||
return shopResultItems.filter((item) => {
|
||||
@@ -475,17 +483,17 @@ function SearchPageContent() {
|
||||
if (!hasGame) return false
|
||||
}
|
||||
|
||||
const minP = priceRange.min ? Number(priceRange.min) : 0
|
||||
const maxP = priceRange.max ? Number(priceRange.max) : Infinity
|
||||
const minP = deferredPriceRange.min ? Number(deferredPriceRange.min) : 0
|
||||
const maxP = deferredPriceRange.max ? Number(deferredPriceRange.max) : Infinity
|
||||
if (item.minPrice < minP) return false
|
||||
if (priceRange.max && item.minPrice > maxP) return false
|
||||
if (deferredPriceRange.max && item.minPrice > maxP) return false
|
||||
|
||||
if (onlyOnline && !item.hasAvailable) return false
|
||||
if (item.shop.rating < Number(minRating)) return false
|
||||
|
||||
return true
|
||||
})
|
||||
}, [shopResultItems, searchQuery, selectedGames, priceRange, onlyOnline, minRating])
|
||||
}, [shopResultItems, searchQuery, selectedGames, deferredPriceRange, onlyOnline, minRating])
|
||||
|
||||
const sortedResults = useMemo<SearchResult[]>(() => {
|
||||
const playerResults: SearchResult[] = filteredPlayers.map((player) => ({
|
||||
|
||||
Reference in New Issue
Block a user