172 lines
4.3 KiB
TypeScript
172 lines
4.3 KiB
TypeScript
import Link from 'next/link'
|
|
import { SongCard } from '@/components/SongCard'
|
|
import { GenreBadge } from '@/components/GenreBadge'
|
|
import { SectionHeader } from '@/components/SectionHeader'
|
|
import { prisma } from '@/lib/prisma'
|
|
|
|
async function getTrendingSongs() {
|
|
try {
|
|
const songs = await prisma.song.findMany({
|
|
where: {
|
|
isPublic: true,
|
|
},
|
|
include: {
|
|
artist: {
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
slug: true,
|
|
avatarUrl: true,
|
|
verified: true,
|
|
},
|
|
},
|
|
album: {
|
|
select: {
|
|
id: true,
|
|
title: true,
|
|
slug: true,
|
|
coverUrl: true,
|
|
},
|
|
},
|
|
},
|
|
orderBy: {
|
|
playCount: 'desc',
|
|
},
|
|
take: 8,
|
|
})
|
|
return songs
|
|
} catch (error) {
|
|
console.error('Error fetching trending songs:', error)
|
|
return []
|
|
}
|
|
}
|
|
|
|
async function getNewReleases() {
|
|
try {
|
|
const songs = await prisma.song.findMany({
|
|
where: {
|
|
isPublic: true,
|
|
},
|
|
include: {
|
|
artist: {
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
slug: true,
|
|
avatarUrl: true,
|
|
verified: true,
|
|
},
|
|
},
|
|
album: {
|
|
select: {
|
|
id: true,
|
|
title: true,
|
|
slug: true,
|
|
coverUrl: true,
|
|
},
|
|
},
|
|
},
|
|
orderBy: {
|
|
createdAt: 'desc',
|
|
},
|
|
take: 8,
|
|
})
|
|
return songs
|
|
} catch (error) {
|
|
console.error('Error fetching new releases:', error)
|
|
return []
|
|
}
|
|
}
|
|
|
|
async function getGenres() {
|
|
try {
|
|
const genres = await prisma.genre.findMany({
|
|
orderBy: {
|
|
name: 'asc',
|
|
},
|
|
})
|
|
return genres
|
|
} catch (error) {
|
|
console.error('Error fetching genres:', error)
|
|
return []
|
|
}
|
|
}
|
|
|
|
export default async function HomePage() {
|
|
const [trendingSongs, newReleases, genres] = await Promise.all([
|
|
getTrendingSongs(),
|
|
getNewReleases(),
|
|
getGenres(),
|
|
])
|
|
|
|
return (
|
|
<main className="min-h-screen bg-zinc-950">
|
|
<div className="max-w-7xl mx-auto px-4 py-8">
|
|
{/* Hero Section */}
|
|
<div className="mb-12">
|
|
<h1 className="text-5xl font-bold text-white mb-4">Discover Music</h1>
|
|
<p className="text-xl text-zinc-400">
|
|
Explore trending tracks, new releases, and your favorite genres
|
|
</p>
|
|
</div>
|
|
|
|
{/* Trending Section */}
|
|
<section className="mb-12">
|
|
<SectionHeader
|
|
title="Trending Now"
|
|
showSeeAll
|
|
seeAllHref="/search?filter=trending"
|
|
/>
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 mt-6">
|
|
{trendingSongs.map((song: any) => (
|
|
<SongCard
|
|
key={song.id}
|
|
id={song.id}
|
|
title={song.title}
|
|
artistName={song.artist?.name || 'Unknown Artist'}
|
|
coverUrl={song.coverUrl || song.album?.coverUrl}
|
|
duration={song.duration || 0}
|
|
plays={song.playCount}
|
|
/>
|
|
))}
|
|
</div>
|
|
</section>
|
|
|
|
{/* New Releases Section */}
|
|
<section className="mb-12">
|
|
<SectionHeader
|
|
title="New Releases"
|
|
showSeeAll
|
|
seeAllHref="/search?filter=new"
|
|
/>
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 mt-6">
|
|
{newReleases.map((song: any) => (
|
|
<SongCard
|
|
key={song.id}
|
|
id={song.id}
|
|
title={song.title}
|
|
artistName={song.artist?.name || 'Unknown Artist'}
|
|
coverUrl={song.coverUrl || song.album?.coverUrl}
|
|
duration={song.duration || 0}
|
|
plays={song.playCount}
|
|
/>
|
|
))}
|
|
</div>
|
|
</section>
|
|
|
|
{/* Genres Section */}
|
|
<section>
|
|
<SectionHeader title="Browse Genres" />
|
|
<div className="flex flex-wrap gap-3 mt-6">
|
|
{genres.map((genre: any) => (
|
|
<Link key={genre.id} href={`/genre/${genre.slug}`}>
|
|
<GenreBadge name={genre.name} />
|
|
</Link>
|
|
))}
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</main>
|
|
)
|
|
}
|