'use client'; import { useState, useRef, useEffect } from 'react'; // Configuration const BASE_URL = "https://openwheels.racing/files/music/"; // Icons function PlayIcon({ className = "w-6 h-6" }) { return ( ); } function PauseIcon({ className = "w-6 h-6" }) { return ( ); } function SkipNextIcon({ className = "w-6 h-6" }) { return ( ); } function SkipPrevIcon({ className = "w-6 h-6" }) { return ( ); } function VideoIcon({ className = "w-5 h-5" }) { return ( ); } function MusicIcon({ className = "w-5 h-5" }) { return ( ); } function RefreshIcon({ className = "w-5 h-5" }) { return ( ); } export default function MusicPage() { const [tracks, setTracks] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [currentTrackIndex, setCurrentTrackIndex] = useState(0); const [isPlaying, setIsPlaying] = useState(false); const [currentTime, setCurrentTime] = useState(0); const [duration, setDuration] = useState(0); const [selectedTheme, setSelectedTheme] = useState('all'); const mediaRef = useRef(null); // Fetch available tracks from the server const fetchTracks = async () => { setLoading(true); setError(null); try { const response = await fetch('/api/music/tracks'); if (!response.ok) { throw new Error('Failed to fetch tracks'); } const data = await response.json(); setTracks(data.tracks || []); } catch (err) { console.error('Error fetching tracks:', err); setError(err.message); // Fallback to hardcoded tracks if API fails setTracks([ { title: "Alone Again", fileName: "AloneAgain.mp4", artist: "Unknown Artist", theme: "general" }, { title: "House Music VOL1", fileName: "deephousetherapy.mp4", artist: "Deep House Therapy", theme: "house" }, { title: "House Music VOL2", fileName: "videoplayback.mp4", artist: "Various Artists", theme: "house" }, ]); } finally { setLoading(false); } }; useEffect(() => { fetchTracks(); }, []); // Group tracks by theme const tracksByTheme = tracks.reduce((acc, track) => { const theme = track.theme || 'general'; if (!acc[theme]) { acc[theme] = []; } acc[theme].push(track); return acc; }, {}); const themes = Object.keys(tracksByTheme).sort(); // Get filtered tracks based on selected theme const filteredTracks = selectedTheme === 'all' ? tracks : tracksByTheme[selectedTheme] || []; const currentTrack = filteredTracks[currentTrackIndex]; const isVideo = currentTrack?.fileName.toLowerCase().endsWith('.mp4'); useEffect(() => { if (mediaRef.current && currentTrack) { mediaRef.current.load(); if (isPlaying) { mediaRef.current.play().catch(err => { console.error('Playback error:', err); setIsPlaying(false); }); } } }, [currentTrackIndex, currentTrack]); const togglePlayPause = () => { if (mediaRef.current) { if (isPlaying) { mediaRef.current.pause(); } else { mediaRef.current.play().catch(err => { console.error('Playback error:', err); }); } setIsPlaying(!isPlaying); } }; const nextTrack = () => { if (filteredTracks.length > 0) { setCurrentTrackIndex((prev) => (prev + 1) % filteredTracks.length); setIsPlaying(true); } }; const prevTrack = () => { if (filteredTracks.length > 0) { setCurrentTrackIndex((prev) => (prev - 1 + filteredTracks.length) % filteredTracks.length); setIsPlaying(true); } }; const handleTimeUpdate = () => { if (mediaRef.current) { setCurrentTime(mediaRef.current.currentTime); setDuration(mediaRef.current.duration || 0); } }; const handleSeek = (e) => { const rect = e.currentTarget.getBoundingClientRect(); const x = e.clientX - rect.left; const percentage = x / rect.width; if (mediaRef.current) { mediaRef.current.currentTime = percentage * duration; } }; const formatTime = (time) => { if (isNaN(time)) return "0:00"; const minutes = Math.floor(time / 60); const seconds = Math.floor(time % 60); return `${minutes}:${seconds.toString().padStart(2, '0')}`; }; const handleThemeChange = (theme) => { setSelectedTheme(theme); setCurrentTrackIndex(0); setIsPlaying(false); }; if (loading) { return (
High-fidelity streaming for the racing community
LOADING TRACKS...
High-fidelity streaming for the racing community
NO TRACKS AVAILABLE
{error &&Error: {error}
}High-fidelity streaming for the racing community
{/* Theme Filter */}{currentTrack.artist}
FORMAT
MP4 / AUDIO
QUALITY
HIGH FIDELITY
TRACKS
{tracks.length} AVAILABLE
STREAMING
PROGRESSIVE LOAD