fediversion/frontend/components/ui/empty-state.tsx
fullsizemalt 99e5924588
Some checks failed
Deploy Fediversion / deploy (push) Failing after 1s
feat: Sprint 2 - empty states, discovery, attendance stats
- Add EmptyState component with 6 variants
- Add discover.py router with smart filtering
  - GET /discover/shows (year, venue, city, tour filters)
  - GET /discover/years
  - GET /discover/recent
- Add GET /attendance/me/stats (by vertical breakdown)
2025-12-28 16:49:24 -08:00

86 lines
2.8 KiB
TypeScript

"use client"
import Link from "next/link"
import { Button } from "@/components/ui/button"
import { Card, CardContent } from "@/components/ui/card"
import { Music, Users, Calendar, Star } from "lucide-react"
interface EmptyStateProps {
type: "shows" | "songs" | "attendance" | "feed" | "reviews" | "generic"
bandName?: string
}
const EMPTY_STATES = {
shows: {
icon: Calendar,
title: "No Shows Yet",
description: "Be the first to explore shows for this band!",
action: { label: "Browse All Bands", href: "/" }
},
songs: {
icon: Music,
title: "No Songs Found",
description: "Song data is still being imported.",
action: { label: "Check Back Soon", href: "/" }
},
attendance: {
icon: Users,
title: "No Shows Tracked",
description: "Start tracking your concert attendance!",
action: { label: "Find Shows", href: "/shows" }
},
feed: {
icon: Star,
title: "Your Feed is Empty",
description: "Follow some bands to see activity here.",
action: { label: "Pick Your Bands", href: "/onboarding" }
},
reviews: {
icon: Star,
title: "No Reviews Yet",
description: "Be the first to share your thoughts!",
action: null
},
generic: {
icon: Music,
title: "Nothing Here Yet",
description: "Check back soon for updates.",
action: { label: "Go Home", href: "/" }
}
}
export function EmptyState({ type, bandName }: EmptyStateProps) {
const config = EMPTY_STATES[type] || EMPTY_STATES.generic
const Icon = config.icon
return (
<Card className="border-dashed">
<CardContent className="flex flex-col items-center justify-center py-12 text-center">
<div className="rounded-full bg-muted p-4 mb-4">
<Icon className="h-8 w-8 text-muted-foreground" />
</div>
<h3 className="font-semibold text-lg mb-2">
{bandName ? `${config.title} for ${bandName}` : config.title}
</h3>
<p className="text-muted-foreground mb-4 max-w-sm">
{config.description}
</p>
{config.action && (
<Button asChild>
<Link href={config.action.href}>{config.action.label}</Link>
</Button>
)}
</CardContent>
</Card>
)
}
// Inline empty state for lists
export function EmptyListState({ message }: { message: string }) {
return (
<div className="flex flex-col items-center justify-center py-8 text-center text-muted-foreground">
<Music className="h-6 w-6 mb-2 opacity-50" />
<p>{message}</p>
</div>
)
}