diff --git a/README.md b/README.md
index d172d11..3ff3baa 100644
--- a/README.md
+++ b/README.md
@@ -33,3 +33,4 @@ You will need some environment variables set to properly self-host aidxnCC. They
## To-Do
- [ ] Dockerize for easier deployment
+- [ ] Use MusicBrainz recording collections for displaying data about music
diff --git a/app/music/page.tsx b/app/music/page.tsx
index f10a013..dacb362 100644
--- a/app/music/page.tsx
+++ b/app/music/page.tsx
@@ -2,14 +2,23 @@ import Header from '@/components/Header'
import MusicWidget from '@/components/widgets/Music'
import MusicInfo from '@/components/objects/MusicInfo'
import Footer from '@/components/Footer'
+import { Music as MusicNote } from "lucide-react";
export default function Music() {
return (
+
{timePeriods.map((period) => (
))}
diff --git a/components/objects/SeekBar.tsx b/components/objects/SeekBar.tsx
new file mode 100644
index 0000000..df0ab75
--- /dev/null
+++ b/components/objects/SeekBar.tsx
@@ -0,0 +1,52 @@
+"use client"
+
+import * as React from "react"
+
+interface SeekBarProps {
+ duration: string
+ startPos: number
+}
+
+export function SeekBar({ duration, startPos }: SeekBarProps) {
+ const getDurationInSeconds = (timeStr: string) => {
+ const parts = timeStr.split(":").map(Number)
+ if (parts.length === 3) {
+ return parts[0] * 3600 + parts[1] * 60 + parts[2]
+ } else {
+ return parts[0] * 60 + parts[1]
+ }
+ }
+
+ const formatTime = (seconds: number) => {
+ const hours = Math.floor(seconds / 3600)
+ const minutes = Math.floor((seconds % 3600) / 60)
+ const remainingSeconds = seconds % 60
+
+ if (hours > 0) {
+ return `${hours}:${minutes.toString().padStart(2, "0")}:${remainingSeconds.toString().padStart(2, "0")}`
+ }
+ return `${minutes}:${remainingSeconds.toString().padStart(2, "0")}`
+ }
+
+ const totalSeconds = getDurationInSeconds(duration)
+ const [currentSeconds] = React.useState(startPos)
+ const progress = (currentSeconds / totalSeconds) * 100
+
+ return (
+
+
+
{formatTime(currentSeconds)}
+
{duration}
+
+
+
+
+ )
+}
+
diff --git a/components/widgets/Music.tsx b/components/widgets/Music.tsx
index 047ccd2..ca3dce3 100644
--- a/components/widgets/Music.tsx
+++ b/components/widgets/Music.tsx
@@ -1,101 +1,127 @@
-"use client";
+"use client"
-import { useState, useEffect } from 'react';
-import Image from 'next/image';
-import { Play, SkipBack, SkipForward } from 'lucide-react';
-import LoadingSpinner from '../objects/LoadingSpinner';
+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"
interface Song {
- albumArt: string;
- name: string;
- artist: string;
- duration: string;
- link?: string;
+ albumArt: string
+ name: string
+ artist: string
+ duration: string
+ link?: string
}
interface Period {
- timePeriod: string;
- songs: Song[];
+ timePeriod: string
+ songs: Song[]
}
export default function Home() {
- const [timePeriod, setTimePeriod] = useState('Early Summer 2024');
- const [songs, setSongs] = useState
([]);
- const [currentIndex, setCurrentIndex] = useState(0);
- const [isLoading, setIsLoading] = useState(true);
+ const [timePeriod, setTimePeriod] = useState("Early Summer 2024")
+ const [songs, setSongs] = useState([])
+ const [currentIndex, setCurrentIndex] = useState(0)
+ const [isLoading, setIsLoading] = useState(true)
+ const [currentPosition, setCurrentPosition] = useState(0)
useEffect(() => {
- setIsLoading(true);
- fetch('/data/music.json')
- .then(response => response.json())
+ setIsLoading(true)
+ fetch("/data/music.json")
+ .then((response) => response.json())
.then((data: Period[]) => {
- const selectedPeriod = data.find((period) => period.timePeriod === timePeriod);
- const songsList = selectedPeriod ? selectedPeriod.songs : [];
- setSongs(songsList);
- setCurrentIndex(Math.floor(Math.random() * songsList.length));
- setIsLoading(false);
+ 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)
})
- .catch(error => {
- console.error('Error fetching music data:', error);
- setIsLoading(false);
- });
- }, [timePeriod]);
+ .catch((error) => {
+ console.error("Error fetching music data:", error)
+ setIsLoading(false)
+ })
+ }, [timePeriod])
const handleNext = () => {
- setCurrentIndex((currentIndex + 1) % songs.length);
- };
+ setCurrentIndex((prevIndex) => {
+ const nextIndex = (prevIndex + 1) % songs.length
+ const durationInSeconds = parseDuration(songs[nextIndex].duration)
+ setCurrentPosition(Math.floor(Math.random() * durationInSeconds))
+ return nextIndex
+ })
+ }
const handlePrevious = () => {
- setCurrentIndex((currentIndex - 1 + songs.length) % songs.length);
- };
+ 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 (
-
+
- Music By Time Period
-
- Time Period:
- setTimePeriod(e.target.value)}
- className="ml-2 p-2 bg-gray-700 text-gray-300 rounded-sm"
- >
- Early Summer 2024
-
-
-
{isLoading && }
{!isLoading && songs.length > 0 && (
-
-
-
{songs[currentIndex].name}
-
{songs[currentIndex].artist}
-
{songs[currentIndex].duration}
-
-
-
-
-
window.open(songs[currentIndex]?.link, '_blank')}>
-
-
-
-
-
-
+
+
{songs[currentIndex].name}
+
{songs[currentIndex].artist}
+
+
+
+
+
+
window.open(songs[currentIndex]?.link, "_blank")}>
+
+
+
+
+
)}
+
+
+
+ Time Period
+
+ setTimePeriod(e.target.value)}
+ className="px-3 py-2 bg-gray-700 rounded-sm mb-2"
+ >
+ Early Summer 2024
+
+
- );
+ )
}