154 lines
4.7 KiB
TypeScript
154 lines
4.7 KiB
TypeScript
import { Tag } from '@/components/ui/tag'
|
|
import { cn, formatNumberToKMB } from '@/lib/utils'
|
|
import { IAlbumItem, LikedStatus, LockStatus } from '@/services/user'
|
|
import Image from 'next/image'
|
|
import { useState } from 'react'
|
|
import { useAIUser } from '../context/aiUser'
|
|
import { IconButton } from '@/components/ui/button'
|
|
import AlbumItemAction from './AlbumItemAction'
|
|
import { formatFromCents } from '@/utils/number'
|
|
|
|
interface AlbumItemProps {
|
|
item: IAlbumItem
|
|
onLike: (albumId: number, isLiked: boolean) => void
|
|
onImageClick: () => void
|
|
}
|
|
|
|
const AlbumItem = ({ item, onLike, onImageClick }: AlbumItemProps) => {
|
|
const [imageLoading, setImageLoading] = useState(true)
|
|
const { isOwner } = useAIUser()
|
|
|
|
const handleLike = () => {
|
|
onLike(item.albumId, item.likedStatus === LikedStatus.Liked)
|
|
}
|
|
|
|
const renderTag = () => {
|
|
if (item.isDefault) {
|
|
return null
|
|
}
|
|
if (isOwner) {
|
|
if (item.lockStatus) {
|
|
return (
|
|
<Tag variant="dark" className="absolute top-2 right-2 p-[6px]" size="small">
|
|
<i className="iconfont icon-private !text-[12px] leading-none" />
|
|
</Tag>
|
|
)
|
|
}
|
|
}
|
|
if (item.lockStatus === LockStatus.Unlock) {
|
|
return (
|
|
<Tag
|
|
variant="default"
|
|
className="bg-primary-gradient-normal absolute top-2 right-2 p-[6px]"
|
|
size="small"
|
|
>
|
|
<i className="iconfont icon-public !text-[12px] leading-none" />
|
|
</Tag>
|
|
)
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
const renderOverlay = () => {
|
|
// 如果是自己的相册,则不显示解锁按钮
|
|
if (isOwner) {
|
|
return null
|
|
}
|
|
|
|
if (item.lockStatus === LockStatus.Lock) {
|
|
return (
|
|
<div
|
|
className="absolute inset-0 flex cursor-pointer flex-col items-center justify-center gap-3"
|
|
onClick={(e) => {
|
|
// e.stopPropagation();
|
|
// handleUnlock();
|
|
}}
|
|
>
|
|
<i className="iconfont icon-private-border !text-[24px] leading-none" />
|
|
<div className="flex items-center gap-2">
|
|
<div className="flex items-center gap-1">
|
|
<div className="relative h-4 w-4">
|
|
<Image src="/icons/diamond.svg" alt="diamond" fill className="object-contain" />
|
|
</div>
|
|
<span className="text-sm font-semibold text-white">
|
|
{formatFromCents(item.unlockPrice || 0)}
|
|
</span>
|
|
</div>
|
|
<div className="txt-label-m text-txt-primary-normal">Unlock</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
return null
|
|
}
|
|
|
|
const renderDefaultTag = () => {
|
|
if (item.isDefault) {
|
|
return (
|
|
<Tag variant="dark" className="absolute top-2 left-2" size="small">
|
|
Default
|
|
</Tag>
|
|
)
|
|
}
|
|
return null
|
|
}
|
|
|
|
return (
|
|
<div className="group relative cursor-pointer overflow-hidden rounded-2xl pb-[134%]">
|
|
<div className="absolute inset-0" onClick={onImageClick}>
|
|
{/* 背景图片 */}
|
|
<div className="relative h-full w-full">
|
|
<Image
|
|
src={item.imgUrl || item.img1}
|
|
alt="Album image"
|
|
fill
|
|
className={cn(
|
|
'object-cover object-top transition-opacity duration-300',
|
|
imageLoading ? 'opacity-0' : 'opacity-100'
|
|
)}
|
|
onLoadingComplete={() => setImageLoading(false)}
|
|
sizes="(max-width: 768px) 50vw, 176px"
|
|
/>
|
|
{imageLoading && (
|
|
<div className="bg-surface-nest-normal absolute inset-0 animate-pulse" />
|
|
)}
|
|
</div>
|
|
{renderDefaultTag()}
|
|
|
|
{/* 标签 */}
|
|
{renderTag()}
|
|
|
|
{/* 付费内容遮罩 */}
|
|
{renderOverlay()}
|
|
|
|
{/* 底部操作区 */}
|
|
<div
|
|
className="absolute right-2 bottom-2 left-2 flex items-center justify-between"
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
{/* 点赞按钮 */}
|
|
{(item.lockStatus !== LockStatus.Lock || isOwner) && (
|
|
<div className="bg-surface-element-dark-normal flex items-center gap-[2px] rounded-full pr-1 backdrop-blur-lg">
|
|
<IconButton variant="ghost" size="xs" onClick={handleLike}>
|
|
{item.likedStatus === LikedStatus.Liked ? (
|
|
<i className="iconfont icon-Like-fill !text-important-normal !text-[16px] leading-none" />
|
|
) : (
|
|
<i className="iconfont icon-Like !text-[16px] leading-none" />
|
|
)}
|
|
</IconButton>
|
|
<span className="txt-numMonotype-xs text-white">
|
|
{formatNumberToKMB(item.likedCount ?? 0)}
|
|
</span>
|
|
</div>
|
|
)}
|
|
|
|
<AlbumItemAction data={item} />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default AlbumItem
|