AudioForge / frontend /src /components /generations-list.tsx
OnyxlMunkey's picture
c618549
"use client";
import { useQuery } from "@tanstack/react-query";
import { generationsApi } from "@/lib/api";
import { GenerationCard } from "@/components/generation-card";
import { Loader2 } from "lucide-react";
export function GenerationsList() {
const { data, isLoading, error } = useQuery({
queryKey: ["generations"],
queryFn: () => generationsApi.list(1, 20),
refetchInterval: (query) => {
// Refetch if there are pending/processing generations
const hasActive = query.state.data?.items.some(
(item) => item.status === "pending" || item.status === "processing"
);
return hasActive ? 2000 : 10000; // Poll every 2s if active, 10s otherwise
},
});
if (isLoading) {
return (
<div className="flex flex-col items-center justify-center py-12 space-y-4">
<div className="relative">
<Loader2 className="h-12 w-12 animate-spin text-primary" />
<div className="absolute inset-0 h-12 w-12 rounded-full bg-primary/20 animate-ping" />
</div>
<p className="text-sm text-muted-foreground animate-pulse">
Loading your creations...
</p>
</div>
);
}
if (error) {
return (
<div className="text-center py-12 bg-destructive/10 border border-destructive/20 rounded-lg">
<div className="text-4xl mb-4">πŸ˜”</div>
<p className="text-lg font-semibold text-destructive mb-2">
Oops! Something went wrong
</p>
<p className="text-sm text-muted-foreground">
Failed to load generations. Please try again.
</p>
</div>
);
}
if (!data || data.items.length === 0) {
return (
<div className="text-center py-16 bg-gradient-to-br from-secondary/30 to-secondary/10 border border-dashed border-primary/30 rounded-lg">
<div className="text-6xl mb-4 animate-bounce-subtle">🎡</div>
<p className="text-2xl font-bold mb-2 bg-gradient-to-r from-primary to-purple-500 bg-clip-text text-transparent">
Your Canvas Awaits
</p>
<p className="text-muted-foreground mb-4">
No generations yet. Time to create your first masterpiece!
</p>
<div className="flex items-center justify-center gap-2 text-sm text-muted-foreground">
<span>πŸ‘ˆ</span>
<span>Start by describing your music on the left</span>
</div>
</div>
);
}
return (
<div className="space-y-4">
<div className="flex items-center gap-3 mb-6">
<div className="w-1 h-8 bg-gradient-to-b from-purple-500 to-primary rounded-full" />
<h2 className="font-display text-2xl font-bold">Your Creations</h2>
<div className="ml-auto px-3 py-1 bg-primary/10 rounded-full">
<span className="text-sm font-medium text-primary">
{data.items.length} track{data.items.length !== 1 ? 's' : ''}
</span>
</div>
</div>
<div className="space-y-3">
{data.items.map((generation, index) => (
<div
key={generation.id}
style={{ animationDelay: `${index * 50}ms` }}
className="animate-fade-in"
>
<GenerationCard generation={generation} />
</div>
))}
</div>
</div>
);
}