diff --git a/docs/design/02a-menu.jpeg b/docs/design/02a-menu.jpeg new file mode 100644 index 0000000..570f5a2 Binary files /dev/null and b/docs/design/02a-menu.jpeg differ diff --git a/docs/design/02b-menu.png b/docs/design/02b-menu.png new file mode 100644 index 0000000..269a8e7 Binary files /dev/null and b/docs/design/02b-menu.png differ diff --git a/docs/design/02c-menu.jpeg b/docs/design/02c-menu.jpeg new file mode 100644 index 0000000..560729f Binary files /dev/null and b/docs/design/02c-menu.jpeg differ diff --git a/src/components/Navigation/Navigation.tsx b/src/components/Navigation/Navigation.tsx index c5eb310..4895f9d 100644 --- a/src/components/Navigation/Navigation.tsx +++ b/src/components/Navigation/Navigation.tsx @@ -1,7 +1,8 @@ import React, { useState, useEffect } from 'react'; import { IonMenu, IonHeader, IonToolbar, IonTitle, IonContent, IonList, IonItem, IonLabel, IonIcon } from '@ionic/react'; -import { list, search, heart, add, mic, documentText, time, trophy, people } from 'ionicons/icons'; +import { timeOutline, settingsOutline, listOutline, musicalNotesOutline, peopleOutline, peopleCircleOutline, heartOutline, searchOutline, starOutline } from 'ionicons/icons'; import { useLocation, useNavigate } from 'react-router-dom'; +import { PlayerControls } from '../common'; const Navigation: React.FC = () => { const location = useLocation(); @@ -9,15 +10,16 @@ const Navigation: React.FC = () => { const [isLargeScreen, setIsLargeScreen] = useState(false); const navItems = [ - { path: '/queue', label: 'Queue', icon: list }, - { path: '/search', label: 'Search', icon: search }, - { path: '/favorites', label: 'Favorites', icon: heart }, - { path: '/new-songs', label: 'New Songs', icon: add }, - { path: '/artists', label: 'Artists', icon: mic }, - { path: '/song-lists', label: 'Song Lists', icon: documentText }, - { path: '/history', label: 'History', icon: time }, - { path: '/top-played', label: 'Top 100', icon: trophy }, - { path: '/singers', label: 'Singers', icon: people }, + { path: '/search', label: 'Search', icon: searchOutline }, + { path: '/queue', label: 'Queue', icon: musicalNotesOutline }, + { path: '/singers', label: 'Singers', icon: peopleCircleOutline }, + { path: '/artists', label: 'Artists', icon: peopleOutline }, + { path: '/top-played', label: 'Top 100 Played', icon: starOutline }, + { path: '/favorites', label: 'Favorites', icon: heartOutline }, + { path: '/history', label: 'History', icon: timeOutline }, + { path: '/new-songs', label: 'New Songs', icon: listOutline }, + { path: '/song-lists', label: 'Song Lists', icon: listOutline }, + { path: '/settings', label: 'Settings', icon: settingsOutline }, ]; // Check screen size for responsive menu behavior @@ -103,6 +105,11 @@ const Navigation: React.FC = () => { ))} + + {/* Player Controls */} +
+ +
); } @@ -138,6 +145,11 @@ const Navigation: React.FC = () => { ))} + + {/* Player Controls for Mobile */} +
+ +
); diff --git a/src/components/common/PlayerControls.tsx b/src/components/common/PlayerControls.tsx index 473caac..4601604 100644 --- a/src/components/common/PlayerControls.tsx +++ b/src/components/common/PlayerControls.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { IonCard, IonCardContent, IonChip, IonIcon } from '@ionic/react'; -import { play, pause, stop } from 'ionicons/icons'; +import { playOutline, pauseOutline, stopOutline, play, pause, stop } from 'ionicons/icons'; import ActionButton from './ActionButton'; import { useAppSelector } from '../../redux'; import { selectPlayerState, selectIsAdmin, selectQueue } from '../../redux'; @@ -11,9 +11,10 @@ import { PlayerState } from '../../types'; interface PlayerControlsProps { className?: string; + variant?: 'light' | 'dark'; } -const PlayerControls: React.FC = ({ className = '' }) => { +const PlayerControls: React.FC = ({ className = '', variant = 'light' }) => { const playerState = useAppSelector(selectPlayerState); const isAdmin = useAppSelector(selectIsAdmin); const controllerName = useAppSelector(selectControllerName); @@ -83,6 +84,88 @@ const PlayerControls: React.FC = ({ className = '' }) => { } }; + const getStatusText = () => { + switch (currentState) { + case PlayerState.playing: + return 'Currently Playing'; + case PlayerState.paused: + return 'Currently Paused'; + default: + return 'Currently Stopped'; + } + }; + + // Dark mode variant + if (variant === 'dark') { + return ( +
+ {/* Status Text */} +
+

{getStatusText()}

+
+ + {/* Control Buttons */} +
+ {currentState === PlayerState.playing ? ( +
+ + Pause +
+ ) : ( +
+ + Play +
+ )} + + {currentState !== PlayerState.stopped && ( +
+ + Stop +
+ )} +
+ + {!hasSongsInQueue && ( +
+ Add songs to queue to enable playback controls +
+ )} +
+ ); + } + + // Light mode variant (original) return ( @@ -100,20 +183,18 @@ const PlayerControls: React.FC = ({ className = '' }) => { - - Pause + ) : ( - - Play + )} @@ -123,8 +204,7 @@ const PlayerControls: React.FC = ({ className = '' }) => { variant="danger" size="sm" > - - Stop + )} diff --git a/src/features/Queue/Queue.tsx b/src/features/Queue/Queue.tsx index a081490..8127e23 100644 --- a/src/features/Queue/Queue.tsx +++ b/src/features/Queue/Queue.tsx @@ -108,12 +108,14 @@ const Queue: React.FC = () => { subtitle={`${queueStats.totalSongs} song${queueStats.totalSongs !== 1 ? 's' : ''} in queue`} /> -
- {/* Player Controls - Only visible to admin users */} -
- + {/* Player Controls - Only visible to admin users */} +
+
+
+
+
{/* Queue List */} items={queueItems}