148 lines
4.7 KiB
TypeScript
148 lines
4.7 KiB
TypeScript
/**
|
|
* useHomeData Hook
|
|
*
|
|
* Manages data loading for the Home page, fetching all 7 sections using React Query
|
|
* and providing refresh functionality for mixes.
|
|
*/
|
|
|
|
import { useEffect } from 'react';
|
|
import { useQueryClient } from '@tanstack/react-query';
|
|
import { useAuth } from '@/lib/auth-context';
|
|
import { toast } from 'sonner';
|
|
import type {
|
|
Artist,
|
|
ListenedItem,
|
|
Podcast,
|
|
Audiobook,
|
|
Mix,
|
|
PopularArtist,
|
|
} from '../types';
|
|
import {
|
|
useRecentlyListenedQuery,
|
|
useRecentlyAddedQuery,
|
|
useRecommendationsQuery,
|
|
useMixesQuery,
|
|
usePopularArtistsQuery,
|
|
useTopPodcastsQuery,
|
|
useAudiobooksQuery,
|
|
useRefreshMixesMutation,
|
|
useBrowseAllQuery,
|
|
queryKeys,
|
|
} from '@/hooks/useQueries';
|
|
|
|
interface PlaylistPreview {
|
|
id: string;
|
|
source: string;
|
|
type: string;
|
|
title: string;
|
|
description: string | null;
|
|
creator: string;
|
|
imageUrl: string | null;
|
|
trackCount: number;
|
|
url: string;
|
|
}
|
|
|
|
export interface UseHomeDataReturn {
|
|
// Data sections
|
|
recentlyListened: ListenedItem[];
|
|
recentlyAdded: Artist[];
|
|
recommended: Artist[];
|
|
mixes: Mix[];
|
|
popularArtists: PopularArtist[];
|
|
recentPodcasts: Podcast[];
|
|
recentAudiobooks: Audiobook[];
|
|
featuredPlaylists: PlaylistPreview[];
|
|
|
|
// Loading states
|
|
isLoading: boolean;
|
|
isRefreshingMixes: boolean;
|
|
isBrowseLoading: boolean;
|
|
|
|
// Actions
|
|
handleRefreshMixes: () => Promise<void>;
|
|
}
|
|
|
|
/**
|
|
* Custom hook to load all Home page data sections using React Query
|
|
*
|
|
* Loads the following sections with automatic caching:
|
|
* 1. Recently listened (Continue Listening)
|
|
* 2. Recently added artists
|
|
* 3. Recommended for you
|
|
* 4. Mixes (Made For You)
|
|
* 5. Popular artists
|
|
* 6. Recent podcasts
|
|
* 7. Recent audiobooks
|
|
*
|
|
* @returns {UseHomeDataReturn} All home page data and loading states
|
|
*/
|
|
export function useHomeData(): UseHomeDataReturn {
|
|
const { isAuthenticated } = useAuth();
|
|
const queryClient = useQueryClient();
|
|
|
|
// Listen for mixes-updated event (fired when user saves mood preferences)
|
|
useEffect(() => {
|
|
const handleMixesUpdated = () => {
|
|
queryClient.invalidateQueries({ queryKey: queryKeys.mixes() });
|
|
};
|
|
|
|
window.addEventListener('mixes-updated', handleMixesUpdated);
|
|
return () => window.removeEventListener('mixes-updated', handleMixesUpdated);
|
|
}, [queryClient]);
|
|
|
|
// React Query hooks - these automatically handle caching, refetching, and loading states
|
|
const { data: recentlyListenedData, isLoading: isLoadingListened } = useRecentlyListenedQuery(10);
|
|
const { data: recentlyAddedData, isLoading: isLoadingAdded } = useRecentlyAddedQuery(10);
|
|
const { data: recommendedData, isLoading: isLoadingRecommended } = useRecommendationsQuery(10);
|
|
const { data: mixesData, isLoading: isLoadingMixes } = useMixesQuery();
|
|
const { data: popularData, isLoading: isLoadingPopular } = usePopularArtistsQuery(20);
|
|
const { data: podcastsData, isLoading: isLoadingPodcasts } = useTopPodcastsQuery(10);
|
|
const { data: audiobooksData, isLoading: isLoadingAudiobooks } = useAudiobooksQuery();
|
|
const { data: browseData, isLoading: isBrowseLoading } = useBrowseAllQuery();
|
|
|
|
// Mutation for refreshing mixes
|
|
const { mutateAsync: refreshMixes, isPending: isRefreshingMixes } = useRefreshMixesMutation();
|
|
|
|
/**
|
|
* Refresh mixes and update cache
|
|
*/
|
|
const handleRefreshMixes = async () => {
|
|
try {
|
|
await refreshMixes();
|
|
toast.success('Mixes refreshed! Check out your new daily picks');
|
|
} catch (error) {
|
|
console.error('Failed to refresh mixes:', error);
|
|
toast.error('Failed to refresh mixes');
|
|
}
|
|
};
|
|
|
|
// Process recently listened data - can contain artists, podcasts, or audiobooks
|
|
const items = recentlyListenedData?.items || [];
|
|
|
|
// Calculate overall loading state - true if any query is loading
|
|
const isLoading =
|
|
!isAuthenticated ||
|
|
isLoadingListened ||
|
|
isLoadingAdded ||
|
|
isLoadingRecommended ||
|
|
isLoadingMixes ||
|
|
isLoadingPopular ||
|
|
isLoadingPodcasts ||
|
|
isLoadingAudiobooks;
|
|
|
|
return {
|
|
recentlyListened: items,
|
|
recentlyAdded: recentlyAddedData?.artists || [],
|
|
recommended: recommendedData?.artists || [],
|
|
mixes: Array.isArray(mixesData) ? mixesData : [],
|
|
popularArtists: popularData?.artists || [],
|
|
recentPodcasts: Array.isArray(podcastsData) ? podcastsData.slice(0, 10) : [],
|
|
recentAudiobooks: Array.isArray(audiobooksData) ? audiobooksData.slice(0, 10) : [],
|
|
featuredPlaylists: browseData?.playlists || [],
|
|
isLoading,
|
|
isRefreshingMixes,
|
|
isBrowseLoading,
|
|
handleRefreshMixes,
|
|
};
|
|
}
|