91 lines
2.7 KiB
TypeScript
91 lines
2.7 KiB
TypeScript
import { AlbumHeader } from '@/components/AlbumHeader'
|
|
import { TrackList } from '@/components/TrackList'
|
|
|
|
interface PageProps {
|
|
params: Promise<{ id: string }>
|
|
}
|
|
|
|
async function getAlbum(id: string) {
|
|
const res = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/albums/${id}`, {
|
|
cache: 'no-store',
|
|
})
|
|
if (!res.ok) throw new Error('Album not found')
|
|
const data = await res.json()
|
|
return data.album
|
|
}
|
|
|
|
export default async function AlbumPage({ params }: PageProps) {
|
|
const { id } = await params
|
|
const album = await getAlbum(id)
|
|
|
|
// Calculate total duration from songs
|
|
const totalDuration = album.songs?.reduce((acc: number, song: any) => acc + (song.duration || 0), 0) || 0
|
|
|
|
// Transform songs for TrackList
|
|
const tracks = album.songs?.map((song: any, index: number) => ({
|
|
id: song.id,
|
|
title: song.title,
|
|
artistName: album.artist?.name || 'Unknown Artist',
|
|
duration: song.duration || 0,
|
|
plays: song.plays,
|
|
position: index + 1
|
|
})) || []
|
|
|
|
return (
|
|
<main className="min-h-screen bg-zinc-950">
|
|
<AlbumHeader
|
|
title={album.title}
|
|
artistName={album.artist?.name || 'Unknown Artist'}
|
|
artistId={album.artistId}
|
|
coverUrl={album.coverUrl}
|
|
releaseDate={album.releaseDate}
|
|
trackCount={album.songs?.length || 0}
|
|
duration={totalDuration}
|
|
type={album.type || 'album'}
|
|
/>
|
|
|
|
<div className="max-w-7xl mx-auto px-4 py-8">
|
|
{/* Track List */}
|
|
{tracks.length > 0 && (
|
|
<section className="mb-8">
|
|
<TrackList tracks={tracks} showPosition />
|
|
</section>
|
|
)}
|
|
|
|
{/* Album Info */}
|
|
<section className="grid grid-cols-1 md:grid-cols-2 gap-8 mt-12 text-zinc-300">
|
|
<div>
|
|
<h3 className="text-lg font-semibold text-white mb-2">Release Date</h3>
|
|
<p>{new Date(album.releaseDate).toLocaleDateString('en-US', {
|
|
year: 'numeric',
|
|
month: 'long',
|
|
day: 'numeric'
|
|
})}</p>
|
|
</div>
|
|
|
|
{album.label && (
|
|
<div>
|
|
<h3 className="text-lg font-semibold text-white mb-2">Label</h3>
|
|
<p>{album.label.name}</p>
|
|
</div>
|
|
)}
|
|
|
|
{album.songs && album.songs.length > 0 && (
|
|
<div>
|
|
<h3 className="text-lg font-semibold text-white mb-2">Total Duration</h3>
|
|
<p>
|
|
{Math.floor(album.songs.reduce((acc: number, song: any) => acc + song.duration, 0) / 60)} minutes
|
|
</p>
|
|
</div>
|
|
)}
|
|
|
|
<div>
|
|
<h3 className="text-lg font-semibold text-white mb-2">Tracks</h3>
|
|
<p>{album.songs?.length || 0} songs</p>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</main>
|
|
)
|
|
}
|