"use client"; import { useMemo, useState, useEffect } from "react"; import { useRouter, useSearchParams } from "next/navigation"; import { Search, X, Heart } from "lucide-react"; import type { GameCard as GameCardData } from "@spinza/shared"; import { useSession } from "@/lib/store"; import { cn } from "@/lib/utils"; import { Button, Empty } from "@/components/ui"; import { GameCard } from "./game-card"; const FILTERS = [ { key: "all", label: "All" }, { key: "featured", label: "Featured" }, { key: "new", label: "New" }, { key: "high", label: "High volatility" }, { key: "relaxed", label: "Relaxed" }, { key: "jackpot", label: "Jackpot" }, { key: "risk", label: "Risk · Cash out" }, { key: "originals", label: "Beyond Slots" }, { key: "favourites", label: "Favourites" }, ] as const; type FilterKey = (typeof FILTERS)[number]["key"]; const isFilter = (v: string | null): v is FilterKey => !!v && FILTERS.some((f) => f.key === v); export function GamesBrowser({ games }: { games: GameCardData[] }) { const params = useSearchParams(); const router = useRouter(); const status = useSession((s) => s.status); const [filter, setFilter] = useState(isFilter(params.get("filter")) ? (params.get("filter") as FilterKey) : "all"); const [query, setQuery] = useState(params.get("q") ?? ""); const [favs, setFavs] = useState>(() => Object.fromEntries(games.map((g) => [g.slug, !!g.favorite]))); useEffect(() => { const p = new URLSearchParams(); if (filter !== "all") p.set("filter", filter); if (query.trim()) p.set("q", query.trim()); const qs = p.toString(); router.replace(qs ? `/games?${qs}` : "/games", { scroll: false }); }, [filter, query, router]); const list = useMemo(() => { const q = query.trim().toLowerCase(); return games .filter((g) => { switch (filter) { case "featured": return g.isFeatured; case "new": return g.isNew; case "high": return g.volatility === "high" || g.volatility === "extreme"; case "relaxed": return g.volatility === "low" || g.volatility === "medium"; case "jackpot": return g.isJackpot; case "risk": return g.kind === "crash"; case "originals": return g.kind === "arcade"; case "favourites": return favs[g.slug]; default: return true; } }) .filter((g) => !q || g.name.toLowerCase().includes(q) || g.tagline.toLowerCase().includes(q) || g.theme.toLowerCase().includes(q) || g.tags.some((t) => t.includes(q)) || g.features.some((f) => f.toLowerCase().includes(q))); }, [games, filter, query, favs]); const counts = useMemo>( () => ({ all: games.length, featured: games.filter((g) => g.isFeatured).length, new: games.filter((g) => g.isNew).length, high: games.filter((g) => g.volatility === "high" || g.volatility === "extreme").length, relaxed: games.filter((g) => g.volatility === "low" || g.volatility === "medium").length, jackpot: games.filter((g) => g.isJackpot).length, risk: games.filter((g) => g.kind === "crash").length, originals: games.filter((g) => g.kind === "arcade").length, favourites: Object.values(favs).filter(Boolean).length, }), [games, favs], ); return (
{FILTERS.map((f) => ( ))}
{filter === "favourites" && status !== "authenticated" ? ( } action={} /> ) : list.length ? (
{list.map((g) => ( setFavs((f) => ({ ...f, [slug]: fav }))} /> ))}
) : ( : } action={ } /> )}
); }