diff --git a/web/src/app/api/artists/route.ts b/web/src/app/api/artists/route.ts index 57c7758..4dee2eb 100644 --- a/web/src/app/api/artists/route.ts +++ b/web/src/app/api/artists/route.ts @@ -38,6 +38,7 @@ export async function GET(request: Request) { id: a.id, mbid: a.mbid, name: a.name, + createdAt: a.createdAt, autoMonitorFuture: a.autoMonitorFuture, showAllTypes: a.showAllTypes, releaseCount: visible.length, diff --git a/web/src/app/artists/artists-client.tsx b/web/src/app/artists/artists-client.tsx index 3d1602f..cd49825 100644 --- a/web/src/app/artists/artists-client.tsx +++ b/web/src/app/artists/artists-client.tsx @@ -10,6 +10,7 @@ type Artist = { id: string; mbid: string; name: string; + createdAt: string; autoMonitorFuture: boolean; releaseCount: number; monitoredCount: number; @@ -17,11 +18,21 @@ type Artist = { }; type Hit = { mbid: string; name: string; disambiguation: string }; +type SortKey = "followed" | "name" | "have" | "monitored" | "releases"; +const SORTS: { key: SortKey; label: string; cmp: (a: Artist, b: Artist) => number }[] = [ + { key: "followed", label: "Recently followed", cmp: (a, b) => b.createdAt.localeCompare(a.createdAt) }, + { key: "name", label: "Name A–Z", cmp: (a, b) => a.name.localeCompare(b.name) }, + { key: "have", label: "Most in library", cmp: (a, b) => b.haveCount - a.haveCount || a.name.localeCompare(b.name) }, + { key: "monitored", label: "Most monitored", cmp: (a, b) => b.monitoredCount - a.monitoredCount || a.name.localeCompare(b.name) }, + { key: "releases", label: "Most releases", cmp: (a, b) => b.releaseCount - a.releaseCount || a.name.localeCompare(b.name) }, +]; + export function ArtistsClient() { const [artists, setArtists] = useState([]); const [ownedNotFollowed, setOwnedNotFollowed] = useState([]); const [justFollowed, setJustFollowed] = useState>(new Set()); const [filter, setFilter] = useState(""); + const [sort, setSort] = useState("followed"); const [showAdd, setShowAdd] = useState(false); const [query, setQuery] = useState(""); const [hits, setHits] = useState([]); @@ -113,8 +124,10 @@ export function ArtistsClient() { const followedMbids = new Set(artists.map((a) => a.mbid)); const shown = useMemo(() => { const n = filter.trim().toLowerCase(); - return n ? artists.filter((a) => a.name.toLowerCase().includes(n)) : artists; - }, [artists, filter]); + const filtered = n ? artists.filter((a) => a.name.toLowerCase().includes(n)) : artists; + const cmp = (SORTS.find((s) => s.key === sort) ?? SORTS[0]).cmp; + return [...filtered].sort(cmp); + }, [artists, filter, sort]); const ownedShown = useMemo( () => ownedNotFollowed.filter((name) => !justFollowed.has(name)), [ownedNotFollowed, justFollowed], @@ -137,6 +150,14 @@ export function ArtistsClient() { onChange={(e) => setFilter(e.target.value)} /> +