add refresh button to album / artist carousels

This commit is contained in:
jeffvli
2025-12-03 18:05:15 -08:00
parent 9d498d4ca2
commit a47f94ebb2
3 changed files with 61 additions and 25 deletions
@@ -22,6 +22,7 @@ interface GridCarouselProps {
loadNextPage?: () => void; loadNextPage?: () => void;
onNextPage: (page: number) => void; onNextPage: (page: number) => void;
onPrevPage: (page: number) => void; onPrevPage: (page: number) => void;
onRefresh?: () => void;
rowCount?: number; rowCount?: number;
title?: ReactNode | string; title?: ReactNode | string;
} }
@@ -43,7 +44,16 @@ const pageVariants: Variants = {
}; };
function BaseGridCarousel(props: GridCarouselProps) { function BaseGridCarousel(props: GridCarouselProps) {
const { cards, hasNextPage, loadNextPage, onNextPage, onPrevPage, rowCount = 1, title } = props; const {
cards,
hasNextPage,
loadNextPage,
onNextPage,
onPrevPage,
onRefresh,
rowCount = 1,
title,
} = props;
const { ref, ...cq } = useContainerQuery({ const { ref, ...cq } = useContainerQuery({
'2xl': 1280, '2xl': 1280,
'3xl': 1440, '3xl': 1440,
@@ -128,30 +138,44 @@ function BaseGridCarousel(props: GridCarouselProps) {
{cq.isCalculated && ( {cq.isCalculated && (
<> <>
<div className={styles.navigation}> <div className={styles.navigation}>
{typeof title === 'string' ? ( <Group gap="xs" justify="space-between" w="100%">
<TextTitle fw={700} isNoSelect order={3}> <Group gap="xs">
{title} {typeof title === 'string' ? (
</TextTitle> <TextTitle fw={700} isNoSelect order={3}>
) : ( {title}
title </TextTitle>
)} ) : (
<Group gap="xs" justify="end"> title
<ActionIcon )}
disabled={isPrevDisabled} {onRefresh && (
icon="arrowLeftS" <ActionIcon
iconProps={{ size: 'lg' }} icon="refresh"
onClick={handlePrevPage} iconProps={{ size: 'md' }}
size="xs" onClick={onRefresh}
variant="subtle" size="xs"
/> tooltip={{ label: 'Refresh' }}
<ActionIcon variant="transparent"
disabled={isNextDisabled} />
icon="arrowRightS" )}
iconProps={{ size: 'lg' }} </Group>
onClick={handleNextPage} <Group gap="xs" justify="end">
size="xs" <ActionIcon
variant="subtle" disabled={isPrevDisabled}
/> icon="arrowLeftS"
iconProps={{ size: 'lg' }}
onClick={handlePrevPage}
size="xs"
variant="subtle"
/>
<ActionIcon
disabled={isNextDisabled}
icon="arrowRightS"
iconProps={{ size: 'lg' }}
onClick={handleNextPage}
size="xs"
variant="subtle"
/>
</Group>
</Group> </Group>
</div> </div>
<AnimatePresence custom={currentPage} initial={false} mode="wait"> <AnimatePresence custom={currentPage} initial={false} mode="wait">
@@ -34,6 +34,7 @@ const BaseAlbumInfiniteCarousel = (props: AlbumCarouselProps) => {
data: albums, data: albums,
fetchNextPage, fetchNextPage,
hasNextPage, hasNextPage,
refetch,
} = useAlbumListInfinite(sortBy, sortOrder, 20, additionalQuery); } = useAlbumListInfinite(sortBy, sortOrder, 20, additionalQuery);
const controls = useDefaultItemListControls(); const controls = useDefaultItemListControls();
@@ -65,6 +66,10 @@ const BaseAlbumInfiniteCarousel = (props: AlbumCarouselProps) => {
const handlePrevPage = useCallback(() => {}, []); const handlePrevPage = useCallback(() => {}, []);
const handleRefresh = useCallback(() => {
refetch();
}, [refetch]);
const firstPageItems = excludeIds const firstPageItems = excludeIds
? albums.pages[0]?.items.filter((album) => !excludeIds.includes(album.id)) || [] ? albums.pages[0]?.items.filter((album) => !excludeIds.includes(album.id)) || []
: albums.pages[0]?.items || []; : albums.pages[0]?.items || [];
@@ -80,6 +85,7 @@ const BaseAlbumInfiniteCarousel = (props: AlbumCarouselProps) => {
loadNextPage={fetchNextPage} loadNextPage={fetchNextPage}
onNextPage={handleNextPage} onNextPage={handleNextPage}
onPrevPage={handlePrevPage} onPrevPage={handlePrevPage}
onRefresh={handleRefresh}
rowCount={rowCount} rowCount={rowCount}
title={title} title={title}
/> />
@@ -34,6 +34,7 @@ export const BaseAlbumArtistInfiniteCarousel = (props: AlbumArtistCarouselProps)
data: albumArtists, data: albumArtists,
fetchNextPage, fetchNextPage,
hasNextPage, hasNextPage,
refetch,
} = useAlbumArtistListInfinite(sortBy, sortOrder, 20, additionalQuery); } = useAlbumArtistListInfinite(sortBy, sortOrder, 20, additionalQuery);
const controls = useDefaultItemListControls(); const controls = useDefaultItemListControls();
@@ -65,6 +66,10 @@ export const BaseAlbumArtistInfiniteCarousel = (props: AlbumArtistCarouselProps)
const handlePrevPage = useCallback(() => {}, []); const handlePrevPage = useCallback(() => {}, []);
const handleRefresh = useCallback(() => {
refetch();
}, [refetch]);
const firstPageItems = excludeIds const firstPageItems = excludeIds
? albumArtists.pages[0]?.items.filter( ? albumArtists.pages[0]?.items.filter(
(albumArtist) => !excludeIds.includes(albumArtist.id), (albumArtist) => !excludeIds.includes(albumArtist.id),
@@ -82,6 +87,7 @@ export const BaseAlbumArtistInfiniteCarousel = (props: AlbumArtistCarouselProps)
loadNextPage={fetchNextPage} loadNextPage={fetchNextPage}
onNextPage={handleNextPage} onNextPage={handleNextPage}
onPrevPage={handlePrevPage} onPrevPage={handlePrevPage}
onRefresh={handleRefresh}
rowCount={rowCount} rowCount={rowCount}
title={title} title={title}
/> />