tfrere's picture
update front
fd164b2
raw
history blame
6.31 kB
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;