diff --git a/src/features/Artists/Artists.tsx b/src/features/Artists/Artists.tsx index 6e0512e..7cacf6e 100644 --- a/src/features/Artists/Artists.tsx +++ b/src/features/Artists/Artists.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect, useRef } from 'react'; -import { IonSearchbar, IonList, IonItem, IonLabel, IonModal, IonHeader, IonToolbar, IonTitle, IonContent, IonButton, IonIcon, IonChip } from '@ionic/react'; +import { IonSearchbar, IonList, IonItem, IonLabel, IonModal, IonHeader, IonToolbar, IonTitle, IonButton, IonIcon, IonChip } from '@ionic/react'; import { close, add, heart, heartOutline } from 'ionicons/icons'; import { useArtists } from '../../hooks'; import { useAppSelector } from '../../redux'; @@ -68,133 +68,140 @@ const Artists: React.FC = () => { const selectedArtistSongs = selectedArtist ? getSongsByArtist(selectedArtist) : []; return ( -
-
-

Artists

- - {/* Search Input */} - handleSearchChange(e.detail.value || '')} - debounce={300} - showClearButton="focus" - /> + <> + + + Artists + + +
+
+

Artists

+ + {/* Search Input */} + handleSearchChange(e.detail.value || '')} + debounce={300} + showClearButton="focus" + /> - {/* Debug info */} -
- Total songs loaded: {songsCount} | Showing: {artists.length} of {allArtists.length} artists | Search term: "{searchTerm}" + {/* Debug info */} +
+ Total songs loaded: {songsCount} | Showing: {artists.length} of {allArtists.length} artists | Search term: "{searchTerm}" +
-
- {/* Artists List */} -
- {songsCount === 0 ? ( -
-
- - - -
-

Loading artists...

-

Please wait while songs are being loaded from the database

-
- ) : artists.length === 0 ? ( -
-
- - - -
-

- {searchTerm ? "No artists found" : "No artists available"} -

-

- {searchTerm ? "Try adjusting your search terms" : "Artists will appear here once songs are loaded"} -

-
- ) : ( - - {artists.map((artist) => ( - handleArtistClick(artist)}> - -

- {artist} -

-

- {getSongCountByArtist(artist)} song{getSongCountByArtist(artist) !== 1 ? 's' : ''} -

-
- - View Songs - -
- ))} - - {/* Infinite scroll trigger */} - {hasMore && ( -
-
- - - - - Loading more artists... -
+ {/* Artists List */} +
+ {songsCount === 0 ? ( +
+
+ + +
- )} - - )} -
- - {/* Artist Songs Modal */} - - - - Songs by {selectedArtist} - - - - - - - - - {selectedArtistSongs.map((song) => ( - - -

- {song.title} -

-

- {song.artist} -

-
-
- handleAddToQueue(song)} - > - - - handleToggleFavorite(song)} - > - - +

Loading artists...

+

Please wait while songs are being loaded from the database

+
+ ) : artists.length === 0 ? ( +
+
+ + + +
+

+ {searchTerm ? "No artists found" : "No artists available"} +

+

+ {searchTerm ? "Try adjusting your search terms" : "Artists will appear here once songs are loaded"} +

+
+ ) : ( + + {artists.map((artist) => ( + handleArtistClick(artist)}> + +

+ {artist} +

+

+ {getSongCountByArtist(artist)} song{getSongCountByArtist(artist) !== 1 ? 's' : ''} +

+
+ + View Songs + +
+ ))} + + {/* Infinite scroll trigger */} + {hasMore && ( +
+
+ + + + + Loading more artists... +
-
- ))} -
-
-
-
+ )} + + )} +
+ + {/* Artist Songs Modal */} + + + + Songs by {selectedArtist} + + + + + + +
+ + {selectedArtistSongs.map((song) => ( + + +

+ {song.title} +

+

+ {song.artist} +

+
+
+ handleAddToQueue(song)} + > + + + handleToggleFavorite(song)} + > + + +
+
+ ))} +
+
+
+
+ ); }; diff --git a/src/features/Favorites/Favorites.tsx b/src/features/Favorites/Favorites.tsx index 4a10a07..6304f44 100644 --- a/src/features/Favorites/Favorites.tsx +++ b/src/features/Favorites/Favorites.tsx @@ -34,24 +34,22 @@ const Favorites: React.FC = () => { -
- -
+ ); }; diff --git a/src/features/NewSongs/NewSongs.tsx b/src/features/NewSongs/NewSongs.tsx index d21e561..513dcf5 100644 --- a/src/features/NewSongs/NewSongs.tsx +++ b/src/features/NewSongs/NewSongs.tsx @@ -34,24 +34,22 @@ const NewSongs: React.FC = () => { -
- -
+ ); }; diff --git a/src/features/Singers/Singers.tsx b/src/features/Singers/Singers.tsx index 081ce5b..28a8b0f 100644 --- a/src/features/Singers/Singers.tsx +++ b/src/features/Singers/Singers.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { IonHeader, IonToolbar, IonTitle, IonContent, IonList, IonItem, IonLabel, IonItemSliding, IonItemOptions, IonItemOption, IonIcon, IonChip } from '@ionic/react'; +import { IonHeader, IonToolbar, IonTitle, IonList, IonItem, IonLabel, IonItemSliding, IonItemOptions, IonItemOption, IonIcon, IonChip } from '@ionic/react'; import { people, trash, time } from 'ionicons/icons'; import { EmptyState } from '../../components/common'; import { useSingers } from '../../hooks'; @@ -34,76 +34,74 @@ const Singers: React.FC = () => { - -
-

- {singers.length} singer{singers.length !== 1 ? 's' : ''} in the party -

- - {/* Debug info */} -
- Singers loaded: {singersCount} -
- - {/* Singers List */} -
- {singersCount === 0 ? ( - - - - } - /> - ) : singers.length === 0 ? ( - - - - } - /> - ) : ( - - {singers.map((singer) => ( - - - - -

- {singer.name} -

-
- - - {formatDate(singer.lastLogin)} - -
-
-
- - {/* Swipe to Remove (Admin Only) */} - {isAdmin && ( - - handleRemoveSinger(singer)} - > - - - - )} -
- ))} -
- )} -
+
+

+ {singers.length} singer{singers.length !== 1 ? 's' : ''} in the party +

+ + {/* Debug info */} +
+ Singers loaded: {singersCount}
- + + {/* Singers List */} +
+ {singersCount === 0 ? ( + + + + } + /> + ) : singers.length === 0 ? ( + + + + } + /> + ) : ( + + {singers.map((singer) => ( + + + + +

+ {singer.name} +

+
+ + + {formatDate(singer.lastLogin)} + +
+
+
+ + {/* Swipe to Remove (Admin Only) */} + {isAdmin && ( + + handleRemoveSinger(singer)} + > + + + + )} +
+ ))} +
+ )} +
+
); }; diff --git a/src/features/SongLists/SongLists.tsx b/src/features/SongLists/SongLists.tsx index 692af0b..a7311cd 100644 --- a/src/features/SongLists/SongLists.tsx +++ b/src/features/SongLists/SongLists.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect, useRef } from 'react'; -import { IonHeader, IonToolbar, IonTitle, IonContent, IonList, IonItem, IonLabel, IonModal, IonButton, IonIcon, IonChip, IonAccordion, IonAccordionGroup } from '@ionic/react'; +import { IonHeader, IonToolbar, IonTitle, IonList, IonItem, IonLabel, IonModal, IonButton, IonIcon, IonChip, IonAccordion, IonAccordionGroup } from '@ionic/react'; import { close, documentText, add, heart, heartOutline } from 'ionicons/icons'; import { useSongLists } from '../../hooks'; import { useAppSelector } from '../../redux'; @@ -95,78 +95,76 @@ const SongLists: React.FC = () => { - -
-

- {songLists.length} song list{songLists.length !== 1 ? 's' : ''} available -

- - {/* Debug info */} -
- Song lists loaded: {songListCount} -
- - {/* Song Lists */} -
- {songListCount === 0 ? ( -
-
- - - -
-

Loading song lists...

-

Please wait while song lists are being loaded

-
- ) : songLists.length === 0 ? ( -
-
- - - -
-

No song lists available

-

Song lists will appear here when they're available

-
- ) : ( - - {songLists.map((songList) => ( - handleSongListClick(songList.key!)}> - - -

- {songList.title} -

-

- {songList.songs.length} song{songList.songs.length !== 1 ? 's' : ''} -

-
- - View Songs - -
- ))} - - {/* Infinite scroll trigger */} - {hasMore && ( -
-
- - - - - Loading more song lists... -
-
- )} -
- )} -
+
+

+ {songLists.length} song list{songLists.length !== 1 ? 's' : ''} available +

+ + {/* Debug info */} +
+ Song lists loaded: {songListCount}
- + + {/* Song Lists */} +
+ {songListCount === 0 ? ( +
+
+ + + +
+

Loading song lists...

+

Please wait while song lists are being loaded

+
+ ) : songLists.length === 0 ? ( +
+
+ + + +
+

No song lists available

+

Song lists will appear here when they're available

+
+ ) : ( + + {songLists.map((songList) => ( + handleSongListClick(songList.key!)}> + + +

+ {songList.title} +

+

+ {songList.songs.length} song{songList.songs.length !== 1 ? 's' : ''} +

+
+ + View Songs + +
+ ))} + + {/* Infinite scroll trigger */} + {hasMore && ( +
+
+ + + + + Loading more song lists... +
+
+ )} +
+ )} +
+
{/* Song List Modal */} @@ -178,8 +176,8 @@ const SongLists: React.FC = () => { - - + {/* Remove IonContent, use a div instead */} +
{finalSelectedList?.songs.map((songListSong: SongListSong, idx) => { const availableSongs = checkSongAvailability(songListSong); @@ -212,7 +210,7 @@ const SongLists: React.FC = () => { {isAvailable ? ( {availableSongs.map((song: Song, sidx) => ( - +

{song.title} @@ -250,7 +248,7 @@ const SongLists: React.FC = () => { ); })} - +

); diff --git a/src/features/TopPlayed/Top100.tsx b/src/features/TopPlayed/Top100.tsx index ee9c145..7ee4f71 100644 --- a/src/features/TopPlayed/Top100.tsx +++ b/src/features/TopPlayed/Top100.tsx @@ -1,14 +1,17 @@ import React from 'react'; import { IonHeader, IonToolbar, IonTitle, IonChip, IonIcon } from '@ionic/react'; +import { trophy } from 'ionicons/icons'; import { InfiniteScrollList } from '../../components/common'; import { useTopPlayed } from '../../hooks'; import { useAppSelector } from '../../redux'; import { selectTopPlayed } from '../../redux'; +import type { TopPlayed, Song } from '../../types'; + +const Top100: React.FC = () => { + console.log('Top100 component - RENDERING START'); -const TopPlayed: React.FC = () => { const { topPlayedItems, - hasMore, loadMore, handleAddToQueue, handleToggleFavorite, @@ -17,18 +20,110 @@ const TopPlayed: React.FC = () => { const topPlayed = useAppSelector(selectTopPlayed); const topPlayedCount = Object.keys(topPlayed).length; - // Debug logging - console.log('TopPlayed component - top played count:', topPlayedCount); - console.log('TopPlayed component - top played items:', topPlayedItems); + console.log('Top100 component - Redux data:', { topPlayedCount, topPlayedItems: topPlayedItems.length }); - const renderExtraContent = (item: any, index: number) => ( -
-
- - #{index + 1} -
-
- ); + // Mock data for testing + const mockTopPlayedItems: TopPlayed[] = [ + { + key: 'mock-1', + title: 'Bohemian Rhapsody', + artist: 'Queen', + count: 156 + }, + { + key: 'mock-2', + title: 'Sweet Caroline', + artist: 'Neil Diamond', + count: 142 + }, + { + key: 'mock-3', + title: 'Don\'t Stop Believin\'', + artist: 'Journey', + count: 128 + }, + { + key: 'mock-4', + title: 'Livin\' on a Prayer', + artist: 'Bon Jovi', + count: 115 + }, + { + key: 'mock-5', + title: 'Wonderwall', + artist: 'Oasis', + count: 98 + }, + { + key: 'mock-6', + title: 'Hotel California', + artist: 'Eagles', + count: 87 + }, + { + key: 'mock-7', + title: 'Stairway to Heaven', + artist: 'Led Zeppelin', + count: 76 + }, + { + key: 'mock-8', + title: 'Imagine', + artist: 'John Lennon', + count: 65 + }, + { + key: 'mock-9', + title: 'Hey Jude', + artist: 'The Beatles', + count: 54 + }, + { + key: 'mock-10', + title: 'Yesterday', + artist: 'The Beatles', + count: 43 + } + ]; + + // Convert TopPlayed items to Song format for consistent UI + const songItems: Song[] = mockTopPlayedItems.map((item: TopPlayed) => ({ + ...item, + path: '', // TopPlayed doesn't have path + disabled: false, + favorite: false, + })); + + // Use mock data for now + const displayItems = songItems; + const displayCount = songItems.length; + const displayHasMore = false; // No more mock data to load + + console.log('Top100 component - Mock data:', { + displayItems: displayItems.length, + displayCount, + displayHasMore, + firstItem: displayItems[0] + }); + + console.log('Top100 component - About to render JSX'); + + // Wrapper functions to handle type conversion + const handleAddToQueueWrapper = (song: Song) => { + console.log('Top100 component - Add to Queue clicked:', song); + const topPlayedItem = mockTopPlayedItems.find(item => item.key === song.key); + if (topPlayedItem) { + handleAddToQueue(topPlayedItem); + } + }; + + const handleToggleFavoriteWrapper = (song: Song) => { + console.log('Top100 component - Remove clicked:', song); + const topPlayedItem = mockTopPlayedItems.find(item => item.key === song.key); + if (topPlayedItem) { + handleToggleFavorite(topPlayedItem); + } + }; return ( <> @@ -37,33 +132,41 @@ const TopPlayed: React.FC = () => { Top 100 Played - {topPlayedItems.length} + {displayItems.length} -
- -
+ ( +
+
+ + #{index + 1} +
+ + {item.count} play{item.count !== 1 ? 's' : ''} + +
+ )} + /> ); }; -export default TopPlayed; \ No newline at end of file +export default Top100; \ No newline at end of file