diff --git a/src/components/Knowledge/KnowledgeStats.tsx b/src/components/Knowledge/KnowledgeStats.tsx
new file mode 100644
index 0000000..d3d8285
--- /dev/null
+++ b/src/components/Knowledge/KnowledgeStats.tsx
@@ -0,0 +1,60 @@
+import React, { memo } from "react"
+import { useSelector } from "react-redux"
+import styles from "./styles.module.scss"
+import { fetchBoxListIfNeed, selectSortedUniqueDetailedBoxes } from "../../store/boxList"
+import {
+ fetchVolunteerDetailedKnowledgeListIfNeed,
+ selectVolunteerDetailedKnowledgeList,
+} from "../../store/volunteerDetailedKnowledgeList"
+import { DetailedBox } from "../../services/boxes"
+import { VolunteerDetailedKnowledge } from "../../services/volunteers"
+
+const KnowledgeStats: React.FC = (): JSX.Element | null => {
+ const detailedBoxes = useSelector(selectSortedUniqueDetailedBoxes) as DetailedBox[]
+ const volunteerDetailedKnowledgeList = useSelector(selectVolunteerDetailedKnowledgeList)
+
+ const knowledgeStats = detailedBoxes.map((box) => ({
+ ok: wiseVolunteersNumber(volunteerDetailedKnowledgeList, box.gameId, "ok"),
+ bof: wiseVolunteersNumber(volunteerDetailedKnowledgeList, box.gameId, "bof"),
+ box,
+ }))
+
+ const unknownGames = knowledgeStats.filter((stat) => stat.ok === 0 && stat.bof === 0)
+
+ return (
+
+
{unknownGames.length} jeux non connus par des bénévoles :
+
+ {knowledgeStats
+ .filter((stat) => stat.ok === 0 && stat.bof === 0)
+ .map((stat) => (
+ -
+
+ {stat.box.title}
+
+
+ ))}
+
+
+ )
+}
+
+function wiseVolunteersNumber(
+ volunteersKnowledge: VolunteerDetailedKnowledge[],
+ gameId: number,
+ wiseness: "ok" | "bof"
+): number {
+ return volunteersKnowledge.filter(
+ (v) =>
+ v[wiseness].includes(gameId) && (v.dayWishes.includes("S") || v.dayWishes.includes("D"))
+ ).length
+}
+
+export default memo(KnowledgeStats)
+
+export const fetchFor = [fetchBoxListIfNeed, fetchVolunteerDetailedKnowledgeListIfNeed]
diff --git a/src/components/Navigation/MainMenu.tsx b/src/components/Navigation/MainMenu.tsx
index 9e95ea4..6a51100 100644
--- a/src/components/Navigation/MainMenu.tsx
+++ b/src/components/Navigation/MainMenu.tsx
@@ -78,6 +78,7 @@ const MainMenu: FC = (): JSX.Element => {
{/*
*/}
+
= (): JSX.Element => {
+ const jwtToken = useSelector(selectUserJwtToken)
+ if (jwtToken === undefined) return Loading...
+ if (!jwtToken) {
+ return
+ }
+ return (
+
+ )
+}
+
+// Fetch server-side data here
+export const loadData = (): AppThunk[] => [...fetchForKnowledgeCard.map((f) => f())]
+
+export default memo(KnowledgeStatsPage)
diff --git a/src/pages/KnowledgeStats/index.tsx b/src/pages/KnowledgeStats/index.tsx
new file mode 100644
index 0000000..b92a2a2
--- /dev/null
+++ b/src/pages/KnowledgeStats/index.tsx
@@ -0,0 +1,16 @@
+import loadable from "@loadable/component"
+
+import { Loading, ErrorBoundary } from "../../components"
+import { Props, loadData } from "./KnowledgeStatsPage"
+
+const Knowledges = loadable(() => import("./KnowledgeStatsPage"), {
+ fallback: ,
+})
+
+export default (props: Props): JSX.Element => (
+
+
+
+)
+
+export { loadData }
diff --git a/src/routes/index.ts b/src/routes/index.ts
index 309a7b2..f23a85f 100755
--- a/src/routes/index.ts
+++ b/src/routes/index.ts
@@ -10,6 +10,7 @@ import AsyncAnnouncements, { loadData as loadAnnouncementsData } from "../pages/
import AsyncTeamAssignment, { loadData as loadTeamAssignmentData } from "../pages/TeamAssignment"
import AsyncRegisterPage, { loadData as loadRegisterPage } from "../pages/Register"
import AsyncKnowledge, { loadData as loadKnowledgeData } from "../pages/Knowledge"
+import AsyncKnowledgeStats, { loadData as loadKnowledgeStatsData } from "../pages/KnowledgeStats"
// import AsyncLoans, { loadData as loadLoansData } from "../pages/Loans"
import AsyncLoaning, { loadData as loadLoaningData } from "../pages/Loaning"
import AsyncKnowledgeCards, { loadData as loadCardKnowledgeData } from "../pages/KnowledgeCards"
@@ -46,6 +47,11 @@ export default [
component: AsyncKnowledge,
loadData: loadKnowledgeData,
},
+ {
+ path: "/connaissancesStats",
+ component: AsyncKnowledgeStats,
+ loadData: loadKnowledgeStatsData,
+ },
// {
// path: "/emprunts",
// component: AsyncLoans,