feat(preview): link discovery feed + Find-similar to the artist preview
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,7 @@ export function DiscoverClient() {
|
||||
const [query, setQuery] = useState("");
|
||||
const [search, setSearch] = useState<SearchResult | null>(null);
|
||||
const [busy, setBusy] = useState(false);
|
||||
const [followedSimilar, setFollowedSimilar] = useState<Set<string>>(new Set());
|
||||
|
||||
const loadFeed = useCallback(async () => {
|
||||
setFeed(await (await fetch("/api/discover")).json());
|
||||
@@ -70,6 +71,17 @@ export function DiscoverClient() {
|
||||
}
|
||||
}
|
||||
|
||||
async function followSimilar(a: { mbid: string; name: string }) {
|
||||
const res = await fetch("/api/artists", {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/json" },
|
||||
body: JSON.stringify({ mbid: a.mbid, name: a.name }),
|
||||
});
|
||||
if (res.ok || res.status === 409) {
|
||||
setFollowedSimilar((s) => new Set(s).add(a.mbid));
|
||||
}
|
||||
}
|
||||
|
||||
async function act(id: string, action: "follow" | "want" | "dismiss") {
|
||||
await fetch(`/api/discover/${id}`, {
|
||||
method: "POST",
|
||||
@@ -104,7 +116,13 @@ export function DiscoverClient() {
|
||||
<ul>
|
||||
{search.similar.map((s) => (
|
||||
<li key={s.mbid}>
|
||||
{s.name} <small>({s.score.toFixed(1)})</small>
|
||||
<a href={`/discover/artist/${s.mbid}?name=${encodeURIComponent(s.name)}`}>{s.name}</a>{" "}
|
||||
<small>({s.score.toFixed(1)})</small>{" "}
|
||||
{followedSimilar.has(s.mbid) ? (
|
||||
<span>Followed</span>
|
||||
) : (
|
||||
<button onClick={() => followSimilar(s)}>Follow</button>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
@@ -116,7 +134,11 @@ export function DiscoverClient() {
|
||||
<ul>
|
||||
{feed.artists.map((s) => (
|
||||
<li key={s.id}>
|
||||
<strong>{s.artistName}</strong>{" "}
|
||||
<strong>
|
||||
<a href={`/discover/artist/${s.artistMbid}?name=${encodeURIComponent(s.artistName)}`}>
|
||||
{s.artistName}
|
||||
</a>
|
||||
</strong>{" "}
|
||||
<small>score {s.score.toFixed(2)} · {s.seedCount} seed(s) · {s.sources.join(", ")}</small>{" "}
|
||||
<button onClick={() => act(s.id, "follow")}>Follow</button>{" "}
|
||||
<button onClick={() => act(s.id, "dismiss")}>Dismiss</button>
|
||||
@@ -130,7 +152,14 @@ export function DiscoverClient() {
|
||||
<ul>
|
||||
{feed.albums.map((s) => (
|
||||
<li key={s.id}>
|
||||
<strong>{s.album}</strong> — {s.artistName}{" "}
|
||||
<strong>
|
||||
<a
|
||||
href={`/discover/artist/${s.artistMbid}?name=${encodeURIComponent(s.artistName)}#rg-${s.rgMbid}`}
|
||||
>
|
||||
{s.album}
|
||||
</a>
|
||||
</strong>{" "}
|
||||
— {s.artistName}{" "}
|
||||
<small>score {s.score.toFixed(2)}</small>{" "}
|
||||
<button onClick={() => act(s.id, "want")}>Want</button>{" "}
|
||||
<button onClick={() => act(s.id, "dismiss")}>Dismiss</button>
|
||||
|
||||
Reference in New Issue
Block a user