UI-UX/src/components/artist/RankCard.tsx

83 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { Artist } from "@/types/artist";
import { cn } from "@/lib/cn";
interface RankCardProps {
artist: Artist;
/** 全榜单(用于计算与上下名的差距) */
allArtists: Artist[];
className?: string;
}
export default function RankCard({ artist, allArtists, className }: RankCardProps) {
// 按当前票数排序后定位艺人
const sorted = [...allArtists].sort((a, b) => b.votes - a.votes);
const idx = sorted.findIndex((a) => a.id === artist.id);
const prev = idx > 0 ? sorted[idx - 1] : undefined;
const next = idx < sorted.length - 1 ? sorted[idx + 1] : undefined;
const leadOver = next ? artist.votes - next.votes : null;
const trailBehind = prev ? prev.votes - artist.votes : null;
const isFirst = artist.rank === 1;
const inTop12 = artist.rank <= 12;
return (
<div
className={cn(
"bg-elevated/60 backdrop-blur-md border border-white/10 rounded-xl p-4 sm:p-5 grid grid-cols-2 gap-4",
className,
)}
>
{/* 当前排名 */}
<div>
<div className="font-label text-[10px] tracking-widest uppercase text-white/40 mb-1">
</div>
<div className="flex items-end gap-2">
<span
className={cn(
"font-display text-3xl sm:text-4xl tabular-nums leading-none",
inTop12 ? "text-purple-300 glow-text-purple" : "text-white/70",
)}
>
#{artist.rank}
</span>
<span className="text-xs text-white/45 pb-1 tabular-nums">
{(artist.votes / 10000).toFixed(1)}w
</span>
</div>
{inTop12 && (
<span className="inline-block mt-2 font-label text-[10px] tracking-widest text-pink-400 uppercase">
</span>
)}
</div>
{/* 差距信息 */}
<div className="text-right">
{isFirst && leadOver != null ? (
<>
<div className="font-label text-[10px] tracking-widest uppercase text-white/40 mb-1">
</div>
<div className="font-display text-lg sm:text-xl text-pink-400 tabular-nums">
+{leadOver.toLocaleString()}
</div>
<div className="text-[10px] text-white/40"></div>
</>
) : trailBehind != null ? (
<>
<div className="font-label text-[10px] tracking-widest uppercase text-white/40 mb-1">
</div>
<div className="font-display text-lg sm:text-xl text-purple-300 tabular-nums">
{trailBehind.toLocaleString()}
</div>
<div className="text-[10px] text-white/40"></div>
</>
) : null}
</div>
</div>
);
}