144 lines
4.9 KiB
TypeScript
144 lines
4.9 KiB
TypeScript
import Link from "next/link"
|
|
import { Button } from "@/components/ui/button"
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
|
import { getApiUrl } from "@/lib/api-config"
|
|
|
|
interface Vertical {
|
|
id: number
|
|
name: string
|
|
slug: string
|
|
description: string | null
|
|
}
|
|
|
|
interface Scene {
|
|
id: number
|
|
name: string
|
|
slug: string
|
|
description: string | null
|
|
}
|
|
|
|
async function getVerticals(): Promise<Vertical[]> {
|
|
try {
|
|
const res = await fetch(`${getApiUrl()}/verticals`, { next: { revalidate: 60 } })
|
|
if (!res.ok) return []
|
|
return res.json()
|
|
} catch {
|
|
return []
|
|
}
|
|
}
|
|
|
|
async function getScenes(): Promise<Scene[]> {
|
|
try {
|
|
const res = await fetch(`${getApiUrl()}/verticals/scenes`, { next: { revalidate: 60 } })
|
|
if (!res.ok) return []
|
|
return res.json()
|
|
} catch {
|
|
return []
|
|
}
|
|
}
|
|
|
|
export default async function HomePage() {
|
|
const [verticals, scenes] = await Promise.all([getVerticals(), getScenes()])
|
|
|
|
return (
|
|
<div className="space-y-16">
|
|
{/* Hero Section */}
|
|
<section className="text-center py-16 space-y-6">
|
|
<h1 className="text-5xl font-bold tracking-tight">
|
|
Fediversion
|
|
</h1>
|
|
<p className="text-xl text-muted-foreground max-w-2xl mx-auto">
|
|
The unified platform for the entire jam scene.
|
|
One account, all your favorite bands.
|
|
</p>
|
|
<div className="flex justify-center gap-4">
|
|
<Button asChild size="lg">
|
|
<Link href="/onboarding">Get Started</Link>
|
|
</Button>
|
|
<Button asChild variant="outline" size="lg">
|
|
<Link href="/billy-strings">Explore Shows</Link>
|
|
</Button>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Scenes Section */}
|
|
{scenes.length > 0 && (
|
|
<section className="space-y-6">
|
|
<h2 className="text-2xl font-bold text-center">Browse by Scene</h2>
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 max-w-3xl mx-auto">
|
|
{scenes.map((scene) => (
|
|
<Link
|
|
key={scene.slug}
|
|
href={`/?scene=${scene.slug}`}
|
|
className="block p-4 rounded-lg border bg-card hover:bg-accent transition-colors text-center"
|
|
>
|
|
<div className="font-semibold">{scene.name}</div>
|
|
{scene.description && (
|
|
<div className="text-sm text-muted-foreground mt-1 line-clamp-2">
|
|
{scene.description}
|
|
</div>
|
|
)}
|
|
</Link>
|
|
))}
|
|
</div>
|
|
</section>
|
|
)}
|
|
|
|
{/* Bands Grid */}
|
|
<section className="space-y-6">
|
|
<h2 className="text-2xl font-bold text-center">Featured Bands</h2>
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
{verticals.map((vertical) => (
|
|
<Card key={vertical.slug} className="hover:shadow-lg transition-shadow">
|
|
<CardHeader>
|
|
<CardTitle>
|
|
<Link href={`/${vertical.slug}`} className="hover:underline">
|
|
{vertical.name}
|
|
</Link>
|
|
</CardTitle>
|
|
{vertical.description && (
|
|
<CardDescription>{vertical.description}</CardDescription>
|
|
)}
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="flex gap-2">
|
|
<Button asChild variant="outline" size="sm">
|
|
<Link href={`/${vertical.slug}/shows`}>Shows</Link>
|
|
</Button>
|
|
<Button asChild variant="outline" size="sm">
|
|
<Link href={`/${vertical.slug}/songs`}>Songs</Link>
|
|
</Button>
|
|
<Button asChild variant="outline" size="sm">
|
|
<Link href={`/${vertical.slug}/venues`}>Venues</Link>
|
|
</Button>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
))}
|
|
</div>
|
|
</section>
|
|
|
|
{/* Stats Section */}
|
|
<section className="bg-muted/50 rounded-lg p-8 text-center space-y-4">
|
|
<h2 className="text-2xl font-bold">Join the Community</h2>
|
|
<p className="text-muted-foreground">
|
|
Track shows, rate performances, discover connections across bands.
|
|
</p>
|
|
<div className="grid grid-cols-3 gap-6 max-w-md mx-auto pt-4">
|
|
<div>
|
|
<div className="text-3xl font-bold">{verticals.length}</div>
|
|
<div className="text-sm text-muted-foreground">Bands</div>
|
|
</div>
|
|
<div>
|
|
<div className="text-3xl font-bold">{scenes.length}</div>
|
|
<div className="text-sm text-muted-foreground">Scenes</div>
|
|
</div>
|
|
<div>
|
|
<div className="text-3xl font-bold">1</div>
|
|
<div className="text-sm text-muted-foreground">Account</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
)
|
|
}
|