feat: 创建房间时支持自定义筛选条件(距离/人均/菜系)

替换硬编码搜索参数,用户可选择距离范围(1/3/5km)、
人均价格区间(50以下/50-100/100+)和菜系偏好(火锅、
日料、烧烤等),直接提升推荐质量。
This commit is contained in:
2026-02-24 18:29:38 +08:00
parent 059c009a8b
commit d83e5ec6c4
2 changed files with 126 additions and 5 deletions
+84 -1
View File
@@ -17,6 +17,21 @@ interface LocationSuggestion {
const SHANGHAI_COORDS = { lat: 31.2222, lng: 121.4764 };
const DISTANCE_OPTIONS = [
{ label: "1km", value: 1000 },
{ label: "3km", value: 3000 },
{ label: "5km", value: 5000 },
] as const;
const PRICE_OPTIONS = [
{ label: "不限", value: "any" },
{ label: "¥50以下", value: "under50" },
{ label: "¥50-100", value: "50to100" },
{ label: "¥100+", value: "over100" },
] as const;
const CUISINE_OPTIONS = ["不限", "火锅", "日料", "烧烤", "西餐", "川菜", "粤菜", "东南亚"] as const;
function getLocation(): Promise<{ lat: number; lng: number }> {
if (process.env.NODE_ENV === "development") {
return Promise.resolve(SHANGHAI_COORDS);
@@ -49,6 +64,9 @@ export default function LandingPage() {
const [showSuggestions, setShowSuggestions] = useState(false);
const [selectedLocation, setSelectedLocation] = useState<LocationSuggestion | null>(null);
const [fetchingSuggestions, setFetchingSuggestions] = useState(false);
const [radius, setRadius] = useState(3000);
const [priceRange, setPriceRange] = useState("any");
const [cuisine, setCuisine] = useState("不限");
const suggestRef = useRef<HTMLDivElement>(null);
const debounceRef = useRef<ReturnType<typeof setTimeout>>(null);
@@ -132,7 +150,7 @@ export default function LandingPage() {
const res = await fetch("/api/room/create", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(coords),
body: JSON.stringify({ ...coords, radius, priceRange, cuisine }),
});
if (!res.ok) {
@@ -304,6 +322,71 @@ export default function LandingPage() {
</AnimatePresence>
</div>
<div className="flex flex-col gap-2 rounded-xl border border-zinc-100 bg-zinc-50/50 px-3 py-2.5">
<div className="flex items-center gap-3">
<span className="w-8 shrink-0 text-xs font-medium text-zinc-400"></span>
<div className="flex gap-1.5">
{DISTANCE_OPTIONS.map((opt) => (
<button
key={opt.value}
type="button"
onClick={() => setRadius(opt.value)}
disabled={loading}
className={`h-7 rounded-full px-3 text-xs font-medium transition-colors disabled:opacity-50 ${
radius === opt.value
? "bg-emerald-500 text-white shadow-sm"
: "bg-white text-zinc-500 hover:bg-zinc-200"
}`}
>
{opt.label}
</button>
))}
</div>
</div>
<div className="flex items-center gap-3">
<span className="w-8 shrink-0 text-xs font-medium text-zinc-400"></span>
<div className="flex flex-wrap gap-1.5">
{PRICE_OPTIONS.map((opt) => (
<button
key={opt.value}
type="button"
onClick={() => setPriceRange(opt.value)}
disabled={loading}
className={`h-7 rounded-full px-3 text-xs font-medium transition-colors disabled:opacity-50 ${
priceRange === opt.value
? "bg-emerald-500 text-white shadow-sm"
: "bg-white text-zinc-500 hover:bg-zinc-200"
}`}
>
{opt.label}
</button>
))}
</div>
</div>
<div className="flex items-start gap-3">
<span className="w-8 shrink-0 pt-1.5 text-xs font-medium text-zinc-400"></span>
<div className="flex flex-wrap gap-1.5">
{CUISINE_OPTIONS.map((opt) => (
<button
key={opt}
type="button"
onClick={() => setCuisine(opt)}
disabled={loading}
className={`h-7 rounded-full px-3 text-xs font-medium transition-colors disabled:opacity-50 ${
cuisine === opt
? "bg-emerald-500 text-white shadow-sm"
: "bg-white text-zinc-500 hover:bg-zinc-200"
}`}
>
{opt}
</button>
))}
</div>
</div>
</div>
<button
onClick={handleCreate}
disabled={loading}