forked from
chadtmiller.com/slices-teal-relay
Teal.fm frontend powered by slices.network
tealfm-slices.wisp.place
tealfm
slices
1import { graphql, useLazyLoadQuery } from "react-relay";
2import { useParams } from "react-router-dom";
3import type { ProfileTopAlbumsQuery } from "./__generated__/ProfileTopAlbumsQuery.graphql";
4import AlbumItem from "./AlbumItem";
5import { useDateRangeFilter } from "./useDateRangeFilter";
6import { useMemo } from "react";
7
8export default function ProfileTopAlbums() {
9 const { handle, period } = useParams<{ handle: string; period?: string }>();
10 const dateRangeVariables = useDateRangeFilter(period);
11
12 const queryVariables = useMemo(() => {
13 return {
14 where: {
15 ...dateRangeVariables.where,
16 actorHandle: { eq: handle },
17 },
18 };
19 }, [handle, dateRangeVariables]);
20
21 const data = useLazyLoadQuery<ProfileTopAlbumsQuery>(
22 graphql`
23 query ProfileTopAlbumsQuery($where: FmTealAlphaFeedPlayWhereInput) {
24 fmTealAlphaFeedPlaysAggregated(
25 groupBy: [{ field: releaseMbId }, { field: releaseName }, { field: artists }]
26 orderBy: { count: desc }
27 limit: 50
28 where: $where
29 ) {
30 releaseMbId
31 releaseName
32 artists
33 count
34 }
35 }
36 `,
37 queryVariables,
38 { fetchKey: `${handle}-${period || "all"}`, fetchPolicy: "store-or-network" }
39 );
40
41 const albums = [...(data.fmTealAlphaFeedPlaysAggregated || [])];
42
43 // Deduplicate by release name, keeping the one with highest count
44 // Prefer entries with artist data
45 const seenNames = new Set<string>();
46 const dedupedAlbums = albums
47 .sort((a, b) => {
48 // First sort by count (already sorted from query)
49 if (b.count !== a.count) return b.count - a.count;
50 // Then prefer entries with artists data
51 if (a.artists && !b.artists) return -1;
52 if (!a.artists && b.artists) return 1;
53 return 0;
54 })
55 .filter((album) => {
56 const name = album.releaseName || "Unknown Album";
57 if (seenNames.has(name)) {
58 return false;
59 }
60 seenNames.add(name);
61 return true;
62 })
63 .slice(0, 10);
64
65 const maxCount = dedupedAlbums.length > 0 ? dedupedAlbums[0].count : 0;
66
67 return (
68 <div className="space-y-1">
69 {dedupedAlbums.map((album, index) => (
70 <AlbumItem
71 key={album.releaseMbId || index}
72 releaseName={album.releaseName || "Unknown Album"}
73 releaseMbId={album.releaseMbId}
74 artists={album.artists}
75 count={album.count}
76 rank={index + 1}
77 maxCount={maxCount}
78 />
79 ))}
80 </div>
81 );
82}