find-a-leaderboard / client /src /context /LeaderboardContext.jsx
tfrere's picture
update front
953a39e
raw
history blame
6.99 kB
import React, {
createContext,
useContext,
useState,
useCallback,
useMemo,
} from "react";
const LeaderboardContext = createContext();
export const LeaderboardProvider = ({ children }) => {
const [leaderboards, setLeaderboards] = useState([]);
const [searchQuery, setSearchQuery] = useState("");
const [arenaOnly, setArenaOnly] = useState(false);
// Calculate total number of unique leaderboards (excluding duplicates)
const totalLeaderboards = useMemo(() => {
const uniqueIds = new Set(leaderboards.map((board) => board.id));
return uniqueIds.size;
}, [leaderboards]);
// Filter functions for categories
const filterByTag = useCallback((tag, boards) => {
return (
boards?.filter(
(board) =>
board.tags?.includes(tag) || board.consolidated_tags?.includes(tag)
) || []
);
}, []);
const filterByLanguage = useCallback((boards) => {
return (
boards?.filter(
(board) =>
board.tags?.some((tag) => tag.startsWith("language:")) ||
board.consolidated_tags?.some((tag) => tag.startsWith("language:"))
) || []
);
}, []);
const filterByVision = useCallback((boards) => {
return (
boards?.filter(
(board) =>
board.tags?.some(
(tag) => tag === "modality:video" || tag === "modality:image"
) ||
board.consolidated_tags?.some(
(tag) => tag === "modality:video" || tag === "modality:image"
)
) || []
);
}, []);
const filterUncategorized = useCallback((boards) => {
const categorizedTags = [
"eval:code",
"eval:math",
"modality:video",
"modality:image",
"modality:audio",
"modality:tools",
"domain:financial",
"domain:medical",
"domain:legal",
];
return (
boards?.filter((board) => {
if (
(!board.tags || board.tags.length === 0) &&
(!board.consolidated_tags || board.consolidated_tags.length === 0)
) {
return true;
}
const hasNoTagsInCategory = !board.tags?.some(
(tag) => categorizedTags.includes(tag) || tag.startsWith("language:")
);
const hasNoConsolidatedTagsInCategory = !board.consolidated_tags?.some(
(tag) => categorizedTags.includes(tag) || tag.startsWith("language:")
);
return hasNoTagsInCategory && hasNoConsolidatedTagsInCategory;
}) || []
);
}, []);
// Define sections
const allSections = useMemo(() => {
if (!leaderboards) return [];
return [
{
id: "code",
title: "Code",
data: filterByTag("eval:code", leaderboards),
},
{
id: "math",
title: "Math",
data: filterByTag("eval:math", leaderboards),
},
{
id: "language",
title: "Language Specific",
data: filterByLanguage(leaderboards),
},
{ id: "vision", title: "Vision", data: filterByVision(leaderboards) },
{
id: "audio",
title: "Audio",
data: filterByTag("modality:audio", leaderboards),
},
{
id: "agentic",
title: "Agentic",
data: filterByTag("modality:tools", leaderboards),
},
{
id: "financial",
title: "Financial",
data: filterByTag("domain:financial", leaderboards),
},
{
id: "medical",
title: "Medical",
data: filterByTag("domain:medical", leaderboards),
},
{
id: "legal",
title: "Legal",
data: filterByTag("domain:legal", leaderboards),
},
{
id: "uncategorized",
title: "Uncategorized",
data: filterUncategorized(leaderboards),
},
];
}, [
leaderboards,
filterByTag,
filterByLanguage,
filterByVision,
filterUncategorized,
]);
// Get sections with data
const sections = useMemo(() => {
return allSections.filter((section) => section.data.length > 0);
}, [allSections]);
// Filter leaderboards based on search query and arena toggle
const filterLeaderboards = useCallback(
(boards) => {
if (!boards) return [];
let filtered = [...boards];
// Filter by search query
if (searchQuery) {
const query = searchQuery.toLowerCase();
const searchableTagPrefixes = [
"domain:",
"language:",
"judge:",
"test:",
"modality:",
"submission:",
];
filtered = filtered.filter((board) => {
const isTagSearch = searchableTagPrefixes.some((prefix) =>
query.startsWith(prefix)
);
if (isTagSearch) {
return (
board.tags?.some((tag) => tag.toLowerCase().includes(query)) ||
board.consolidated_tags?.some((tag) =>
tag.toLowerCase().includes(query)
)
);
}
return board.card_data?.title?.toLowerCase().includes(query);
});
}
// Filter arena only
if (arenaOnly) {
filtered = filtered.filter(
(board) =>
board.tags?.includes("judge:humans") ||
board.consolidated_tags?.includes("judge:humans")
);
}
return filtered;
},
[searchQuery, arenaOnly]
);
// Get filtered count
const filteredCount = useMemo(() => {
return filterLeaderboards(leaderboards).length;
}, [filterLeaderboards, leaderboards]);
// Function to get highlighted parts of text
const getHighlightedText = useCallback((text, searchTerm) => {
if (!searchTerm || !text) return { text, shouldHighlight: false };
const query = searchTerm.toLowerCase();
const searchableTagPrefixes = [
"domain:",
"language:",
"judge:",
"test:",
"modality:",
"submission:",
];
// Si c'est une recherche par tag, on ne highlight rien
if (searchableTagPrefixes.some((prefix) => query.startsWith(prefix))) {
return { text, shouldHighlight: false };
}
// Sinon on highlight les parties qui matchent
const index = text.toLowerCase().indexOf(query);
if (index === -1) return { text, shouldHighlight: false };
return {
text,
shouldHighlight: true,
highlightStart: index,
highlightEnd: index + query.length,
};
}, []);
const value = {
leaderboards,
setLeaderboards,
searchQuery,
setSearchQuery,
arenaOnly,
setArenaOnly,
totalLeaderboards,
filteredCount,
filterLeaderboards,
sections,
allSections,
getHighlightedText,
};
return (
<LeaderboardContext.Provider value={value}>
{children}
</LeaderboardContext.Provider>
);
};
export const useLeaderboard = () => {
const context = useContext(LeaderboardContext);
if (!context) {
throw new Error("useLeaderboard must be used within a LeaderboardProvider");
}
return context;
};