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"; | |
import { useLeaderboard } from "../context/LeaderboardContext"; | |
const LeaderboardCard = ({ leaderboard }) => { | |
const { | |
card_data = {}, | |
likes = 0, | |
enriched, | |
consolidated_notes, | |
organization, | |
} = leaderboard; | |
const { getHighlightedText, searchQuery } = useLeaderboard(); | |
const { | |
text: highlightedText, | |
shouldHighlight, | |
highlightStart, | |
highlightEnd, | |
} = getHighlightedText(card_data.title || leaderboard.id, searchQuery); | |
// Fonction pour capitaliser la première lettre | |
const capitalizeFirst = (str) => { | |
if (!str) return ""; | |
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 || "#6366f1" | |
} 0%, ${card_data.colorTo || "#a855f7"} 100%)`, | |
color: "white", | |
overflow: "visible", | |
"&::after": { | |
content: '""', | |
position: "absolute", | |
top: 0, | |
left: 0, | |
right: 0, | |
bottom: 0, | |
backgroundColor: "rgba(0, 0, 0, 0.15)", | |
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="subtitle1" | |
sx={{ | |
fontWeight: 900, | |
whiteSpace: "nowrap", | |
overflow: "hidden", | |
textOverflow: "ellipsis", | |
}} | |
> | |
{shouldHighlight ? ( | |
<> | |
{highlightedText.slice(0, highlightStart)} | |
<Box | |
component="span" | |
sx={{ | |
bgcolor: "primary.main", | |
color: "primary.contrastText", | |
px: 0.5, | |
borderRadius: 0.5, | |
}} | |
> | |
{highlightedText.slice(highlightStart, highlightEnd)} | |
</Box> | |
{highlightedText.slice(highlightEnd)} | |
</> | |
) : ( | |
card_data.title || leaderboard.id | |
)} | |
</Typography> | |
</CardContent> | |
</Card> | |
{(card_data.short_description || consolidated_notes) && ( | |
<Typography | |
variant="body2" | |
sx={{ | |
color: "text.secondary", | |
fontSize: "0.875rem", | |
}} | |
> | |
{card_data.short_description || consolidated_notes} | |
</Typography> | |
)} | |
</Stack> | |
</Box> | |
); | |
}; | |
export default LeaderboardCard; | |