146 lines
4.8 KiB
TypeScript
146 lines
4.8 KiB
TypeScript
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 { useLocation, useNavigate } from 'react-router-dom';
|
|
|
|
const Navigation: React.FC = () => {
|
|
const location = useLocation();
|
|
const navigate = useNavigate();
|
|
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 },
|
|
];
|
|
|
|
// Check screen size for responsive menu behavior
|
|
useEffect(() => {
|
|
const checkScreenSize = () => {
|
|
const large = window.innerWidth >= 768;
|
|
console.log('Screen width:', window.innerWidth, 'Is large screen:', large);
|
|
setIsLargeScreen(large);
|
|
};
|
|
|
|
checkScreenSize();
|
|
window.addEventListener('resize', checkScreenSize);
|
|
return () => window.removeEventListener('resize', checkScreenSize);
|
|
}, []);
|
|
|
|
const handleNavigation = (path: string) => {
|
|
navigate(path);
|
|
// Close menu on mobile after navigation
|
|
if (!isLargeScreen) {
|
|
const menu = document.querySelector('ion-menu');
|
|
if (menu) {
|
|
menu.close();
|
|
}
|
|
}
|
|
};
|
|
|
|
// For large screens, render a fixed sidebar instead of a menu
|
|
if (isLargeScreen) {
|
|
console.log('Rendering large screen sidebar');
|
|
return (
|
|
<div
|
|
style={{
|
|
position: 'fixed',
|
|
left: 0,
|
|
top: 0,
|
|
height: '100vh',
|
|
width: '256px',
|
|
backgroundColor: 'white',
|
|
boxShadow: '2px 0 8px rgba(0,0,0,0.1)',
|
|
zIndex: 1000,
|
|
borderRight: '1px solid #e5e7eb',
|
|
overflowY: 'auto'
|
|
}}
|
|
>
|
|
<div style={{ padding: '16px', borderBottom: '1px solid #e5e7eb', backgroundColor: '#f9fafb' }}>
|
|
<h2 style={{ fontSize: '18px', fontWeight: '600', color: '#1f2937', margin: 0 }}>Karaoke</h2>
|
|
<p style={{ fontSize: '14px', color: '#6b7280', margin: '4px 0 0 0' }}>Singer: Matt</p>
|
|
</div>
|
|
<nav style={{ marginTop: '16px' }}>
|
|
{navItems.map((item) => (
|
|
<div
|
|
key={item.path}
|
|
onClick={() => handleNavigation(item.path)}
|
|
style={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
padding: '12px 16px',
|
|
cursor: 'pointer',
|
|
backgroundColor: location.pathname === item.path ? '#dbeafe' : 'transparent',
|
|
color: location.pathname === item.path ? '#2563eb' : '#374151',
|
|
borderRight: location.pathname === item.path ? '2px solid #2563eb' : 'none',
|
|
transition: 'background-color 0.2s, color 0.2s'
|
|
}}
|
|
onMouseEnter={(e) => {
|
|
if (location.pathname !== item.path) {
|
|
e.currentTarget.style.backgroundColor = '#f3f4f6';
|
|
}
|
|
}}
|
|
onMouseLeave={(e) => {
|
|
if (location.pathname !== item.path) {
|
|
e.currentTarget.style.backgroundColor = 'transparent';
|
|
}
|
|
}}
|
|
>
|
|
<IonIcon
|
|
icon={item.icon}
|
|
style={{
|
|
marginRight: '12px',
|
|
fontSize: '20px'
|
|
}}
|
|
/>
|
|
<span style={{ fontWeight: '500' }}>{item.label}</span>
|
|
</div>
|
|
))}
|
|
</nav>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// For mobile screens, use the Ionic menu
|
|
console.log('Rendering mobile menu');
|
|
return (
|
|
<IonMenu
|
|
contentId="main-content"
|
|
type="overlay"
|
|
side="start"
|
|
swipeGesture={true}
|
|
style={{
|
|
'--width': '250px'
|
|
} as React.CSSProperties}
|
|
>
|
|
<IonHeader>
|
|
<IonToolbar>
|
|
<IonTitle>Menu</IonTitle>
|
|
</IonToolbar>
|
|
</IonHeader>
|
|
<IonContent>
|
|
<IonList>
|
|
{navItems.map((item) => (
|
|
<IonItem
|
|
key={item.path}
|
|
button
|
|
onClick={() => handleNavigation(item.path)}
|
|
className={location.pathname === item.path ? 'ion-activated' : ''}
|
|
>
|
|
<IonIcon icon={item.icon} slot="start" />
|
|
<IonLabel>{item.label}</IonLabel>
|
|
</IonItem>
|
|
))}
|
|
</IonList>
|
|
</IonContent>
|
|
</IonMenu>
|
|
);
|
|
};
|
|
|
|
export default Navigation;
|