Files
Lyra/web/src/app/wanted/wanted-client.tsx
T
2026-07-11 14:11:53 +02:00

71 lines
2.0 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
type Wanted = {
id: string;
artistName: string;
album: string;
state: string;
currentQualityClass: number | null;
lastSearchedAt: string | null;
};
export function WantedClient() {
const [rows, setRows] = useState<Wanted[]>([]);
const [artist, setArtist] = useState("");
const [album, setAlbum] = useState("");
const [error, setError] = useState("");
async function refresh() {
const res = await fetch("/api/wanted");
setRows((await res.json()).wanted);
}
useEffect(() => {
refresh();
}, []);
async function add(e: React.FormEvent) {
e.preventDefault();
setError("");
if (!artist.trim() || !album.trim()) return;
const res = await fetch("/api/wanted", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ artist, album }),
});
if (!res.ok) {
setError((await res.json()).error ?? "failed to add");
return;
}
setArtist("");
setAlbum("");
refresh();
}
async function searchNow(w: Wanted) {
await fetch(`/api/releases/${w.id}/search`, { method: "POST" });
refresh();
}
return (
<div>
<form onSubmit={add}>
<input aria-label="wanted artist" placeholder="Artist" value={artist} onChange={(e) => setArtist(e.target.value)} />
<input aria-label="wanted album" placeholder="Album" value={album} onChange={(e) => setAlbum(e.target.value)} />
<button type="submit">Add to wanted</button>
{error ? <span> {error}</span> : null}
</form>
<ul>
{rows.map((w) => (
<li key={w.id}>
{w.artistName} {w.album} · <em>{w.currentQualityClass !== null ? `have q${w.currentQualityClass}, upgrading` : w.state}</em>
{w.lastSearchedAt ? ` · last tried ${new Date(w.lastSearchedAt).toLocaleString()}` : " · never tried"}{" "}
<button onClick={() => searchNow(w)}>Search now</button>
</li>
))}
</ul>
</div>
);
}