tfrere's picture
update empty states and header section
2405b72
raw
history blame
5.79 kB
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;