feat(web): restyle Artists, Discover, Wanted, discography + preview (Phase 2)
Convert the remaining pages onto the Pressing Plant system: PageHead component, shared list-row / toggle / small+ghost button / tracklist classes, and page wrappers trimmed now that the shell provides masthead + nav. All logic and test hooks (aria-labels, button text) preserved. Verified in the real app across both themes (Playwright): artists/discover/wanted/discography render cohesively with real data. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { PageHead } from "../_ui/page-head";
|
||||
import { SectionHeader } from "../_ui/section-header";
|
||||
|
||||
type Artist = {
|
||||
id: string;
|
||||
@@ -68,38 +70,86 @@ export function ArtistsClient() {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<form onSubmit={search}>
|
||||
<input aria-label="artist search" placeholder="Search an artist…" value={query} onChange={(e) => setQuery(e.target.value)} />
|
||||
<button type="submit">Search</button>
|
||||
<PageHead title="Artists" eyebrow="The roster · follow & watch" />
|
||||
|
||||
<form className="request-form" onSubmit={search}>
|
||||
<label className="field">
|
||||
<span>Find an artist</span>
|
||||
<input
|
||||
aria-label="artist search"
|
||||
placeholder="Search MusicBrainz…"
|
||||
value={query}
|
||||
onChange={(e) => setQuery(e.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<button type="submit" className="btn accent">
|
||||
Search
|
||||
</button>
|
||||
{searching ? <span className="rmeta">searching…</span> : null}
|
||||
</form>
|
||||
{searching ? <p>Searching…</p> : null}
|
||||
|
||||
{hits.length > 0 ? (
|
||||
<ul>
|
||||
{hits.map((h) => (
|
||||
<li key={h.mbid}>
|
||||
<a href={`/discover/artist/${h.mbid}?name=${encodeURIComponent(h.name)}`}>{h.name}</a>
|
||||
{h.disambiguation ? ` (${h.disambiguation})` : ""}{" "}
|
||||
{followedMbids.has(h.mbid) ? (
|
||||
<span> · following</span>
|
||||
) : (
|
||||
<button onClick={() => follow(h)}>Follow</button>
|
||||
)}
|
||||
<>
|
||||
<SectionHeader title="Search results" note={`${hits.length} found`} />
|
||||
<ul className="list">
|
||||
{hits.map((h) => (
|
||||
<li key={h.mbid} className="list-row">
|
||||
<div className="main">
|
||||
<div className="rtitle">
|
||||
<a href={`/discover/artist/${h.mbid}?name=${encodeURIComponent(h.name)}`}>{h.name}</a>
|
||||
{h.disambiguation ? <span className="dim"> — {h.disambiguation}</span> : null}
|
||||
</div>
|
||||
</div>
|
||||
<div className="actions">
|
||||
{followedMbids.has(h.mbid) ? (
|
||||
<span className="following">Following</span>
|
||||
) : (
|
||||
<button className="btn sm" onClick={() => follow(h)}>
|
||||
Follow
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
) : null}
|
||||
|
||||
<SectionHeader title="Watching" note={`${artists.length} artists`} />
|
||||
{artists.length === 0 ? (
|
||||
<p className="empty">Not following anyone yet. Search above and follow an artist to start watching their releases.</p>
|
||||
) : (
|
||||
<ul className="list">
|
||||
{artists.map((a) => (
|
||||
<li key={a.id} className="list-row">
|
||||
<div className="main">
|
||||
<div className="rtitle">
|
||||
<a href={`/artists/${a.id}`}>{a.name}</a>
|
||||
</div>
|
||||
<div className="rmeta">
|
||||
<span className="score">
|
||||
{a.haveCount} have <span className="dot">·</span> {a.monitoredCount} monitored <span className="dot">·</span> {a.releaseCount} releases
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="actions">
|
||||
<label className="toggle">
|
||||
<input
|
||||
type="checkbox"
|
||||
aria-label={`auto-monitor ${a.name}`}
|
||||
checked={a.autoMonitorFuture}
|
||||
onChange={() => toggleAuto(a)}
|
||||
/>
|
||||
auto-monitor
|
||||
</label>
|
||||
<button className="btn sm ghost" onClick={() => unfollow(a)}>
|
||||
Unfollow
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : null}
|
||||
|
||||
<ul>
|
||||
{artists.map((a) => (
|
||||
<li key={a.id}>
|
||||
<a href={`/artists/${a.id}`}>{a.name}</a> · {a.haveCount}/{a.monitoredCount} have/monitored of {a.releaseCount}{" "}
|
||||
<label>
|
||||
<input type="checkbox" aria-label={`auto-monitor ${a.name}`} checked={a.autoMonitorFuture} onChange={() => toggleAuto(a)} /> auto-monitor future
|
||||
</label>{" "}
|
||||
<button onClick={() => unfollow(a)}>Unfollow</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user