import React, { useState, useEffect, useCallback } from 'react'; import { MediaList } from '../components/MediaList'; import { MediaItem } from '../api/jellyfin'; import { Loader } from '../components/Loader'; import { usePageTitle } from '../context/PageTitleContext/PageTitleContext'; import { useParams, useNavigate } from 'react-router-dom'; import { usePullToRefresh } from '../hooks/usePullToRefresh'; import { InlineLoader } from '../components/InlineLoader'; import './Discover.css'; interface SectionData { title: string; description?: string; items?: MediaItem[]; tracks?: MediaItem[]; albums?: MediaItem[]; } interface GenreOverview { title: string; description?: string; genres: Array<{ genre: string; title: string; tracks?: MediaItem[]; trackCount?: number; }>; } export const SectionMore: React.FC = () => { const { setPageTitle } = usePageTitle(); const { section } = useParams<{ section: string }>(); const navigate = useNavigate(); const [sectionData, setSectionData] = useState(null); const [genreOverview, setGenreOverview] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const fetchSectionData = useCallback(async () => { setLoading(true); setError(null); try { // Handle special case for genres overview if (section === 'genres') { // For the genres overview, show all available genres as clickable cards const availableGenres = [ 'Rock', 'Pop', 'Hip-Hop', 'Electronic', 'Jazz', 'Classical', 'Country', 'R&B', 'Folk', 'Reggae', 'Blues', 'Metal', 'Punk', 'Alternative', 'Funk', 'Soul', 'Indie', 'World', 'Latin', 'Gospel', 'Ambient', 'House', 'Techno', 'Dubstep', 'Trance', 'Disco', 'Ska', 'Grunge', 'Progressive', 'Experimental', 'Acoustic', 'Singer-Songwriter', 'New Age', 'Instrumental', 'Soundtrack' ]; const genreOverviewData: GenreOverview = { title: 'Explore by Genre', description: 'Discover new music across all available genres', genres: availableGenres.map(genre => ({ genre: genre.toLowerCase().replace(/[^a-z0-9]/g, ''), title: genre, tracks: [], // We'll show these as clickable cards, not with tracks trackCount: 40 // Assume each genre has tracks })) }; setGenreOverview(genreOverviewData); setPageTitle('Explore by Genre'); return; } // Regular section handling let fetchUrl; let apiPath; // Handle genre sections (convert genre-Pop to genre/Pop) if (section?.startsWith('genre-')) { const genreName = section.replace('genre-', ''); apiPath = `genre/${genreName}`; } else { apiPath = section; } // Check if we're on the live site if (window.location.hostname === 'music.samcloud.ca') { // Use relative URL for live site (will use the same domain with reverse proxy) fetchUrl = `/api/discover/${apiPath}?limit=40`; } else { // Use development backend URL for localhost const backendUrl = import.meta.env.VITE_BACKEND_URL || 'http://localhost:5140'; fetchUrl = `${backendUrl}/api/discover/${apiPath}?limit=40`; } console.log('Fetching section data from:', fetchUrl); const response = await fetch(fetchUrl); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.error || `HTTP error! status: ${response.status}`); } const data = await response.json(); console.log('Section data received:', data); setSectionData(data); setPageTitle(data.title); } catch (e: any) { console.error(`Failed to fetch ${section} data:`, e); setError(e.message || `Failed to fetch ${section} content.`); } finally { setLoading(false); } }, [section, setPageTitle, navigate]); // Restore pull-to-refresh (hidden swipe) const { containerRef, isRefreshing } = usePullToRefresh({ onRefresh: fetchSectionData }); useEffect(() => { if (section) { fetchSectionData(); } }, [section, fetchSectionData]); if (loading) { return (

{section ? section.replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase()) : 'Section'}

); } if (error) { return (

{section ? section.replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase()) : 'Section'}

{error}

We're having trouble loading this section. Please try again later.

); } // Handle genres overview if (section === 'genres' && genreOverview) { return (
{isRefreshing && }

{genreOverview.title}

{genreOverview.description &&

{genreOverview.description}

}
{genreOverview.genres.map((genre) => (
navigate(`/section/genre-${genre.genre}`)} >

{genre.title}

{genre.trackCount} tracks

))}
); } if (!sectionData) { return (

{section ? section.replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase()) : 'Section'}

No data available for this section.

); } return (
{isRefreshing && }

{sectionData.title}

{sectionData.description &&

{sectionData.description}

}
); };