Initial commit: AuroraMusic monorepo
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
"use client";
|
||||
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
import { api, type Song } from "@/lib/api";
|
||||
import { useAuth } from "@/lib/auth";
|
||||
import { SongCard } from "@/components/SongCard";
|
||||
|
||||
export default function LibraryPage() {
|
||||
const { user, loading } = useAuth();
|
||||
const router = useRouter();
|
||||
const [songs, setSongs] = useState<Song[] | null>(null);
|
||||
const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
||||
|
||||
const load = useCallback(async () => {
|
||||
const { items } = await api.mySongs();
|
||||
setSongs(items);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading && !user) router.push("/login");
|
||||
}, [loading, user, router]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!user) return;
|
||||
load();
|
||||
}, [user, load]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!songs) return;
|
||||
const hasActive = songs.some((s) => s.status === "pending" || s.status === "processing");
|
||||
if (hasActive && !pollRef.current) {
|
||||
pollRef.current = setInterval(load, 3000);
|
||||
} else if (!hasActive && pollRef.current) {
|
||||
clearInterval(pollRef.current);
|
||||
pollRef.current = null;
|
||||
}
|
||||
return () => {
|
||||
if (pollRef.current) {
|
||||
clearInterval(pollRef.current);
|
||||
pollRef.current = null;
|
||||
}
|
||||
};
|
||||
}, [songs, load]);
|
||||
|
||||
if (loading || !user) return null;
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-3xl px-6 py-16">
|
||||
<div className="flex items-center justify-between">
|
||||
<h1 className="text-3xl font-bold">Your library</h1>
|
||||
<Link
|
||||
href="/create"
|
||||
className="rounded-full bg-white px-4 py-2 text-sm font-semibold text-black hover:bg-white/90"
|
||||
>
|
||||
+ New song
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{songs === null ? (
|
||||
<p className="mt-10 text-white/50">Loading…</p>
|
||||
) : songs.length === 0 ? (
|
||||
<p className="mt-10 text-white/50">
|
||||
Nothing yet.{" "}
|
||||
<Link href="/create" className="underline">
|
||||
Generate your first song
|
||||
</Link>
|
||||
.
|
||||
</p>
|
||||
) : (
|
||||
<div className="mt-8 flex flex-col gap-4">
|
||||
{songs.map((song) => (
|
||||
<SongCard
|
||||
key={song.id}
|
||||
song={song}
|
||||
isOwner
|
||||
onChange={(updated) => setSongs((prev) => prev?.map((s) => (s.id === updated.id ? updated : s)) ?? null)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user