this repo has no description

more styling & artist & release links

karitham.dev f5be275e 800769ba

verified
Changed files
+73 -46
src
+73 -46
src/App.tsx
··· 8 8 Suspense, 9 9 } from "solid-js"; 10 10 11 + const LB_API_URL = `https://api.listenbrainz.org`; 12 + const COVERARTARCHIVE_URL = "https://coverartarchive.org"; 13 + const MB_API_URL = "https://musicbrainz.org"; 14 + 11 15 export type Settings = { 12 16 username: string; 13 17 range: Range; 18 + count: number; 14 19 }; 15 20 16 21 export default () => { 17 22 const [settings, setSettings] = createSignal<Settings>({ 18 23 username: "karitham", 19 - range: "all_time", 24 + range: "this_month", 25 + count: 10, 20 26 }); 21 27 const [artistFetcher] = makeCache( 22 - (set: Settings) => artists(set.username, undefined, set.range), 28 + (set: Settings) => artists(set.username, undefined, set.range, set.count), 23 29 { 24 30 storage: localStorage, 25 31 sourceHash(source) { ··· 29 35 ); 30 36 const [artistRes] = createResource(settings, artistFetcher); 31 37 const [groupsFetcher] = makeCache( 32 - (set: Settings) => releaseGroups(set.username, undefined, set.range), 38 + (set: Settings) => 39 + releaseGroups(set.username, undefined, set.range, set.count), 33 40 { 34 41 storage: localStorage, 35 42 sourceHash(source) { ··· 40 47 const [groupsRes] = createResource(settings, groupsFetcher); 41 48 42 49 return ( 43 - <div class="bg-black min-h-screen text-white p-8"> 44 - <h1 class="text-4xl font-bold mb-8 text-center"> 45 - Your ListenBrainz Stats 46 - </h1> 47 - <div class="flex flex-col sm:flex-row items-center justify-center gap-4 mb-8"> 48 - <input 49 - type="text" 50 - value={settings().username} 51 - onChange={(e) => { 52 - setSettings(() => ({ 53 - ...settings(), 54 - username: e.target.value, 55 - })); 56 - }} 57 - placeholder="Enter username" 58 - class="p-4 rounded-lg bg-gray-800 text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-green-500 w-full sm:w-auto" 59 - /> 60 - <select 61 - value={settings().range} 62 - onChange={(e) => { 63 - setSettings(() => ({ 64 - ...settings(), 65 - range: e.target.value as Range, 66 - })); 67 - }} 68 - class="p-4 rounded-lg bg-gray-800 text-white focus:outline-none focus:ring-2 focus:ring-green-500 w-full sm:w-auto" 50 + <main class="bg-black min-h-screen text-white p-8"> 51 + <div class="m-auto max-w-4xl flex flex-col align-center"> 52 + <h1 class="text-4xl font-bold mb-8 text-center"> 53 + Your ListenBrainz Stats 54 + </h1> 55 + <div class="flex flex-col sm:flex-row items-center justify-center gap-4 mb-8"> 56 + <input 57 + type="text" 58 + value={settings().username} 59 + onChange={(e) => { 60 + setSettings(() => ({ 61 + ...settings(), 62 + username: e.target.value, 63 + })); 64 + }} 65 + placeholder="Enter username" 66 + class="p-4 rounded-lg bg-gray-800 text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-green-500 w-full sm:w-auto" 67 + /> 68 + <select 69 + value={settings().range} 70 + onChange={(e) => { 71 + setSettings(() => ({ 72 + ...settings(), 73 + range: e.target.value as Range, 74 + })); 75 + }} 76 + class="p-4 rounded-lg bg-gray-800 text-white focus:outline-none focus:ring-2 focus:ring-green-500 w-full sm:w-auto" 77 + > 78 + {ranges.map((r) => ( 79 + <option value={r}>{r}</option> 80 + ))} 81 + </select> 82 + </div> 83 + <Suspense 84 + fallback={<p class="text-center text-gray-400">Loading...</p>} 69 85 > 70 - {ranges.map((r) => ( 71 - <option value={r}>{r}</option> 72 - ))} 73 - </select> 86 + <div> 87 + <div> 88 + <h2 class="text-2xl font-semibold my-6 text-center"> 89 + Top Artists 90 + </h2> 91 + <Artists artists={artistRes()?.artists || []} /> 92 + </div> 93 + <div> 94 + <h2 class="text-2xl font-semibold my-6 text-center"> 95 + Top Albums 96 + </h2> 97 + <ReleaseGroups groups={groupsRes()?.release_groups || []} /> 98 + </div> 99 + </div> 100 + </Suspense> 74 101 </div> 75 - <Suspense fallback={<p class="text-center text-gray-400">Loading...</p>}> 76 - <h2 class="text-2xl font-semibold my-6 text-center">Top Artists</h2> 77 - <Artists artists={artistRes()?.artists || []} /> 78 - <h2 class="text-2xl font-semibold my-6 text-center">Top Albums</h2> 79 - <ReleaseGroups groups={groupsRes()?.release_groups || []} /> 80 - </Suspense> 81 - </div> 102 + </main> 82 103 ); 83 104 }; 84 105 ··· 127 148 /> 128 149 </Show> 129 150 <p class="text-white text-center font-bold text-base truncate mb-1"> 130 - {props.artist.artist_name} 151 + <a 152 + target="_blank" 153 + href={`${MB_API_URL}/artist/${props.artist.artist_mbid}`} 154 + > 155 + {props.artist.artist_name} 156 + </a> 131 157 </p> 132 158 <p class="text-gray-500 text-base truncate mb-1"> 133 159 {props.artist.listen_count} listens ··· 182 208 /> 183 209 </Show> 184 210 <p class="text-white text-center font-bold text-base truncate mb-1"> 185 - {props.group.release_group_name} 211 + <a 212 + target="_blank" 213 + href={`${MB_API_URL}/release/${props.group.caa_release_mbid}`} 214 + > 215 + {props.group.release_group_name} 216 + </a> 186 217 </p> 187 218 <p class="text-gray-500 text-base truncate mb-1"> 188 219 {props.group.listen_count} listens ··· 190 221 </div> 191 222 ); 192 223 }; 193 - 194 - const LB_API_URL = `https://api.listenbrainz.org`; 195 - const COVERARTARCHIVE_URL = "https://coverartarchive.org"; 196 - const MB_API_URL = "https://musicbrainz.org"; 197 224 198 225 const ranges = ["this_week", "this_month", "this_year", "all_time"] as const; 199 226 export type Range = (typeof ranges)[number];