This repository has been archived on 2025-03-08. You can view files and clone it, but cannot push or open issues or pull requests.

128 lines
4.2 KiB
TypeScript
Raw Permalink Normal View History

2025-02-27 17:39:22 -05:00
"use client"
2025-02-27 17:39:22 -05:00
import { useState, useEffect } from "react"
import Image from "next/image"
import { Play, SkipBack, SkipForward } from "lucide-react"
import LoadingSpinner from "../objects/LoadingSpinner"
import { SeekBar } from "@/components/objects/SeekBar"
2025-01-08 09:33:27 -05:00
interface Song {
2025-02-27 17:39:22 -05:00
albumArt: string
name: string
artist: string
duration: string
link?: string
2025-01-08 09:33:27 -05:00
}
interface Period {
2025-02-27 17:39:22 -05:00
timePeriod: string
songs: Song[]
2025-01-08 09:33:27 -05:00
}
export default function Home() {
2025-02-27 17:39:22 -05:00
const [timePeriod, setTimePeriod] = useState("Early Summer 2024")
const [songs, setSongs] = useState<Song[]>([])
const [currentIndex, setCurrentIndex] = useState(0)
const [isLoading, setIsLoading] = useState(true)
const [currentPosition, setCurrentPosition] = useState(0)
useEffect(() => {
2025-02-27 17:39:22 -05:00
setIsLoading(true)
fetch("/data/music.json")
.then((response) => response.json())
2025-01-08 09:33:27 -05:00
.then((data: Period[]) => {
2025-02-27 17:39:22 -05:00
const selectedPeriod = data.find((period) => period.timePeriod === timePeriod)
const songsList = selectedPeriod ? selectedPeriod.songs : []
setSongs(songsList)
const newIndex = Math.floor(Math.random() * songsList.length)
setCurrentIndex(newIndex)
// Set initial random position for the selected song
if (songsList.length > 0) {
const durationInSeconds = parseDuration(songsList[newIndex]?.duration || "0:00")
setCurrentPosition(Math.floor(Math.random() * durationInSeconds))
}
setIsLoading(false)
2025-01-08 09:33:27 -05:00
})
2025-02-27 17:39:22 -05:00
.catch((error) => {
console.error("Error fetching music data:", error)
setIsLoading(false)
})
}, [timePeriod])
const handleNext = () => {
2025-02-27 17:39:22 -05:00
setCurrentIndex((prevIndex) => {
const nextIndex = (prevIndex + 1) % songs.length
const durationInSeconds = parseDuration(songs[nextIndex].duration)
setCurrentPosition(Math.floor(Math.random() * durationInSeconds))
return nextIndex
})
}
const handlePrevious = () => {
2025-02-27 17:39:22 -05:00
setCurrentIndex((prevIndex) => {
const nextIndex = (prevIndex - 1 + songs.length) % songs.length
const durationInSeconds = parseDuration(songs[nextIndex].duration)
setCurrentPosition(Math.floor(Math.random() * durationInSeconds))
return nextIndex
})
}
const parseDuration = (duration: string): number => {
const [minutes, seconds] = duration.split(":").map(Number)
return minutes * 60 + seconds
}
return (
2025-02-27 17:39:22 -05:00
<div>
<section id="music-carousel" className="mb-12">
2025-02-27 17:39:22 -05:00
{isLoading && <LoadingSpinner />}
{!isLoading && songs.length > 0 && (
<div className="relative">
<Image
src={songs[currentIndex].albumArt || "/placeholder.svg"}
alt={songs[currentIndex].name}
width={300}
height={300}
className="mb-4 rounded-lg"
/>
<h3 className="text-2xl font-bold text-gray-100">{songs[currentIndex].name}</h3>
<p>{songs[currentIndex].artist}</p>
<SeekBar
key={`${currentIndex}-${currentPosition}`}
startPos={currentPosition}
duration={songs[currentIndex].duration}
/>
<div className="flex justify-center pb-2">
<button onClick={handlePrevious} className="mr-4 cursor-pointer">
<SkipBack className="w-8 h-8" />
</button>
<button className="mr-4 cursor-pointer" onClick={() => window.open(songs[currentIndex]?.link, "_blank")}>
<Play className="w-8 h-8" />
</button>
<button onClick={handleNext} className="cursor-pointer">
<SkipForward className="w-8 h-8" />
</button>
</div>
</div>
)}
<div className="flex flex-col items-center mt-4">
<label htmlFor="timePeriod" className="font-bold uppercase text-sm pb-1">
Time Period
</label>
<select
id="timePeriod"
value={timePeriod}
onChange={(e) => setTimePeriod(e.target.value)}
2025-02-27 17:39:22 -05:00
className="px-3 py-2 bg-gray-700 rounded-sm mb-2"
>
<option value="Early Summer 2024">Early Summer 2024</option>
</select>
</div>
</section>
</div>
2025-02-27 17:39:22 -05:00
)
2025-01-08 09:33:27 -05:00
}