feat: artist discography page + wanted page

This commit is contained in:
Jonathan
2026-07-11 14:11:53 +02:00
parent f7135b9046
commit 7087b2780e
4 changed files with 159 additions and 0 deletions
@@ -0,0 +1,67 @@
"use client";
import { useEffect, useState } from "react";
type Release = {
id: string;
album: string;
primaryType: string | null;
secondaryTypes: string[];
firstReleaseDate: string | null;
monitored: boolean;
state: string;
currentQualityClass: number | null;
};
type Detail = { id: string; name: string; autoMonitorFuture: boolean; releases: Release[] };
function badge(r: Release): string {
if (r.currentQualityClass !== null) return `Have (q${r.currentQualityClass})`;
if (r.monitored) return r.state === "wanted" ? "Wanted" : r.state;
return "Dormant";
}
export function DiscographyClient({ id }: { id: string }) {
const [detail, setDetail] = useState<Detail | null>(null);
async function refresh() {
const res = await fetch(`/api/artists/${id}`);
setDetail(res.ok ? await res.json() : null);
}
useEffect(() => {
refresh();
}, [id]);
async function toggleMonitor(r: Release) {
await fetch(`/api/releases/${r.id}`, {
method: "PATCH",
headers: { "content-type": "application/json" },
body: JSON.stringify({ monitored: !r.monitored }),
});
refresh();
}
async function searchNow(r: Release) {
await fetch(`/api/releases/${r.id}/search`, { method: "POST" });
refresh();
}
if (!detail) return <p>Loading</p>;
return (
<div>
<h1>{detail.name}</h1>
<ul>
{detail.releases.map((r) => (
<li key={r.id}>
<strong>{r.album}</strong>
{r.firstReleaseDate ? ` (${r.firstReleaseDate.slice(0, 4)})` : ""}
{r.primaryType ? ` · ${r.primaryType}` : ""}
{r.secondaryTypes.length ? ` [${r.secondaryTypes.join(", ")}]` : ""} · <em>{badge(r)}</em>{" "}
<label>
<input type="checkbox" aria-label={`monitor ${r.album}`} checked={r.monitored} onChange={() => toggleMonitor(r)} /> monitor
</label>{" "}
<button onClick={() => searchNow(r)}>Search now</button>
</li>
))}
</ul>
</div>
);
}
+11
View File
@@ -0,0 +1,11 @@
import { DiscographyClient } from "./discography-client";
export default async function ArtistDetailPage({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params;
return (
<main>
<p><a href="/artists"> Artists</a></p>
<DiscographyClient id={id} />
</main>
);
}