import React, { useState, useMemo, useCallback } from 'react'; import { IonItem, IonModal, IonHeader, IonToolbar, IonTitle, IonButton, IonIcon, IonChip, IonContent, IonList, IonAccordionGroup, IonAccordion } from '@ionic/react'; import { close, list } from 'ionicons/icons'; import { InfiniteScrollList, SongItem, ListItem, TwoLineDisplay, NumberDisplay } from '../../components/common'; import { useSongLists } from '../../hooks'; import { useAppSelector } from '../../redux'; import { selectSongList } from '../../redux'; import type { SongListSong, SongList, Song } from '../../types'; const SongLists: React.FC = () => { const { songLists, allSongLists, hasMore, loadMore, checkSongAvailability, handleAddToQueue, handleToggleFavorite, } = useSongLists(); const songListData = useAppSelector(selectSongList); const songListCount = Object.keys(songListData).length; const [selectedSongList, setSelectedSongList] = useState(null); const [expandedSongKey, setExpandedSongKey] = useState(null); const handleSongListClick = (songListKey: string) => { setSelectedSongList(songListKey); setExpandedSongKey(null); // Reset expansion when opening a new song list }; const handleCloseSongList = () => { setSelectedSongList(null); setExpandedSongKey(null); // Reset expansion when closing }; const handleSongItemClick = useCallback((songKey: string) => { setExpandedSongKey(expandedSongKey === songKey ? null : songKey); }, [expandedSongKey]); const finalSelectedList = selectedSongList ? allSongLists.find(list => list.key === selectedSongList) : null; // Pre-calculate available songs for the selected list to avoid repeated calculations const selectedListWithAvailability = useMemo(() => { if (!finalSelectedList) return null; return { ...finalSelectedList, songs: finalSelectedList.songs.map(songListSong => ({ ...songListSong, availableSongs: checkSongAvailability(songListSong) })) }; }, [finalSelectedList, checkSongAvailability]); // Render song list item for InfiniteScrollList const renderSongListItem = (songList: SongList) => ( handleSongListClick(songList.key!)} /> ); return ( <>
items={songLists} isLoading={songListCount === 0} hasMore={hasMore} onLoadMore={loadMore} renderItem={renderSongListItem} emptyTitle="No song lists available" emptyMessage="Song lists will appear here when they're available" loadingTitle="Loading song lists..." loadingMessage="Please wait while song lists are being loaded" /> {/* Song List Modal */} {finalSelectedList?.title} {selectedListWithAvailability?.songs.map((songListSong: SongListSong & { availableSongs: Song[] }, index) => { const availableSongs = songListSong.availableSongs; const isAvailable = availableSongs.length > 0; const songKey = songListSong.key || `${songListSong.title}-${songListSong.position}-${index}`; if (isAvailable) { // Available songs get an accordion that expands return ( handleSongItemClick(songKey)}> {/* Number */} {/* Use TwoLineDisplay for consistent formatting */} {availableSongs.length} version{availableSongs.length !== 1 ? 's' : ''}
{availableSongs.map((song: Song, sidx) => ( handleAddToQueue(song)} onToggleFavorite={() => handleToggleFavorite(song)} /> ))}
); } else { // Unavailable songs get a simple item return ( {/* Number */} {/* Use TwoLineDisplay for consistent formatting with disabled styling */} ); } })}
); }; export default SongLists;