122 lines
3.0 KiB
TypeScript
Raw Normal View History

2022-10-28 20:29:04 +08:00
import { resizeImage } from '@/web/utils/common'
2022-05-29 17:53:27 +08:00
import { cx } from '@emotion/css'
2022-05-12 02:45:43 +08:00
import { useNavigate } from 'react-router-dom'
2022-10-28 20:29:04 +08:00
import Image from './Image'
import { prefetchAlbum } from '@/web/api/hooks/useAlbum'
import { prefetchPlaylist } from '@/web/api/hooks/usePlaylist'
import { memo, useCallback } from 'react'
import dayjs from 'dayjs'
2023-01-24 16:29:33 +08:00
import ArtistInline from './ArtistsInline'
2022-03-13 14:40:38 +08:00
2022-10-28 20:29:04 +08:00
type ItemTitle = undefined | 'name'
type ItemSubTitle = undefined | 'artist' | 'year'
2022-03-13 14:40:38 +08:00
2022-10-28 20:29:04 +08:00
const Album = ({
album,
itemTitle,
itemSubtitle,
2022-03-13 14:40:38 +08:00
}: {
2022-10-28 20:29:04 +08:00
album: Album
itemTitle?: ItemTitle
itemSubtitle?: ItemSubTitle
2022-03-13 14:40:38 +08:00
}) => {
2022-10-28 20:29:04 +08:00
const navigate = useNavigate()
const goTo = () => {
navigate(`/album/${album.id}`)
}
const prefetch = () => {
prefetchAlbum({ id: album.id })
}
const title =
itemTitle &&
{
name: album.name,
}[itemTitle]
const subtitle =
itemSubtitle &&
{
artist: (
<ArtistInline
artists={album.artists}
hoverClassName='hover:text-white/50 transition-colors duration-400'
/>
),
year: dayjs(album.publishTime || 0).year(),
}[itemSubtitle]
2022-03-13 14:40:38 +08:00
return (
2022-10-28 20:29:04 +08:00
<div>
<Image
onClick={goTo}
key={album.id}
src={resizeImage(album?.picUrl || '', 'md')}
className='aspect-square rounded-24'
onMouseOver={prefetch}
/>
{title && (
2023-01-24 16:29:33 +08:00
<div className='line-clamp-2 mt-2 text-14 font-medium text-neutral-300'>{title}</div>
2022-03-13 14:40:38 +08:00
)}
2023-01-24 16:29:33 +08:00
{subtitle && <div className='mt-1 text-14 font-medium text-neutral-700'>{subtitle}</div>}
2022-03-13 14:40:38 +08:00
</div>
)
}
2022-10-28 20:29:04 +08:00
const Playlist = ({ playlist }: { playlist: Playlist }) => {
const navigate = useNavigate()
const goTo = useCallback(() => {
navigate(`/playlist/${playlist.id}`)
}, [navigate, playlist.id])
const prefetch = useCallback(() => {
prefetchPlaylist({ id: playlist.id })
}, [playlist.id])
2022-03-13 14:40:38 +08:00
2022-10-28 20:29:04 +08:00
return (
<Image
onClick={goTo}
key={playlist.id}
src={resizeImage(playlist.coverImgUrl || playlist?.picUrl || '', 'md')}
className='aspect-square rounded-24'
onMouseOver={prefetch}
/>
)
2022-03-13 14:40:38 +08:00
}
const CoverRow = ({
albums,
playlists,
2022-10-28 20:29:04 +08:00
title,
2022-03-13 14:40:38 +08:00
className,
2022-10-28 20:29:04 +08:00
itemTitle,
itemSubtitle,
2022-03-13 14:40:38 +08:00
}: {
title?: string
2022-10-28 20:29:04 +08:00
className?: string
2022-03-13 14:40:38 +08:00
albums?: Album[]
playlists?: Playlist[]
2022-10-28 20:29:04 +08:00
itemTitle?: ItemTitle
itemSubtitle?: ItemSubTitle
2022-03-13 14:40:38 +08:00
}) => {
return (
2022-10-28 20:29:04 +08:00
<div className={className}>
{/* Title */}
2023-01-24 16:29:33 +08:00
{title && <h4 className='mb-6 text-14 font-bold uppercase dark:text-neutral-300'>{title}</h4>}
2022-03-13 14:40:38 +08:00
2022-10-28 20:29:04 +08:00
{/* Items */}
<div className='grid grid-cols-3 gap-4 lg:gap-6 xl:grid-cols-4 2xl:grid-cols-5'>
{albums?.map(album => (
2023-01-24 16:29:33 +08:00
<Album key={album.id} album={album} itemTitle={itemTitle} itemSubtitle={itemSubtitle} />
2022-10-28 20:29:04 +08:00
))}
{playlists?.map(playlist => (
<Playlist key={playlist.id} playlist={playlist} />
2022-03-13 14:40:38 +08:00
))}
</div>
</div>
)
}
2022-10-28 20:29:04 +08:00
const memoizedCoverRow = memo(CoverRow)
memoizedCoverRow.displayName = 'CoverRow'
export default memoizedCoverRow