Spaces:
Running
Running
File size: 5,793 Bytes
2f38845 606f214 5621ad9 606f214 6ba1570 606f214 5621ad9 606f214 2f38845 606f214 48cea17 606f214 5621ad9 f145689 606f214 5621ad9 606f214 5621ad9 f145689 606f214 5621ad9 606f214 2f38845 606f214 5621ad9 606f214 2405b72 606f214 5621ad9 606f214 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
import React, { useMemo } from "react";
import { Box } from "@mui/material";
import { useLeaderboard } from "../../context/LeaderboardContext";
import SectionHeader from "./components/SectionHeader";
import LanguageList from "./components/LanguageList";
import LeaderboardGrid from "./components/LeaderboardGrid";
import EmptyState from "./components/EmptyState";
import { useLanguageStats } from "./hooks/useLanguageStats";
const ITEMS_PER_PAGE = 4;
const LeaderboardSection = ({
title,
leaderboards,
filteredLeaderboards,
id,
showEmptyState = false,
}) => {
const {
expandedSections,
setExpandedSections,
selectedLanguage,
setSelectedLanguage,
searchQuery,
selectedCategories,
} = useLeaderboard();
const isExpanded = expandedSections.has(id);
const { languages, languageStats, LANGUAGE_FAMILIES, findLanguageFamily } =
useLanguageStats(leaderboards, filteredLeaderboards);
// Créer un titre enrichi qui inclut les filtres de langue
const enrichedTitle = useMemo(() => {
let newTitle = title;
// Ajouter les langues sélectionnées au titre si elles ne sont pas déjà incluses
if (selectedLanguage && selectedLanguage.size > 0) {
const languageNames = Array.from(selectedLanguage)
.map((lang) => lang.charAt(0).toUpperCase() + lang.slice(1))
.join(", ");
// Vérifier si le titre contient déjà "language"
if (!newTitle.toLowerCase().includes("language")) {
newTitle = `${newTitle} + Language: ${languageNames}`;
} else if (
!newTitle.toLowerCase().includes(languageNames.toLowerCase())
) {
// Si le titre contient "language" mais pas les noms spécifiques
newTitle = newTitle.replace(
/language(\s+specific)?/i,
`Language: ${languageNames}`
);
}
}
// Ajouter le terme de recherche s'il existe
if (
searchQuery &&
!newTitle
.toLowerCase()
.includes(`matching "${searchQuery.toLowerCase()}"`)
) {
newTitle = `${newTitle} matching "${searchQuery}"`;
}
return newTitle;
}, [title, selectedLanguage, searchQuery]);
// Filtrer pour n'avoir que les leaderboards approuvés
const approvedLeaderboards = useMemo(() => {
// Filtrer d'abord pour n'avoir que les leaderboards approuvés
const approved = filteredLeaderboards.filter(
(leaderboard) => leaderboard.approval_status === "approved"
);
// Trier par trending_score (ordre décroissant)
return [...approved].sort((a, b) => {
const scoreA = a.trending_score || 0;
const scoreB = b.trending_score || 0;
return scoreB - scoreA; // Tri décroissant
});
}, [filteredLeaderboards]);
// On ne retourne null que si on n'a pas de leaderboards bruts
if (!leaderboards) return null;
// Déterminer si on doit paginer ou montrer tous les leaderboards
const shouldShowAll =
(selectedCategories.size === 1 && selectedCategories.has(id)) || // Une seule catégorie sélectionnée ET c'est celle-ci
(selectedCategories.size > 1 && id === "combined") || // Plusieurs catégories ET c'est la section combinée
isExpanded || // Section dépliée (quelle que soit la sélection)
id === "search-results"; // Toujours afficher tous les résultats pour la recherche textuelle
// Si on doit tout montrer, on ne divise pas la liste
const displayedLeaderboards = shouldShowAll
? approvedLeaderboards
: approvedLeaderboards.slice(0, ITEMS_PER_PAGE);
const remainingLeaderboards = shouldShowAll
? []
: approvedLeaderboards.slice(ITEMS_PER_PAGE);
// Calculate how many skeletons we need (seulement si on ne montre pas tout)
const skeletonsNeeded = shouldShowAll
? 0
: Math.max(0, 4 - approvedLeaderboards.length);
// On affiche le bouton expand seulement quand on n'a pas de sélection et que ce n'est pas une recherche textuelle
const showExpandButton =
selectedCategories.size === 0 && id !== "search-results";
// Le bouton est actif seulement s'il y a plus de 4 leaderboards
const isExpandButtonEnabled = approvedLeaderboards.length > ITEMS_PER_PAGE;
const toggleExpanded = () => {
setExpandedSections((prev) => {
const newSet = new Set(prev);
if (isExpanded) {
newSet.delete(id);
} else {
newSet.add(id);
}
return newSet;
});
};
// Déterminer si on doit afficher la liste des langues
const showLanguageList =
languages &&
selectedCategories.size > 0 &&
(id === "language" ||
(selectedCategories.size > 1 && selectedCategories.has("language")));
return (
<Box sx={{ mb: 6 }}>
<SectionHeader
title={enrichedTitle}
count={approvedLeaderboards.length}
isExpanded={isExpanded}
onToggleExpand={toggleExpanded}
showExpandButton={showExpandButton}
isExpandButtonEnabled={isExpandButtonEnabled}
/>
{showLanguageList && (
<LanguageList
languages={languages}
languageStats={languageStats}
selectedLanguage={selectedLanguage}
onLanguageSelect={setSelectedLanguage}
LANGUAGE_FAMILIES={LANGUAGE_FAMILIES}
findLanguageFamily={findLanguageFamily}
/>
)}
{approvedLeaderboards.length === 0 ? (
// Toujours afficher EmptyState, que showEmptyState soit true ou non
<EmptyState title={enrichedTitle} searchQuery={searchQuery} />
) : (
<LeaderboardGrid
displayedLeaderboards={displayedLeaderboards}
remainingLeaderboards={remainingLeaderboards}
isExpanded={isExpanded}
skeletonsNeeded={skeletonsNeeded}
id={id}
/>
)}
</Box>
);
};
export default LeaderboardSection;
|