crush-level-web/src/app/(main)/leaderboard/components/SmallRankCard.tsx

81 lines
2.8 KiB
TypeScript
Raw Normal View History

2025-11-13 08:38:25 +00:00
"use client";
import { formatNumberToKMB } from "@/lib/utils";
import Image from "next/image";
import { AiChatRankOutput, AiHeartbeatRankOutput, AiGiftRankOutput } from "@/services/home/types";
import { RankType } from "@/types/global";
import Link from "next/link";
interface SmallRankCardProps {
item: AiChatRankOutput | AiHeartbeatRankOutput | AiGiftRankOutput;
rankType: RankType;
rank?: number; // 用于显示排名如果不传则使用item.rankNo
}
export default function SmallRankCard({
item,
rankType,
rank,
}: SmallRankCardProps) {
// 根据排行榜类型获取对应的数值显示
const getDisplayValue = () => {
switch (rankType) {
case RankType.CHAT:
return formatNumberToKMB((item as AiChatRankOutput).chatNum || 0);
case RankType.CRUSH:
return `${(item as AiHeartbeatRankOutput).heartbeatValTotal || 0}`;
case RankType.GIFTS:
return formatNumberToKMB(Math.floor(((item as AiGiftRankOutput).giftCoinNum || 0) / 100));
default:
return "0";
}
};
// 根据排行榜类型获取对应的图标
const getIcon = () => {
switch (rankType) {
case RankType.CHAT:
return <i className="iconfont icon-Chat !text-[12px]" />;
case RankType.CRUSH:
return <Image src="/icons/icon-crush.svg" alt="" width={12} height={12} />;
case RankType.GIFTS:
return <Image src="/icons/diamond.svg" alt="" width={12} height={12} />;
default:
return <i className="iconfont icon-Chat !text-[12px]" />;
}
};
if (!item) {
return <div className="flex-1 py-12"></div>;
}
const imageUrl = item.homeImageUrl || "";
const rankNo = rank || item.rankNo || 1;
return (
2025-11-24 03:47:20 +00:00
<Link href={`/chat/${item.aiId}`} prefetch key={item.aiId} className="flex-1">
2025-11-13 08:38:25 +00:00
<div className="flex-1 py-12">
<div className="w-full aspect-[240/360] rounded-b-lg relative overflow-hidden">
<div
className="absolute inset-0"
style={{
background: `url(${imageUrl}) #211a2b 50% / cover no-repeat`,
maskImage: "linear-gradient(180deg, rgba(255, 255, 255, 0.00) 0%, #FFF 55%)"
}}
/>
<div className="absolute left-0 right-0 bottom-0 aspect-[240/112]">
<Image src={`/images/leaderboard/${rankNo}-st.svg`} alt="" fill className="object-cover" />
</div>
<div className="absolute inset-0">
<div className="flex items-center justify-center gap-1 absolute bottom-[44] left-0 right-0">
{getIcon()}
<div className="txt-numMonotype-s">{getDisplayValue()}</div>
</div>
<div className="txt-numDisplay-m absolute bottom-1 left-0 right-0 text-center">{rankNo === 2 ? "2nd" : "3rd"}</div>
</div>
</div>
</div>
</Link>
);
2025-11-24 03:47:20 +00:00
}