"use client" import { useEffect, useState, Suspense } from "react" import { getApiUrl } from "@/lib/api-config" import { Loader2, Music2 } from "lucide-react" import { useSearchParams, useRouter, usePathname } from "next/navigation" import { Button } from "@/components/ui/button" import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs" import { DateGroupedList } from "@/components/shows/date-grouped-list" import { FilterPills } from "@/components/shows/filter-pills" import { BandGrid } from "@/components/shows/band-grid" import { Show, Vertical, PaginatedResponse, Venue } from "@/types/models" function ShowsContent() { const searchParams = useSearchParams() const router = useRouter() const pathname = usePathname() // --- State --- const activeView = searchParams.get("view") || "recent" const bandsParam = searchParams.get("bands") const selectedBands = bandsParam ? bandsParam.split(",") : [] const [shows, setShows] = useState([]) const [verticals, setVerticals] = useState([]) const [loading, setLoading] = useState(true) const [loadingVerticals, setLoadingVerticals] = useState(true) // --- Data Fetching: Verticals (Always) --- useEffect(() => { setLoadingVerticals(true) fetch(`${getApiUrl()}/verticals/`) .then(res => { if (!res.ok) throw new Error("Failed to fetch verticals") return res.json() }) .then(data => { setVerticals(data) setLoadingVerticals(false) }) .catch(err => { console.error(err) setLoadingVerticals(false) }) }, []) // --- Data Fetching: Shows (Dependent on View) --- useEffect(() => { if (activeView === "bands") { // Don't fetch shows if we are just browsing bands setLoading(false) return } setLoading(true) const params = new URLSearchParams() // Add band filters if (selectedBands.length > 0) { selectedBands.forEach(b => params.append("vertical_slugs", b)) } // Add view-specific params if (activeView === "upcoming") { params.set("status", "upcoming") } else if (activeView === "my-feed") { // My Feed implies specific tiers // We use the same tiers as FeedFilter used: HEADLINER, MAIN_STAGE, SUPPORTING ["HEADLINER", "MAIN_STAGE", "SUPPORTING"].forEach(t => params.append("tiers", t)) // Also we might want to default to "past" shows for feed? Or all? // "My Feed" usually means recent updates. // Let's explicitly ask for "past" shows (recent history) unless user wants upcoming feed? // For now, let's show PAST shows in My Feed (History), maybe add Upcoming toggle later? // Or just show all? `read_shows` sorts by date desc. // Let's default to Recent (Past) for Feed. // params.set("status", "past") // Actually, if we leave status blank, it returns all (sorted by date desc if modified, but check `read_shows`) // `read_shows` default sorts DESC. // Let's assume user wants recent feed. } else { // Recent (Default) params.set("status", "past") } fetch(`${getApiUrl()}/shows/?${params.toString()}`) .then(res => { // If 401 (Unauthorized) for My Feed, we might get empty list or error if (res.status === 401 && activeView === "my-feed") { return { data: [] as Show[], meta: { total: 0, limit: 0, offset: 0 } } } if (!res.ok) throw new Error("Failed to fetch shows") return res.json() }) .then((data: PaginatedResponse) => { setShows(data.data || []) setLoading(false) }) .catch(err => { console.error(err) setShows([]) // Clear on error setLoading(false) }) }, [activeView, bandsParam]) // bandsParam is the dependency // --- Handlers --- const updateUrl = (view: string, bands: string[]) => { const params = new URLSearchParams() if (view !== "recent") params.set("view", view) if (bands.length > 0) params.set("bands", bands.join(",")) // Push state router.push(`${pathname}${params.toString() ? `?${params.toString()}` : ''}`) } const handleTabChange = (val: string) => { updateUrl(val, selectedBands) } const handleToggleBand = (slug: string) => { let newBands = [...selectedBands] if (newBands.includes(slug)) { newBands = newBands.filter(b => b !== slug) } else { newBands.push(slug) } // If we are on "bands" tab and select a band, switch to "recent" to show results? // User plan says: "Clicking a band adds it to the active filter and switches to 'Recent' view." if (activeView === "bands" && !selectedBands.includes(slug)) { updateUrl("recent", newBands) } else { // Otherwise just update filters (e.g. if unchecking, stay on grid? or if adding from elsewhere?) // If checking from grid -> go to recent. // If unchecking -> stay? // Let's just follow the rule: Select -> Go to Recent. Unselect -> Stay. if (!selectedBands.includes(slug)) { updateUrl("recent", newBands) } else { updateUrl(activeView, newBands) } } } const handleRemoveBand = (slug: string) => { const newBands = selectedBands.filter(b => b !== slug) updateUrl(activeView, newBands) } const handleClearBands = () => { updateUrl(activeView, []) } // --- Render Helpers --- const renderShowList = () => { if (loading) { return (
) } if (shows.length === 0) { return (

No shows found matching your criteria.

) } return } return (
Recent My Feed Upcoming By Band
{renderShowList()} {/* Maybe add auth check banner here if shows is empty and user not logged in? */} {/* For now, just render list */} {renderShowList()} {renderShowList()} {loadingVerticals ? (
) : ( )}
) } export default function ShowsPage() { return ( }> ) }