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 0f1416d..6a51100 100644
--- a/src/components/Navigation/MainMenu.tsx
+++ b/src/components/Navigation/MainMenu.tsx
@@ -1,9 +1,11 @@
-import { FC, useCallback, useState } from "react"
+import { FC, useCallback, useState, useEffect, useMemo } from "react"
import { useSelector } from "react-redux"
import classnames from "classnames"
-import { isUserConnected, routerSelector, selectUserRoles } from "../../store/auth"
+import { isUserConnected, routerSelector, selectUserRoles, selectUserId } from "../../store/auth"
import styles from "./styles.module.scss"
import ROLES from "../../utils/roles.constants"
+import useAction from "../../utils/useAction"
+import { fetchVolunteerListIfNeed, selectVolunteerList } from "../../store/volunteerList"
interface MenuItemProps {
name: string
@@ -29,6 +31,27 @@ const RestrictMenuItem: FC = ({ name, pathname, role }):
return roles.includes(role) ? :
}
+interface TeamMenuItemProps extends MenuItemProps {
+ team: number
+}
+
+const TeamMenuItem: FC = ({ name, pathname, team }): JSX.Element => {
+ const fetch = useAction(fetchVolunteerListIfNeed)
+ const userId = useSelector(selectUserId)
+ useEffect(() => {
+ if (userId) fetch()
+ }, [userId, fetch])
+ const volunteers = useSelector(selectVolunteerList)
+ const user = useMemo(
+ () => volunteers.find((volunteer) => volunteer.id === userId),
+ [volunteers, userId]
+ )
+ return user?.team === team ? :
+}
+
+// Hardcoded value of the "Jeux à volonté" team
+const TEAM_JAV = 2
+
const MainMenu: FC = (): JSX.Element => {
const connected = useSelector(isUserConnected)
const [opened, setOpened] = useState(false)
@@ -54,7 +77,8 @@ 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,