From bc6cd5b0147654dbcf4db639b1fa7992d2ac24fe Mon Sep 17 00:00:00 2001 From: jeffvli Date: Sun, 8 Mar 2026 22:15:54 -0700 Subject: [PATCH] refactor grid columns internally into album artist sections to handle null cases --- .../album-artist-detail-content.tsx | 1057 +++++++++-------- 1 file changed, 550 insertions(+), 507 deletions(-) diff --git a/src/renderer/features/artists/components/album-artist-detail-content.tsx b/src/renderer/features/artists/components/album-artist-detail-content.tsx index 8a2d36d71..e52acf2bf 100644 --- a/src/renderer/features/artists/components/album-artist-detail-content.tsx +++ b/src/renderer/features/artists/components/album-artist-detail-content.tsx @@ -159,53 +159,58 @@ const AlbumArtistActionButtons = ({ interface AlbumArtistMetadataGenresProps { genres?: Array<{ id: string; name: string }>; + order?: number; } -const AlbumArtistMetadataGenres = ({ genres }: AlbumArtistMetadataGenresProps) => { +const AlbumArtistMetadataGenres = ({ genres, order }: AlbumArtistMetadataGenresProps) => { const { t } = useTranslation(); const genrePath = useGenreRoute(); if (!genres || genres.length === 0) return null; return ( - - - {t('entity.genre', { - count: genres.length, - })} - - - {genres.map((genre) => ( - - ))} - - + + + + {t('entity.genre', { + count: genres.length, + })} + + + {genres.map((genre) => ( + + ))} + + + ); }; interface AlbumArtistMetadataBiographyProps { artistName?: string; + order?: number; routeId: string; } const AlbumArtistMetadataBiography = ({ artistName, + order, routeId, }: AlbumArtistMetadataBiographyProps) => { const { t } = useTranslation(); @@ -234,18 +239,20 @@ const AlbumArtistMetadataBiography = ({ if (isLoading) { return ( -
- - {t('page.albumArtistDetail.about', { - artist: artistName, - })} - - - - - - -
+ +
+ + {t('page.albumArtistDetail.about', { + artist: artistName, + })} + + + + + + +
+
); } @@ -254,16 +261,18 @@ const AlbumArtistMetadataBiography = ({ } return ( -
- - {t('page.albumArtistDetail.about', { - artist: artistName, - })} - - - - -
+ +
+ + {t('page.albumArtistDetail.about', { + artist: artistName, + })} + + + + +
+
); }; @@ -302,11 +311,13 @@ const SongTableListContainer = ({ interface AlbumArtistMetadataTopSongsProps { detailQuery: ReturnType>; + order?: number; routeId: string; } const AlbumArtistMetadataTopSongsContent = ({ detailQuery, + order, routeId, }: AlbumArtistMetadataTopSongsProps) => { const { t } = useTranslation(); @@ -395,180 +406,186 @@ const AlbumArtistMetadataTopSongsContent = ({ const isLoading = topSongsQuery.isLoading || !topSongsQuery.data; if (!isLoading && !tableConfig) return null; + if (!isLoading && songs.length === 0) return null; const currentSongId = currentSong?.id; return ( -
- -
- - - {t('page.albumArtistDetail.topSongs', { - postProcess: 'sentenceCase', - })} - - {!isLoading && {songs.length}} - -
-
- - {songs.length > 0 && ( - - - - - - - - - - - - )} -
-
- {isLoading ? ( - - - - ) : tableConfig ? ( - <> - - } - onChange={(e) => setSearchTerm(e.target.value)} - placeholder={t('common.search', { postProcess: 'sentenceCase' })} - radius="xl" - rightSection={ - searchTerm ? ( - setSearchTerm('')} - size="sm" - variant="transparent" - /> - ) : null - } - styles={{ - input: { - background: 'transparent', - border: '1px solid rgba(255, 255, 255, 0.05)', - }, - }} - value={searchTerm} - /> - - setTopSongsQueryType(value as 'community' | 'personal') - } - size="xs" - value={topSongsQueryType} - /> - + +
+ +
+ + + {t('page.albumArtistDetail.topSongs', { + postProcess: 'sentenceCase', + })} + + {!isLoading && {songs.length}} - - +
+ + {songs.length > 0 && ( + + + + + + + + + + + + )} +
+
+ {isLoading ? ( + + + + ) : tableConfig ? ( + <> + + } + onChange={(e) => setSearchTerm(e.target.value)} + placeholder={t('common.search', { + postProcess: 'sentenceCase', + })} + radius="xl" + rightSection={ + searchTerm ? ( + setSearchTerm('')} + size="sm" + variant="transparent" + /> + ) : null + } + styles={{ + input: { + background: 'transparent', + border: '1px solid rgba(255, 255, 255, 0.05)', + }, + }} + value={searchTerm} + /> + + setTopSongsQueryType(value as 'community' | 'personal') + } + size="xs" + value={topSongsQueryType} + /> + + + - - - ) : null} -
-
+ itemCount={filteredSongs.length} + maxRows={5} + tableSize={tableConfig.size} + > + + + + ) : null} + +
+ ); }; const AlbumArtistMetadataTopSongs = ({ detailQuery, + order, routeId, }: AlbumArtistMetadataTopSongsProps) => { const server = useCurrentServer(); @@ -581,17 +598,25 @@ const AlbumArtistMetadataTopSongs = ({ return ( {canStartQuery ? ( - + ) : null} ); }; interface AlbumArtistMetadataFavoriteSongsProps { + order?: number; routeId: string; } -const AlbumArtistMetadataFavoriteSongs = ({ routeId }: AlbumArtistMetadataFavoriteSongsProps) => { +const AlbumArtistMetadataFavoriteSongs = ({ + order, + routeId, +}: AlbumArtistMetadataFavoriteSongsProps) => { const { t } = useTranslation(); const [searchTerm, setSearchTerm] = useState(''); const [debouncedSearchTerm] = useDebouncedValue(searchTerm, 300); @@ -671,154 +696,162 @@ const AlbumArtistMetadataFavoriteSongs = ({ routeId }: AlbumArtistMetadataFavori const isLoading = favoriteSongsQuery.isLoading || !favoriteSongsQuery.data; if (!isLoading && !tableConfig) return null; + if (!isLoading && songs.length === 0) return null; const currentSongId = currentSong?.id; return ( -
- -
- - - {t('page.albumArtistDetail.favoriteSongs', { - postProcess: 'sentenceCase', - })} - - {!isLoading && {songs.length}} - -
-
- - {songs.length > 0 && ( - - - - - - - - - - - - )} -
-
- {isLoading ? ( - - - - ) : tableConfig ? ( - <> - - } - onChange={(e) => setSearchTerm(e.target.value)} - placeholder={t('common.search', { postProcess: 'sentenceCase' })} - radius="xl" - rightSection={ - searchTerm ? ( - setSearchTerm('')} - size="sm" - variant="transparent" - /> - ) : null - } - styles={{ - input: { - background: 'transparent', - border: '1px solid rgba(255, 255, 255, 0.05)', - }, - }} - value={searchTerm} - /> - + +
+ +
+ + + {t('page.albumArtistDetail.favoriteSongs', { + postProcess: 'sentenceCase', + })} + + {!isLoading && {songs.length}} - - +
+ + {songs.length > 0 && ( + + + + + + + + + + + + )} +
+
+ {isLoading ? ( + + + + ) : tableConfig ? ( + <> + + } + onChange={(e) => setSearchTerm(e.target.value)} + placeholder={t('common.search', { + postProcess: 'sentenceCase', + })} + radius="xl" + rightSection={ + searchTerm ? ( + setSearchTerm('')} + size="sm" + variant="transparent" + /> + ) : null + } + styles={{ + input: { + background: 'transparent', + border: '1px solid rgba(255, 255, 255, 0.05)', + }, + }} + value={searchTerm} + /> + + + - - - ) : null} -
-
+ itemCount={filteredSongs.length} + maxRows={5} + tableSize={tableConfig.size} + > + + + + ) : null} + +
+ ); }; @@ -828,6 +861,7 @@ interface AlbumArtistMetadataExternalLinksProps { lastFM: boolean; mbzId?: null | string; musicBrainz: boolean; + order?: number; } const AlbumArtistMetadataExternalLinks = ({ @@ -836,63 +870,70 @@ const AlbumArtistMetadataExternalLinks = ({ lastFM, mbzId, musicBrainz, + order, }: AlbumArtistMetadataExternalLinksProps) => { const { t } = useTranslation(); if (!externalLinks || (!lastFM && !musicBrainz)) return null; return ( - - - {t('common.externalLinks', { - postProcess: 'sentenceCase', - })} - - - {lastFM && ( - - )} - {mbzId && musicBrainz ? ( - - ) : null} - - + + + + {t('common.externalLinks', { + postProcess: 'sentenceCase', + })} + + + {lastFM && ( + + )} + {mbzId && musicBrainz ? ( + + ) : null} + + + ); }; interface AlbumArtistMetadataSimilarArtistsProps { + order?: number; routeId: string; } -const AlbumArtistMetadataSimilarArtists = ({ routeId }: AlbumArtistMetadataSimilarArtistsProps) => { +const AlbumArtistMetadataSimilarArtists = ({ + order, + routeId, +}: AlbumArtistMetadataSimilarArtistsProps) => { const { t } = useTranslation(); const server = useCurrentServer(); const serverId = useCurrentServerId(); @@ -957,13 +998,15 @@ const AlbumArtistMetadataSimilarArtists = ({ routeId }: AlbumArtistMetadataSimil } return ( - + + + ); }; @@ -1022,7 +1065,6 @@ export const AlbumArtistDetailContent = ({ [routeId, detailQuery.data?.name], ); - const showGenres = detailQuery.data?.genres ? detailQuery.data.genres.length !== 0 : false; const mbzId = detailQuery.data?.mbz; const handleArtistRadio = useCallback(async () => { @@ -1061,50 +1103,46 @@ export const AlbumArtistDetailContent = ({ onArtistRadio={handleArtistRadio} /> - {showGenres && ( - - - - )} + {externalLinks && (lastFM || musicBrainz) && ( - - - + )} {enabledItem.biography && ( - - - + )} - - - + {enabledItem.similarArtists && ( - - - + )} {enabledItem.topSongs && ( - - - + )} {enabledItem.favoriteSongs && ( - - - + )} @@ -1427,9 +1465,10 @@ const releaseTypeToEnumMap: Record = { interface ArtistAlbumsProps { albumsQuery: UseSuspenseQueryResult; + order?: number; } -const ArtistAlbums = ({ albumsQuery }: ArtistAlbumsProps) => { +const ArtistAlbums = ({ albumsQuery, order }: ArtistAlbumsProps) => { const { t } = useTranslation(); const artistReleaseTypeItems = useArtistReleaseTypeItems(); const [searchTerm, setSearchTerm] = useState(''); @@ -1674,68 +1713,72 @@ const ArtistAlbums = ({ albumsQuery }: ArtistAlbumsProps) => { ]); return ( - - - } - onChange={(e) => setSearchTerm(e.target.value)} - placeholder={t('common.search', { postProcess: 'sentenceCase' })} - radius="xl" - ref={searchInputRef} - rightSection={ - searchTerm ? ( - setSearchTerm('')} - size="sm" - variant="transparent" - /> - ) : null - } - styles={{ - input: { - background: 'transparent', - border: '1px solid rgba(255, 255, 255, 0.05)', - }, - }} - value={searchTerm} - /> - - setAlbumArtistDetailSort(value as AlbumListSort, sortOrder) - } - sortBy={sortBy} - /> - setAlbumArtistDetailSort(sortBy, value as SortOrder)} - sortOrder={sortOrder} - /> - - - {releaseTypeEntries.length > 0 && ( -
- {cq.isCalculated && ( - - {releaseTypeEntries.map(({ albums, displayName, releaseType }) => ( - + + + } + onChange={(e) => setSearchTerm(e.target.value)} + placeholder={t('common.search', { postProcess: 'sentenceCase' })} + radius="xl" + ref={searchInputRef} + rightSection={ + searchTerm ? ( + setSearchTerm('')} + size="sm" + variant="transparent" /> - ))} - - )} -
- )} -
+ ) : null + } + styles={{ + input: { + background: 'transparent', + border: '1px solid rgba(255, 255, 255, 0.05)', + }, + }} + value={searchTerm} + /> + + setAlbumArtistDetailSort(value as AlbumListSort, sortOrder) + } + sortBy={sortBy} + /> + + setAlbumArtistDetailSort(sortBy, value as SortOrder) + } + sortOrder={sortOrder} + /> + + + {releaseTypeEntries.length > 0 && ( +
+ {cq.isCalculated && ( + + {releaseTypeEntries.map(({ albums, displayName, releaseType }) => ( + + ))} + + )} +
+ )} + + ); };