fediversion/frontend/components/bands/bands-grid.tsx
fullsizemalt e68486ddd2
Some checks failed
Deploy Fediversion / deploy (push) Failing after 1s
fix(nav): add /bands discovery page, fix Browse links to unified routes
2025-12-29 22:03:40 -08:00

108 lines
4.9 KiB
TypeScript

"use client"
import { useEffect, useState } from "react"
import Link from "next/link"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { getApiUrl } from "@/lib/api-config"
import { Loader2, ChevronRight, Music, Calendar, MapPin, ListMusic } from "lucide-react"
interface Vertical {
id: number
name: string
slug: string
description: string | null
color: string | null
show_count?: number
song_count?: number
venue_count?: number
}
export function BandsGrid() {
const [verticals, setVerticals] = useState<Vertical[]>([])
const [loading, setLoading] = useState(true)
useEffect(() => {
async function fetchVerticals() {
try {
const res = await fetch(`${getApiUrl()}/verticals`)
if (res.ok) {
const data = await res.json()
setVerticals(data)
}
} catch (error) {
console.error("Failed to fetch verticals", error)
} finally {
setLoading(false)
}
}
fetchVerticals()
}, [])
if (loading) {
return (
<div className="flex items-center justify-center min-h-[300px]">
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
</div>
)
}
return (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
{verticals.map((vertical) => (
<Link key={vertical.id} href={`/${vertical.slug}`} className="group">
<Card className="h-full transition-all duration-200 hover:scale-[1.02] hover:shadow-lg hover:border-primary/50">
<CardHeader className="pb-2">
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<div
className="w-12 h-12 rounded-lg flex items-center justify-center text-white font-bold text-lg"
style={{ backgroundColor: vertical.color || '#3B82F6' }}
>
{vertical.name.substring(0, 2).toUpperCase()}
</div>
<CardTitle className="text-xl group-hover:text-primary transition-colors">
{vertical.name}
</CardTitle>
</div>
<ChevronRight className="h-5 w-5 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" />
</div>
</CardHeader>
<CardContent>
{vertical.description && (
<p className="text-sm text-muted-foreground line-clamp-2 mb-4">
{vertical.description}
</p>
)}
<div className="flex flex-wrap gap-3 text-xs text-muted-foreground">
<Link
href={`/${vertical.slug}/shows`}
className="flex items-center gap-1 px-2 py-1 rounded-full bg-muted hover:bg-primary/10 hover:text-primary transition-colors"
onClick={(e) => e.stopPropagation()}
>
<Calendar className="h-3 w-3" />
Shows
</Link>
<Link
href={`/${vertical.slug}/songs`}
className="flex items-center gap-1 px-2 py-1 rounded-full bg-muted hover:bg-primary/10 hover:text-primary transition-colors"
onClick={(e) => e.stopPropagation()}
>
<ListMusic className="h-3 w-3" />
Songs
</Link>
<Link
href={`/${vertical.slug}/venues`}
className="flex items-center gap-1 px-2 py-1 rounded-full bg-muted hover:bg-primary/10 hover:text-primary transition-colors"
onClick={(e) => e.stopPropagation()}
>
<MapPin className="h-3 w-3" />
Venues
</Link>
</div>
</CardContent>
</Card>
</Link>
))}
</div>
)
}