Initial commit: AuroraMusic monorepo

This commit is contained in:
Kris
2026-08-29 21:21:51 -05:00
commit 18f124a3d6
8881 changed files with 2283044 additions and 0 deletions
+85
View File
@@ -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>
);
}