diff --git a/src/features/Artists/Artists.tsx b/src/features/Artists/Artists.tsx index 5013d5b..cee00d6 100644 --- a/src/features/Artists/Artists.tsx +++ b/src/features/Artists/Artists.tsx @@ -1,11 +1,12 @@ import React, { useState } from 'react'; import { IonSearchbar, IonModal, IonHeader, IonToolbar, IonTitle, IonButton, IonIcon, IonContent, IonItem } from '@ionic/react'; import { close, list } from 'ionicons/icons'; -import { InfiniteScrollList, SongItem, ListItem, NumberDisplay } from '../../components/common'; +import { InfiniteScrollList, SongItem, ListItem, NumberDisplay, SongInfo } from '../../components/common'; import { useArtists } from '../../hooks'; import { useAppSelector } from '../../redux'; import { selectSongs } from '../../redux'; import { debugLog } from '../../utils/logger'; +import type { Song } from '../../types'; const Artists: React.FC = () => { const { @@ -22,6 +23,8 @@ const Artists: React.FC = () => { const songs = useAppSelector(selectSongs); const songsCount = Object.keys(songs).length; const [selectedArtist, setSelectedArtist] = useState(null); + const [selectedSong, setSelectedSong] = useState(null); + const [isSongInfoOpen, setIsSongInfoOpen] = useState(false); // Debug logging debugLog('Artists component - artists count:', artists.length); @@ -37,6 +40,16 @@ const Artists: React.FC = () => { setSelectedArtist(null); }; + const handleSongInfo = (song: Song) => { + setSelectedSong(song); + setIsSongInfoOpen(true); + }; + + const handleCloseSongInfo = () => { + setIsSongInfoOpen(false); + setSelectedSong(null); + }; + const selectedArtistSongs = selectedArtist ? getSongsByArtist(selectedArtist) : []; // Render artist item for InfiniteScrollList @@ -135,7 +148,7 @@ const Artists: React.FC = () => { song={song} context="search" onAddToQueue={() => handleAddToQueue(song)} - onSelectSinger={() => {}} // Info button functionality + onSelectSinger={() => handleSongInfo(song)} showAddButton={true} showInfoButton={true} showFavoriteButton={false} @@ -150,6 +163,15 @@ const Artists: React.FC = () => { + + {/* Song Info Modal */} + {selectedSong && ( + + )} ); diff --git a/src/features/History/History.tsx b/src/features/History/History.tsx index a7372c9..abcc322 100644 --- a/src/features/History/History.tsx +++ b/src/features/History/History.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { IonChip, IonIcon } from '@ionic/react'; import { time } from 'ionicons/icons'; -import { InfiniteScrollList, SongItem } from '../../components/common'; +import { InfiniteScrollList, SongItem, SongInfo } from '../../components/common'; import { useHistory } from '../../hooks'; import { useAppSelector } from '../../redux'; import { selectHistory, selectIsAdmin } from '../../redux'; @@ -21,11 +21,23 @@ const History: React.FC = () => { const history = useAppSelector(selectHistory); const isAdmin = useAppSelector(selectIsAdmin); const historyCount = Object.keys(history).length; + const [selectedSong, setSelectedSong] = React.useState(null); + const [isSongInfoOpen, setIsSongInfoOpen] = React.useState(false); // Debug logging debugLog('History component - history count:', historyCount); debugLog('History component - history items:', historyItems); + const handleSongInfo = (song: Song) => { + setSelectedSong(song); + setIsSongInfoOpen(true); + }; + + const handleCloseSongInfo = () => { + setIsSongInfoOpen(false); + setSelectedSong(null); + }; + // Render extra content for history items (play date) const renderExtraContent = (item: Song) => { if (item.date) { @@ -53,7 +65,7 @@ const History: React.FC = () => { song={song} context="history" onAddToQueue={() => handleAddToQueue(song)} - onSelectSinger={() => {}} // Info button functionality + onSelectSinger={() => handleSongInfo(song)} onDeleteItem={() => handleDeleteFromHistory(song)} isAdmin={isAdmin} showAddButton={true} @@ -70,6 +82,15 @@ const History: React.FC = () => { loadingTitle="Loading history..." loadingMessage="Please wait while history data is being loaded" /> + + {/* Song Info Modal */} + {selectedSong && ( + + )} ); }; diff --git a/src/features/NewSongs/NewSongs.tsx b/src/features/NewSongs/NewSongs.tsx index 3bed91f..f6799ea 100644 --- a/src/features/NewSongs/NewSongs.tsx +++ b/src/features/NewSongs/NewSongs.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { InfiniteScrollList, SongItem } from '../../components/common'; +import { InfiniteScrollList, SongItem, SongInfo } from '../../components/common'; import { useNewSongs } from '../../hooks'; import { useAppSelector } from '../../redux'; import { selectNewSongsArray } from '../../redux'; @@ -16,11 +16,23 @@ const NewSongs: React.FC = () => { const newSongsArray = useAppSelector(selectNewSongsArray); const newSongsCount = newSongsArray.length; + const [selectedSong, setSelectedSong] = React.useState(null); + const [isSongInfoOpen, setIsSongInfoOpen] = React.useState(false); // Debug logging debugLog('NewSongs component - new songs count:', newSongsCount); debugLog('NewSongs component - new songs items:', newSongsItems); + const handleSongInfo = (song: Song) => { + setSelectedSong(song); + setIsSongInfoOpen(true); + }; + + const handleCloseSongInfo = () => { + setIsSongInfoOpen(false); + setSelectedSong(null); + }; + return ( <> @@ -33,6 +45,7 @@ const NewSongs: React.FC = () => { song={song} context="search" onAddToQueue={() => handleAddToQueue(song)} + onSelectSinger={() => handleSongInfo(song)} showAddButton={true} showInfoButton={true} showFavoriteButton={false} @@ -43,6 +56,15 @@ const NewSongs: React.FC = () => { loadingTitle="Loading new songs..." loadingMessage="Please wait while new songs data is being loaded" /> + + {/* Song Info Modal */} + {selectedSong && ( + + )} ); }; diff --git a/src/features/SongLists/SongLists.tsx b/src/features/SongLists/SongLists.tsx index ca9de7b..690bef8 100644 --- a/src/features/SongLists/SongLists.tsx +++ b/src/features/SongLists/SongLists.tsx @@ -1,7 +1,7 @@ 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 { InfiniteScrollList, SongItem, ListItem, TwoLineDisplay, NumberDisplay, SongInfo } from '../../components/common'; import { useSongLists } from '../../hooks'; import { useAppSelector } from '../../redux'; import { selectSongList } from '../../redux'; @@ -22,6 +22,8 @@ const SongLists: React.FC = () => { const songListCount = Object.keys(songListData).length; const [selectedSongList, setSelectedSongList] = useState(null); const [expandedSongKey, setExpandedSongKey] = useState(null); + const [selectedSong, setSelectedSong] = useState(null); + const [isSongInfoOpen, setIsSongInfoOpen] = useState(false); @@ -39,6 +41,16 @@ const SongLists: React.FC = () => { setExpandedSongKey(expandedSongKey === songKey ? null : songKey); }, [expandedSongKey]); + const handleSongInfo = useCallback((song: Song) => { + setSelectedSong(song); + setIsSongInfoOpen(true); + }, []); + + const handleCloseSongInfo = useCallback(() => { + setIsSongInfoOpen(false); + setSelectedSong(null); + }, []); + const finalSelectedList = selectedSongList ? allSongLists.find(list => list.key === selectedSongList) : null; @@ -132,7 +144,7 @@ const SongLists: React.FC = () => { song={song} context="search" onAddToQueue={() => handleAddToQueue(song)} - onSelectSinger={() => {}} // Info button functionality + onSelectSinger={() => handleSongInfo(song)} showAddButton={true} showInfoButton={true} showFavoriteButton={false} @@ -173,6 +185,15 @@ const SongLists: React.FC = () => { + + {/* Song Info Modal */} + {selectedSong && ( + + )} ); diff --git a/src/features/TopPlayed/Top100.tsx b/src/features/TopPlayed/Top100.tsx index e9f60db..7a30102 100644 --- a/src/features/TopPlayed/Top100.tsx +++ b/src/features/TopPlayed/Top100.tsx @@ -4,7 +4,7 @@ import { close, list } from 'ionicons/icons'; import { useTopPlayed } from '../../hooks'; import { useAppSelector } from '../../redux'; import { selectTopPlayed, selectSongsArray } from '../../redux'; -import { InfiniteScrollList, SongItem, ListItem } from '../../components/common'; +import { InfiniteScrollList, SongItem, ListItem, SongInfo } from '../../components/common'; import { filterSongs } from '../../utils/dataProcessing'; import { debugLog } from '../../utils/logger'; import { useSongOperations } from '../../hooks'; @@ -27,6 +27,8 @@ const Top100: React.FC = () => { const { addToQueue } = useSongOperations(); const { showSuccess, showError } = useToast(); const [selectedTopPlayed, setSelectedTopPlayed] = useState(null); + const [selectedSong, setSelectedSong] = useState(null); + const [isSongInfoOpen, setIsSongInfoOpen] = useState(false); debugLog('Top100 component - Redux data:', { topPlayedCount, topPlayedItems: topPlayedItems.length }); @@ -38,6 +40,16 @@ const Top100: React.FC = () => { setSelectedTopPlayed(null); }, []); + const handleSongInfo = useCallback((song: Song) => { + setSelectedSong(song); + setIsSongInfoOpen(true); + }, []); + + const handleCloseSongInfo = useCallback(() => { + setIsSongInfoOpen(false); + setSelectedSong(null); + }, []); + // Find songs that match the selected top played item const selectedSongs = useMemo(() => { if (!selectedTopPlayed) return []; @@ -141,7 +153,7 @@ const Top100: React.FC = () => { song={song} context="search" onAddToQueue={() => handleAddToQueue(song)} - onSelectSinger={() => {}} // Info button functionality + onSelectSinger={() => handleSongInfo(song)} showAddButton={true} showInfoButton={true} showFavoriteButton={false} @@ -150,6 +162,15 @@ const Top100: React.FC = () => { + + {/* Song Info Modal */} + {selectedSong && ( + + )} ); };