Spaces:
Running
Running
import React from "react"; | |
import { Card, CardContent, Typography, Box, Stack } from "@mui/material"; | |
import FavoriteBorderIcon from "@mui/icons-material/FavoriteBorder"; | |
import { alpha } from "@mui/material/styles"; | |
const LeaderboardCard = ({ leaderboard }) => { | |
const { card_data, likes, enriched, consolidated_notes, organization } = | |
leaderboard; | |
// Fonction pour capitaliser la première lettre | |
const capitalizeFirst = (str) => { | |
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase(); | |
}; | |
// Fonction pour formater les likes | |
const formatLikes = (count) => { | |
if (count >= 1000) { | |
return (count / 1000).toFixed(2).replace(/\.?0+$/, "") + "k"; | |
} | |
return count; | |
}; | |
// Séparer les emojis s'il y en a plusieurs | |
const emojis = card_data.emoji.trim().split(/\s+/); | |
return ( | |
<Box | |
component="a" | |
href={`https://huggingface.co/spaces/${leaderboard.id}`} | |
target="_blank" | |
rel="noopener noreferrer" | |
sx={{ | |
textDecoration: "none", | |
color: "inherit", | |
display: "block", | |
"&:hover": { | |
opacity: 0.95, | |
}, | |
}} | |
> | |
<Stack spacing={1}> | |
<Card | |
elevation={0} | |
sx={{ | |
position: "relative", | |
minHeight: 180, | |
background: `linear-gradient(135deg, ${card_data.colorFrom} 0%, ${card_data.colorTo} 100%)`, | |
color: "white", | |
overflow: "visible", | |
"&::after": { | |
content: '""', | |
position: "absolute", | |
top: 0, | |
left: 0, | |
right: 0, | |
bottom: 0, | |
backgroundColor: "rgba(0, 0, 0, 0.1)", | |
pointerEvents: "none", | |
zIndex: 1, | |
}, | |
}} | |
> | |
{/* Background Emoji */} | |
<Box | |
sx={{ | |
position: "absolute", | |
top: "50%", | |
left: "50%", | |
transform: "translate(-50%, -50%)", | |
fontSize: "3.75rem", | |
opacity: 0.6, | |
pointerEvents: "none", | |
display: "flex", | |
zIndex: 2, | |
}} | |
> | |
{emojis.map((emoji, index) => ( | |
<span key={index}>{emoji}</span> | |
))} | |
</Box> | |
{/* Header with likes and status */} | |
<Box | |
sx={{ | |
position: "absolute", | |
top: 0, | |
left: 0, | |
right: 0, | |
p: 1.5, | |
display: "flex", | |
justifyContent: "space-between", | |
alignItems: "center", | |
zIndex: 2, | |
}} | |
> | |
<Typography | |
variant="body2" | |
sx={{ | |
backgroundColor: "rgba(0, 0, 0, 0.1)", | |
px: 1, | |
py: 0.25, | |
borderRadius: 1, | |
fontSize: "0.75rem", | |
}} | |
> | |
{capitalizeFirst(leaderboard.runtime_stage)} | |
</Typography> | |
<Box | |
sx={{ | |
display: "flex", | |
alignItems: "center", | |
gap: 0.25, | |
fontSize: "0.75rem", | |
}} | |
> | |
<FavoriteBorderIcon sx={{ fontSize: 16 }} /> | |
<Typography variant="body2" sx={{ fontSize: "inherit" }}> | |
{formatLikes(likes)} | |
</Typography> | |
</Box> | |
</Box> | |
{/* Footer with author */} | |
<Box | |
sx={{ | |
position: "absolute", | |
bottom: 0, | |
left: 0, | |
right: 0, | |
p: 1.5, | |
zIndex: 2, | |
}} | |
> | |
<Typography | |
variant="body2" | |
sx={{ | |
fontSize: "0.75rem", | |
opacity: 0.9, | |
}} | |
> | |
by {organization} | |
</Typography> | |
</Box> | |
<CardContent | |
sx={{ | |
height: "100%", | |
display: "flex", | |
alignItems: "center", | |
justifyContent: "center", | |
position: "absolute", | |
top: "50%", | |
left: "50%", | |
transform: "translate(-50%, -50%)", | |
width: "100%", | |
zIndex: 2, | |
p: 0, | |
"&:last-child": { | |
paddingBottom: 0, | |
}, | |
}} | |
> | |
<Typography | |
variant="h6" | |
component="h2" | |
align="center" | |
sx={{ | |
fontSize: "1.25rem", | |
fontWeight: 800, | |
maxWidth: "90%", | |
margin: "0 auto", | |
zIndex: 5, | |
textShadow: "rgba(0, 0, 0, 0.25) 0px 1px 2px", | |
}} | |
> | |
{card_data.title} | |
</Typography> | |
</CardContent> | |
</Card> | |
{consolidated_notes && ( | |
<Typography | |
variant="body2" | |
sx={{ | |
color: "text.secondary", | |
fontSize: "0.875rem", | |
}} | |
> | |
{consolidated_notes} | |
</Typography> | |
)} | |
</Stack> | |
</Box> | |
); | |
}; | |
export default LeaderboardCard; | |