"use client" import { useEffect, useState } from "react" import { useAuth } from "@/contexts/auth-context" import { useRouter } from "next/navigation" import { Card, CardContent } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Textarea } from "@/components/ui/textarea" import { Badge } from "@/components/ui/badge" import { Search, Edit, Save, X, Calendar, ExternalLink } from "lucide-react" import { getApiUrl } from "@/lib/api-config" import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, } from "@/components/ui/dialog" import { Label } from "@/components/ui/label" import Link from "next/link" interface Venue { name: string city?: string state?: string } interface Show { id: number date: string slug: string venue?: Venue notes: string | null nugs_link: string | null bandcamp_link: string | null youtube_link: string | null } export default function AdminShowsPage() { const { user, token, loading: authLoading } = useAuth() const router = useRouter() const [shows, setShows] = useState([]) const [loading, setLoading] = useState(true) const [search, setSearch] = useState("") const [editingShow, setEditingShow] = useState(null) const [saving, setSaving] = useState(false) useEffect(() => { if (authLoading) return if (!user) { router.push("/login") return } if (user.role !== "admin") { router.push("/") return } fetchShows() }, [user, router, authLoading]) const fetchShows = async () => { if (!token) return try { const res = await fetch(`${getApiUrl()}/shows?limit=100&sort=date_desc`, { headers: { Authorization: `Bearer ${token}` } }) if (res.ok) { const data = await res.json() setShows(data.shows || data) } } catch (e) { console.error("Failed to fetch shows", e) } finally { setLoading(false) } } const updateShow = async () => { if (!token || !editingShow) return setSaving(true) try { const res = await fetch(`${getApiUrl()}/admin/shows/${editingShow.id}`, { method: "PATCH", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` }, body: JSON.stringify({ notes: editingShow.notes, nugs_link: editingShow.nugs_link, bandcamp_link: editingShow.bandcamp_link, youtube_link: editingShow.youtube_link }) }) if (res.ok) { fetchShows() setEditingShow(null) } } catch (e) { console.error("Failed to update show", e) } finally { setSaving(false) } } const formatDate = (dateStr: string) => { return new Date(dateStr).toLocaleDateString("en-US", { year: "numeric", month: "short", day: "numeric" }) } const filteredShows = shows.filter(s => s.venue_name?.toLowerCase().includes(search.toLowerCase()) || s.venue_city?.toLowerCase().includes(search.toLowerCase()) || s.date.includes(search) ) if (loading) { return (
{[1, 2, 3].map(i =>
)}
) } return (

Show Management

setSearch(e.target.value)} className="pl-9" />
{filteredShows.slice(0, 50).map(show => ( ))}
Date Venue Links Actions
{formatDate(show.date)}

{show.venue?.name || "Unknown Venue"}

{show.venue?.city}{show.venue?.state ? `, ${show.venue.state}` : ""}

{show.nugs_link && Nugs} {show.bandcamp_link && BC} {show.youtube_link && YT} {!show.nugs_link && !show.bandcamp_link && !show.youtube_link && ( No links )}
{filteredShows.length === 0 && (
No shows found
)}
setEditingShow(null)}> Edit Show: {editingShow && formatDate(editingShow.date)} {editingShow && (