import { Button } from "@/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { ArrowLeft, Calendar, MapPin, ChevronRight, ChevronLeft, Music, Clock, Hash, Play, ExternalLink, Sparkles, Youtube } from "lucide-react"
import Link from "next/link"
import { notFound } from "next/navigation"
import { getApiUrl } from "@/lib/api-config"
import { CommentSection } from "@/components/social/comment-section"
import { EntityReviews } from "@/components/reviews/entity-reviews"
import { SocialWrapper } from "@/components/social/social-wrapper"
import { EntityRating } from "@/components/social/entity-rating"
import { Badge } from "@/components/ui/badge"
import { YouTubeEmbed } from "@/components/ui/youtube-embed"
async function getPerformance(id: string) {
try {
const res = await fetch(`${getApiUrl()}/performances/${id}`, { cache: 'no-store' })
if (!res.ok) return null
return res.json()
} catch (e) {
console.error(e)
return null
}
}
export default async function PerformanceDetailPage({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params
const performance = await getPerformance(slug)
if (!performance) {
notFound()
}
const showDate = new Date(performance.show.date)
const formattedDate = showDate.toLocaleDateString("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric"
})
return (
{/* Hero Banner - Distinct from Song page */}
{/* Breadcrumbs */}
Show
{performance.song.title}
This Performance
{/* Context Badge */}
Specific Performance
{performance.is_heady && (
Heady Version
)}
{performance.rank && performance.total_versions && (
#{performance.rank} of {performance.total_versions}
)}
{performance.set_name && (
{performance.set_name}
)}
{performance.position && (
#{performance.position}
)}
{/* Song Title (links to song page) */}
{performance.song.title}
{/* Nicknames */}
{performance.nicknames && performance.nicknames.length > 0 && (
{performance.nicknames.map((nick: any) => (
"{nick.nickname}"
))}
)}
{/* Show Context - THE KEY DIFFERENTIATOR */}
{formattedDate}
{performance.show.venue && (
{performance.show.venue.name}, {performance.show.venue.city}
{performance.show.venue.state && `, ${performance.show.venue.state}`}
)}
{/* Rating Box */}
{/* Video Section - Show when performance has a video */}
{performance.youtube_link && (
Video
)}
{/* Version Navigation - Prominent */}
Version Timeline
{performance.previous_performance_id ? (
) : (
🎉 Debut Performance
)}
#{performance.times_played || "?"}
of all time
{performance.next_performance_id ? (
) : (
Most Recent
)}
{/* Notes & Details */}
{(performance.notes || performance.segue || performance.track_url) && (
About This Performance
{performance.notes && (
Notes
{performance.notes}
)}
{performance.segue && (
Segues into next song →
)}
{performance.track_url && (
Listen to this performance
)}
)}
{/* Comments */}
{/* Reviews */}
{/* Sidebar */}
{/* Quick Stats */}
Performance Stats
Set Position
{performance.set_name || "—"} #{performance.position || "—"}
Gap Since Last
{performance.gap !== undefined ? `${performance.gap} shows` : "—"}
Times Played
{performance.times_played || "—"}
{/* Top Rated Versions */}
{performance.other_performances && performance.other_performances.length > 0 && (
Top Rated Versions
{performance.other_performances.slice(0, 5).map((perf: any) => (
{new Date(perf.show_date).toLocaleDateString()}
{perf.venue_name}
{perf.avg_rating > 0 && (
★
{perf.avg_rating.toFixed(1)}
)}
))}
View all {performance.other_performances.length + 1} versions →
)}
{/* Quick Links */}
Related Pages
All versions of {performance.song.title}
Full show setlist
{performance.show.venue && (
{performance.show.venue.name}
)}
)
}