diff --git a/web/src/app/artists/artists-client.tsx b/web/src/app/artists/artists-client.tsx new file mode 100644 index 0000000..c2edad5 --- /dev/null +++ b/web/src/app/artists/artists-client.tsx @@ -0,0 +1,99 @@ +"use client"; + +import { useEffect, useState } from "react"; + +type Artist = { + id: string; + mbid: string; + name: string; + autoMonitorFuture: boolean; + releaseCount: number; + monitoredCount: number; + haveCount: number; +}; +type Hit = { mbid: string; name: string; disambiguation: string }; + +export function ArtistsClient() { + const [artists, setArtists] = useState([]); + const [query, setQuery] = useState(""); + const [hits, setHits] = useState([]); + const [searching, setSearching] = useState(false); + + async function refresh() { + const res = await fetch("/api/artists"); + setArtists((await res.json()).artists); + } + useEffect(() => { + refresh(); + }, []); + + async function search(e: React.FormEvent) { + e.preventDefault(); + if (!query.trim()) return; + setSearching(true); + try { + const res = await fetch(`/api/mb/artists?q=${encodeURIComponent(query.trim())}`); + setHits(res.ok ? (await res.json()).artists : []); + } finally { + setSearching(false); + } + } + + async function follow(hit: Hit) { + await fetch("/api/artists", { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ mbid: hit.mbid, name: hit.name }), + }); + setHits([]); + setQuery(""); + refresh(); + } + + async function toggleAuto(a: Artist) { + await fetch(`/api/artists/${a.id}`, { + method: "PATCH", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ autoMonitorFuture: !a.autoMonitorFuture }), + }); + refresh(); + } + + async function unfollow(a: Artist) { + await fetch(`/api/artists/${a.id}`, { method: "DELETE" }); + refresh(); + } + + return ( +
+
+ setQuery(e.target.value)} /> + +
+ {searching ?

Searching…

: null} + {hits.length > 0 ? ( +
    + {hits.map((h) => ( +
  • + {h.name} + {h.disambiguation ? ` (${h.disambiguation})` : ""}{" "} + +
  • + ))} +
+ ) : null} + +
    + {artists.map((a) => ( +
  • + {a.name} · {a.haveCount}/{a.monitoredCount} have/monitored of {a.releaseCount}{" "} + {" "} + +
  • + ))} +
+
+ ); +} diff --git a/web/src/app/artists/page.tsx b/web/src/app/artists/page.tsx new file mode 100644 index 0000000..3c12d26 --- /dev/null +++ b/web/src/app/artists/page.tsx @@ -0,0 +1,11 @@ +import { ArtistsClient } from "./artists-client"; + +export default function ArtistsPage() { + return ( +
+

Watched artists

+

Home · Wanted

+ +
+ ); +} diff --git a/web/src/app/page.tsx b/web/src/app/page.tsx index e0dd0b3..7cc5ef1 100644 --- a/web/src/app/page.tsx +++ b/web/src/app/page.tsx @@ -4,7 +4,7 @@ export default function Home() { return (

Lyra

-

Settings

+

Artists · Wanted · Settings

);