diff --git a/src/app/img/knowledgeCards/duree-fiche.png b/src/app/img/knowledgeCards/duree-fiche.png
new file mode 100644
index 0000000..aa3e390
Binary files /dev/null and b/src/app/img/knowledgeCards/duree-fiche.png differ
diff --git a/src/app/img/knowledgeCards/jauge-orange.png b/src/app/img/knowledgeCards/jauge-orange.png
new file mode 100644
index 0000000..be47fb7
Binary files /dev/null and b/src/app/img/knowledgeCards/jauge-orange.png differ
diff --git a/src/app/img/knowledgeCards/jauge-rouge.png b/src/app/img/knowledgeCards/jauge-rouge.png
new file mode 100644
index 0000000..5874265
Binary files /dev/null and b/src/app/img/knowledgeCards/jauge-rouge.png differ
diff --git a/src/app/img/knowledgeCards/jauge-verte.png b/src/app/img/knowledgeCards/jauge-verte.png
new file mode 100644
index 0000000..59d63ee
Binary files /dev/null and b/src/app/img/knowledgeCards/jauge-verte.png differ
diff --git a/src/app/img/knowledgeCards/nombre_joueurs-fiche.png b/src/app/img/knowledgeCards/nombre_joueurs-fiche.png
new file mode 100644
index 0000000..73ac3fe
Binary files /dev/null and b/src/app/img/knowledgeCards/nombre_joueurs-fiche.png differ
diff --git a/src/app/img/knowledgeCards/ppp-fiche-ko-trespetit.png b/src/app/img/knowledgeCards/ppp-fiche-ko-trespetit.png
new file mode 100644
index 0000000..8d8c4e1
Binary files /dev/null and b/src/app/img/knowledgeCards/ppp-fiche-ko-trespetit.png differ
diff --git a/src/app/img/knowledgeCards/ppp-fiche-trespetit.png b/src/app/img/knowledgeCards/ppp-fiche-trespetit.png
new file mode 100644
index 0000000..cec9a71
Binary files /dev/null and b/src/app/img/knowledgeCards/ppp-fiche-trespetit.png differ
diff --git a/src/app/index.tsx b/src/app/index.tsx
index bc6a5b9..4520708 100755
--- a/src/app/index.tsx
+++ b/src/app/index.tsx
@@ -12,37 +12,46 @@ import LogoutButton from "../components/LogoutButton/LogoutButton"
interface Route {
route: { routes: RouteConfig[] }
+ location: Location
}
export const reactAppId = "react-view"
-const App = ({ route }: Route): JSX.Element => (
-
-
-
-
-
-
-
-
-
{config.APP.description}
-
-
-
-
-
-
-
-
- {/* Child routes won't render without this */}
- {renderRoutes(route.routes)}
-
-
-)
+// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
+const App = ({ route, location }: Route): JSX.Element => {
+ if (location.pathname === "/fiches") {
+ return {renderRoutes(route.routes)}
+ }
+ // else
+
+ return (
+
+
+
+
+
+
+
+
+
{config.APP.description}
+
+
+
+
+
+
+
+
+ {/* Child routes won't render without this */}
+ {renderRoutes(route.routes)}
+
+
+ )
+}
export default App
diff --git a/src/app/styles.module.scss b/src/app/styles.module.scss
index 494f4ed..cb36169 100755
--- a/src/app/styles.module.scss
+++ b/src/app/styles.module.scss
@@ -2,6 +2,13 @@
@import "../theme/mixins";
@import "../theme/main";
+.cardPage {
+ background-color: $color-white;
+ // overflow: auto;
+ display: table;
+ width: 100vw;
+}
+
.header {
position: relative;
margin: 10px 0 20px;
diff --git a/src/components/Knowledge/KnowledgeCard.tsx b/src/components/Knowledge/KnowledgeCard.tsx
new file mode 100644
index 0000000..c0976ce
--- /dev/null
+++ b/src/components/Knowledge/KnowledgeCard.tsx
@@ -0,0 +1,167 @@
+import React, { memo } from "react"
+import { useSelector } from "react-redux"
+import styles from "./styles.module.scss"
+// import styles from "./styles.module.scss"
+import { fetchBoxListIfNeed, selectContainerSortedDetailedBoxes } from "../../store/boxList"
+import {
+ fetchVolunteerDetailedKnowledgeListIfNeed,
+ selectVolunteerDetailedKnowledgeList,
+} from "../../store/volunteerDetailedKnowledgeList"
+import { DetailedBox } from "../../services/boxes"
+import { VolunteerDetailedKnowledge } from "../../services/volunteers"
+
+const KnowledgeCard: React.FC = (): JSX.Element | null => {
+ const detailedBoxes = useSelector(selectContainerSortedDetailedBoxes) as DetailedBox[]
+ const volunteerDetailedKnowledgeList = useSelector(selectVolunteerDetailedKnowledgeList)
+
+ return <>{detailedBoxes.map((box) => boxElement(box, volunteerDetailedKnowledgeList))}>
+}
+
+const boxElement = (
+ box: DetailedBox,
+ volunteerDetailedKnowledgeList: VolunteerDetailedKnowledge[]
+): JSX.Element => {
+ const playerCount: string =
+ box.playersMin === box.playersMax
+ ? `${box.playersMin}`
+ : `${box.playersMin} à ${box.playersMax}`
+
+ const typeStyle = {
+ "": null,
+ Ambiance: styles.verteImg,
+ Famille: styles.orangeImg,
+ Expert: styles.rougeImg,
+ }[box.type]
+
+ const year = new Date().getFullYear()
+
+ const okVolunteers = wiseVolunteers(volunteerDetailedKnowledgeList, box.gameId, "ok")
+ const bofVolunteers = wiseVolunteers(volunteerDetailedKnowledgeList, box.gameId, "bof")
+ const someOk = okVolunteers.length > 0
+ const someBof = bofVolunteers.length > 0
+ const some = someOk || someBof
+
+ return (
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+ Ils maîtrisent |
+
+
+
+
+ {okVolunteers}
+ {!some && (
+ <>
+ Désolé aucun bénévole n'y a joué, il
+ va falloir lire la règle.
+ >
+ )}
+ {!someOk && someBof && (
+ <>
+ Aucun bénévole ne maîtrise les
+ règles de ce jeu.
+ >
+ )}
+
+ |
+
+ {someBof && (
+
+ Ils connaissent |
+
+ )}
+ {someBof && (
+
+
+
+ {bofVolunteers}
+
+ |
+
+ )}
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+ |
+ {playerCount} |
+
+
+
+ |
+ {box.duration} min |
+
+
+
+ |
+ {box.type} |
+
+
+
+ |
+
+
+
+
+
+
+
+ )
+}
+
+function wiseVolunteers(
+ volunteersKnowledge: VolunteerDetailedKnowledge[],
+ gameId: number,
+ wiseness: "ok" | "bof"
+): JSX.Element[] {
+ return volunteersKnowledge
+ .filter(
+ (v) =>
+ v[wiseness].includes(gameId) &&
+ (v.dayWishes.includes("S") || v.dayWishes.includes("D"))
+ )
+ .map((v) => (
+
+ {v.nickname.charAt(0).toUpperCase()}
+ {v.nickname.substring(1)}
+ {v.dayWishes.includes("S") && !v.dayWishes.includes("D") && (
+ (sam.)
+ )}
+ {!v.dayWishes.includes("S") && v.dayWishes.includes("D") && (
+ (dim.)
+ )}
+
+ ))
+}
+
+export default memo(KnowledgeCard)
+
+export const fetchFor = [fetchBoxListIfNeed, fetchVolunteerDetailedKnowledgeListIfNeed]
diff --git a/src/components/Knowledge/styles.module.scss b/src/components/Knowledge/styles.module.scss
index 6ed755c..487b1d0 100755
--- a/src/components/Knowledge/styles.module.scss
+++ b/src/components/Knowledge/styles.module.scss
@@ -122,3 +122,181 @@
background-color: $color-active-niet;
}
}
+
+/* Cards */
+
+.card {
+ display: inline-block;
+ vertical-align: top;
+ width: 48vw;
+ margin: 1vw;
+ break-inside: avoid;
+ border: $color-black solid 0.1vw;
+}
+
+.header {
+ color: $color-white;
+ background-color: #e18502;
+ text-align: center;
+ font-size: 2.5vw;
+ line-height: 5vw;
+ font-family: $font-pel;
+}
+.imageContainer {
+ padding: 1vw;
+}
+
+.benevolesContainer {
+ width: 100%;
+}
+.tableBenevoles {
+ width: 100%;
+ vertical-align: top;
+ padding-top: 1vw;
+}
+.gameImage {
+ width: 10vw;
+}
+
+.okHeader,
+.bofHeader {
+ text-align: center;
+ width: 100%;
+ font-size: 1.8vw;
+ font-weight: bold;
+}
+.okHeader {
+ background-color: #9dba5d;
+}
+.listOk {
+ text-align: center;
+}
+.listOk td {
+ padding-top: 15px;
+ padding-bottom: 15px;
+}
+.bofHeader {
+ background-color: #cb9902;
+}
+.listBof {
+ text-align: center;
+}
+.listBof td {
+ padding-top: 15px;
+ padding-bottom: 15px;
+}
+
+.nicknameContainer {
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: space-evenly;
+ align-content: center;
+ gap: 0.5vw;
+}
+.nickname {
+ flex: 1 1 auto;
+ white-space: nowrap;
+}
+
+.numberOfPlayersImgContainer {
+ width: 6.3vw;
+}
+
+.numberOfPlayersImg {
+ width: 6vw;
+ height: 4vw;
+ background: url("../../app/img/knowledgeCards/nombre_joueurs-fiche.png") no-repeat center center;
+ background-size: cover;
+}
+.numberOfPlayers {
+ font-family: $font-pel;
+ font-size: 1.6vw;
+ white-space: nowrap;
+}
+
+.durationImgContainer {
+ width: 6.1vw;
+ padding-left: 1vw;
+}
+.durationImg {
+ width: 6vw;
+ height: 4vw;
+ background: url("../../app/img/knowledgeCards/duree-fiche.png") no-repeat center center;
+ background-size: cover;
+}
+.duration {
+ font-family: $font-pel;
+ font-size: 1.6vw;
+ white-space: nowrap;
+}
+
+.typeImgContainer {
+ width: 6.2vw;
+ padding-left: 1.1vw;
+}
+.verteImg,
+.orangeImg,
+.rougeImg {
+ width: 6vw;
+ height: 6vw;
+ background-size: cover;
+}
+.verteImg {
+ background: url("../../app/img/knowledgeCards/jauge-verte.png") no-repeat center center;
+}
+.orangeImg {
+ background: url("../../app/img/knowledgeCards/jauge-orange.png") no-repeat center center;
+}
+.rougeImg {
+ background: url("../../app/img/knowledgeCards/jauge-rouge.png") no-repeat center center;
+}
+
+.type {
+ font-family: $font-pel;
+ font-size: 1.6vw;
+ white-space: nowrap;
+}
+
+.pppImgContainer {
+ width: 6vw;
+ padding-left: 0.7vw;
+}
+.pppImg {
+ width: 6vw;
+ height: 3.4vw;
+ background: url("../../app/img/knowledgeCards/ppp-fiche-ko-trespetit.png") no-repeat center
+ center;
+ background-size: cover;
+}
+
+.oneDayOnly {
+ color: $color-red;
+}
+
+.footer {
+ height: 3vw;
+ font-family: $font-pel;
+ display: flex;
+ flex-direction: row;
+ flex-wrap: nowrap;
+ justify-content: space-between;
+ align-content: center;
+ background-color: #96b397;
+ font-style: oblique;
+}
+
+.year {
+ flex: 0 1 auto;
+ align-self: center;
+ margin-left: 1vw;
+ font-size: 1vw;
+}
+
+.container {
+ flex: 0 1 auto;
+ align-self: center;
+ margin-right: 1vw;
+ font-size: 1.5vw;
+}
diff --git a/src/components/index.ts b/src/components/index.ts
index 7532b2c..b9c92f4 100755
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -10,6 +10,7 @@ import GameList from "./GameList"
import Loading from "./Loading"
import LoginForm from "./LoginForm"
import BoxList, { fetchFor as fetchForKnowledge } from "./Knowledge/BoxList"
+import KnowledgeCard, { fetchFor as fetchForKnowledgeCard } from "./Knowledge/KnowledgeCard"
import KnowledgeIntro from "./Knowledge/KnowledgeIntro"
import Asks, { fetchFor as fetchForAsks } from "./Asks"
import ParticipationDetailsForm, {
@@ -34,6 +35,8 @@ export {
fetchForBoard,
BoxList,
fetchForKnowledge,
+ KnowledgeCard,
+ fetchForKnowledgeCard,
DayWishesForm,
fetchForDayWishesForm,
ErrorBoundary,
diff --git a/src/pages/KnowledgeCards/KnowledgeCardsPage.tsx b/src/pages/KnowledgeCards/KnowledgeCardsPage.tsx
new file mode 100644
index 0000000..1dc4507
--- /dev/null
+++ b/src/pages/KnowledgeCards/KnowledgeCardsPage.tsx
@@ -0,0 +1,23 @@
+import { FC, memo } from "react"
+import { useSelector } from "react-redux"
+import { RouteComponentProps } from "react-router-dom"
+
+import { AppThunk } from "../../store"
+import { KnowledgeCard, fetchForKnowledgeCard } from "../../components"
+import { selectUserJwtToken } from "../../store/auth"
+
+export type Props = RouteComponentProps
+
+const KnowledgeCardsPage: FC = (): JSX.Element => {
+ const jwtToken = useSelector(selectUserJwtToken)
+ if (jwtToken === undefined) return Loading...
+ if (!jwtToken) {
+ return Besoin d'être identifié
+ }
+ return
+}
+
+// Fetch server-side data here
+export const loadData = (): AppThunk[] => [...fetchForKnowledgeCard.map((f) => f())]
+
+export default memo(KnowledgeCardsPage)
diff --git a/src/pages/KnowledgeCards/index.tsx b/src/pages/KnowledgeCards/index.tsx
new file mode 100755
index 0000000..5cfac27
--- /dev/null
+++ b/src/pages/KnowledgeCards/index.tsx
@@ -0,0 +1,16 @@
+import loadable from "@loadable/component"
+
+import { Loading, ErrorBoundary } from "../../components"
+import { Props, loadData } from "./KnowledgeCardsPage"
+
+const Knowledges = loadable(() => import("./KnowledgeCardsPage"), {
+ fallback: ,
+})
+
+export default (props: Props): JSX.Element => (
+
+
+
+)
+
+export { loadData }
diff --git a/src/pages/KnowledgeCards/styles.module.scss b/src/pages/KnowledgeCards/styles.module.scss
new file mode 100755
index 0000000..4c6d8ae
--- /dev/null
+++ b/src/pages/KnowledgeCards/styles.module.scss
@@ -0,0 +1,9 @@
+@import "../../theme/mixins";
+
+.knowledgesPage {
+ @include page-wrapper-center;
+}
+
+.knowledgesContent {
+ @include page-content-wrapper(700px);
+}
diff --git a/src/routes/index.ts b/src/routes/index.ts
index 99a253b..af39210 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 AsyncKnowledgeCards, { loadData as loadCardKnowledgeData } from "../pages/KnowledgeCards"
import AsyncTeams, { loadData as loadTeamsData } from "../pages/Teams"
import AsyncBoard, { loadData as loadBoardData } from "../pages/Board"
import AsyncVolunteers, { loadData as loadVolunteersData } from "../pages/Volunteers"
@@ -43,6 +44,12 @@ export default [
component: AsyncKnowledge,
loadData: loadKnowledgeData,
},
+ {
+ path: "/fiches",
+ component: AsyncKnowledgeCards,
+ loadData: loadCardKnowledgeData,
+ meh: "doh",
+ },
{
path: "/preRegister",
component: AsyncRegisterPage,
diff --git a/src/server/gsheets/boxes.ts b/src/server/gsheets/boxes.ts
index 2487df0..36df262 100644
--- a/src/server/gsheets/boxes.ts
+++ b/src/server/gsheets/boxes.ts
@@ -14,6 +14,7 @@ export const detailedBoxListGet = expressAccessor.get(async (list) => {
}
return list
+ .filter((box) => box)
.filter((box) => !box.unplayable)
.map((box) => {
const game = gameList.find((g) => g.id === box.gameId)
@@ -27,6 +28,11 @@ export const detailedBoxListGet = expressAccessor.get(async (list) => {
bggPhoto: game.bggPhoto,
poufpaf: game.poufpaf,
bggId: game.bggId,
+ container: box.container,
+ playersMin: game.playersMin,
+ playersMax: game.playersMax,
+ duration: game.duration,
+ type: game.type,
} as DetailedBox
})
})
diff --git a/src/server/gsheets/games.ts b/src/server/gsheets/games.ts
index d8a7172..5171786 100644
--- a/src/server/gsheets/games.ts
+++ b/src/server/gsheets/games.ts
@@ -13,14 +13,7 @@ export const gameListGet = expressAccessor.listGet()
// export const gameAdd = expressAccessor.add()
// export const gameSet = expressAccessor.set()
-export const gameDetailsUpdate = expressAccessor.listSet(async (list, _body, _id, roles) => {
- if (!roles.includes("admin")) {
- throw Error(
- `À moins d'être admin, on ne peut pas modifier n'importe quel jeu, ${JSON.stringify(
- roles
- )}`
- )
- }
+export const gameDetailsUpdate = expressAccessor.listSet(async (list) => {
const newList = cloneDeep(list)
// TODO update game list details from BGG
diff --git a/src/server/gsheets/volunteers.ts b/src/server/gsheets/volunteers.ts
index 3eceb07..0287369 100644
--- a/src/server/gsheets/volunteers.ts
+++ b/src/server/gsheets/volunteers.ts
@@ -1,6 +1,6 @@
import path from "path"
import * as fs from "fs"
-import { assign, cloneDeep, max, omit, pick } from "lodash"
+import { assign, cloneDeep, max, omit, pick, remove } from "lodash"
import bcrypt from "bcrypt"
import sgMail from "@sendgrid/mail"
@@ -18,6 +18,7 @@ import {
VolunteerParticipationDetails,
VolunteerTeamAssign,
VolunteerKnowledge,
+ VolunteerDetailedKnowledge,
VolunteerPersonalInfo,
} from "../../services/volunteers"
import { canonicalEmail, canonicalMobile, trim, validMobile } from "../../utils/standardization"
@@ -533,3 +534,34 @@ export const volunteerKnowledgeSet = expressAccessor.set(async (list, body, id)
} as VolunteerKnowledge,
}
})
+
+export const volunteerDetailedKnowledgeList = expressAccessor.get(async (list) => {
+ const volunteerList = list.filter((v) => v.team === 2)
+
+ return volunteerList.map((volunteer) => {
+ const nickname = getUniqueNickname(volunteerList, volunteer)
+
+ return {
+ id: volunteer.id,
+ nickname,
+ ok: volunteer.ok,
+ bof: volunteer.bof,
+ niet: volunteer.niet,
+ dayWishes: volunteer.dayWishes,
+ } as VolunteerDetailedKnowledge
+ })
+})
+
+function getUniqueNickname(list: Volunteer[], volunteer: Volunteer): string {
+ const lastnameList = list
+ .filter((v) => v.firstname === volunteer.firstname)
+ .map((v) => v.lastname)
+ let lastnamePrefix = ""
+ while (lastnameList.length > 1) {
+ lastnamePrefix += volunteer.lastname.charAt(lastnamePrefix.length)
+ // eslint-disable-next-line no-loop-func
+ remove(lastnameList, (lastname) => !lastname.startsWith(lastnamePrefix))
+ }
+ const nickname = `${volunteer.firstname}${lastnamePrefix ? ` ${lastnamePrefix}.` : ""}`
+ return nickname
+}
diff --git a/src/server/index.ts b/src/server/index.ts
index ba42158..49fe7be 100755
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -38,6 +38,7 @@ import {
volunteerListGet,
volunteerKnowledgeSet,
volunteerAddNew,
+ volunteerDetailedKnowledgeList,
} from "./gsheets/volunteers"
import { wishListGet, wishAdd } from "./gsheets/wishes"
import config from "../config"
@@ -92,6 +93,7 @@ app.get(
* APIs
*/
// Google Sheets API
+app.get("/GameDetailsUpdate", gameDetailsUpdate)
app.get("/BoxDetailedListGet", detailedBoxListGet)
app.get("/GameListGet", gameListGet)
app.get("/MiscMeetingDateListGet", miscMeetingDateListGet)
@@ -110,6 +112,11 @@ app.get("/TeamListGet", teamListGet)
app.get("/VolunteerDiscordId", secure as RequestHandler, volunteerDiscordId)
app.post("/VolunteerAsksSet", secure as RequestHandler, volunteerAsksSet)
app.post("/VolunteerKnowledgeSet", secure as RequestHandler, volunteerKnowledgeSet)
+app.post(
+ "/VolunteerDetailedKnowledgeListGet",
+ secure as RequestHandler,
+ volunteerDetailedKnowledgeList
+)
app.post(
"/VolunteerParticipationDetailsSet",
secure as RequestHandler,
@@ -125,7 +132,6 @@ app.post("/VolunteerTeamAssignSet", secure as RequestHandler, volunteerTeamAssig
// Admin only
app.post("/VolunteerAddNew", secure as RequestHandler, volunteerAddNew)
app.post("/VolunteerSet", secure as RequestHandler, volunteerSet)
-app.get("/GameDetailsUpdate", secure as RequestHandler, gameDetailsUpdate)
// Push notification subscription
app.post("/notifications/subscribe", notificationsSubscribe)
diff --git a/src/services/boxes.ts b/src/services/boxes.ts
index 7dad63c..5bc42ad 100644
--- a/src/services/boxes.ts
+++ b/src/services/boxes.ts
@@ -43,6 +43,16 @@ export class DetailedBox {
poufpaf = new Game().poufpaf
bggId = new Game().bggId
+
+ playersMin = new Game().playersMin
+
+ playersMax = new Game().playersMax
+
+ duration = new Game().duration
+
+ type = new Game().type
+
+ container = ""
}
export type DetailedBoxWithoutId = Omit
diff --git a/src/services/volunteers.ts b/src/services/volunteers.ts
index 0154ea4..ad91ae4 100644
--- a/src/services/volunteers.ts
+++ b/src/services/volunteers.ts
@@ -238,3 +238,13 @@ export interface VolunteerKnowledge {
bof: Volunteer["bof"]
niet: Volunteer["niet"]
}
+
+export type VolunteerDetailedKnowledgeWithoutId = Omit
+export interface VolunteerDetailedKnowledge {
+ id: Volunteer["id"]
+ nickname: string
+ ok: Volunteer["ok"]
+ bof: Volunteer["bof"]
+ niet: Volunteer["niet"]
+ dayWishes: Volunteer["dayWishes"]
+}
diff --git a/src/services/volunteersAccessors.ts b/src/services/volunteersAccessors.ts
index f1904be..2a0d869 100644
--- a/src/services/volunteersAccessors.ts
+++ b/src/services/volunteersAccessors.ts
@@ -60,3 +60,7 @@ export const volunteerTeamAssignSet =
export const volunteerKnowledgeSet =
serviceAccessors.securedCustomPost<[number, Partial]>("KnowledgeSet")
+
+export const volunteerDetailedKnowledgeList = serviceAccessors.securedCustomPost<[number]>(
+ "DetailedKnowledgeListGet"
+)
diff --git a/src/store/boxList.ts b/src/store/boxList.ts
index cad79bd..8b84459 100644
--- a/src/store/boxList.ts
+++ b/src/store/boxList.ts
@@ -2,11 +2,11 @@ import { PayloadAction, createSlice, createEntityAdapter, createSelector } from
import { sortedUniqBy, sortBy } from "lodash"
import { StateRequest, toastError, elementListFetch } from "./utils"
-import { Box } from "../services/boxes"
+import { DetailedBox } from "../services/boxes"
import { AppThunk, AppState, EntitiesRequest } from "."
import { detailedBoxListGet } from "../services/boxesAccessors"
-const boxAdapter = createEntityAdapter()
+const boxAdapter = createEntityAdapter()
export const initialState = boxAdapter.getInitialState({
readyStatus: "idle",
@@ -19,7 +19,7 @@ const boxList = createSlice({
getRequesting: (state) => {
state.readyStatus = "request"
},
- getSuccess: (state, { payload }: PayloadAction) => {
+ getSuccess: (state, { payload }: PayloadAction) => {
state.readyStatus = "success"
boxAdapter.setAll(state, payload)
},
@@ -49,7 +49,7 @@ export const fetchBoxListIfNeed = (): AppThunk => (dispatch, getState) => {
return null
}
-export const selectBoxListState = (state: AppState): EntitiesRequest => state.boxList
+export const selectBoxListState = (state: AppState): EntitiesRequest => state.boxList
export const selectBoxList = createSelector(
selectBoxListState,
@@ -60,11 +60,9 @@ export const selectBoxList = createSelector(
)
export const selectSortedUniqueDetailedBoxes = createSelector(selectBoxList, (boxes) =>
- sortedUniqBy(
- sortBy(
- boxes.filter((box) => box && !box.unplayable),
- "title"
- ),
- "title"
- )
+ sortedUniqBy(sortBy(boxes, "title"), "title")
+)
+
+export const selectContainerSortedDetailedBoxes = createSelector(selectBoxList, (boxes) =>
+ sortBy(boxes, "container")
)
diff --git a/src/store/rootReducer.ts b/src/store/rootReducer.ts
index 79f0fe4..485c284 100644
--- a/src/store/rootReducer.ts
+++ b/src/store/rootReducer.ts
@@ -21,6 +21,7 @@ import volunteerMealsSet from "./volunteerMealsSet"
import volunteerList from "./volunteerList"
import volunteerLogin from "./volunteerLogin"
import volunteerKnowledgeSet from "./volunteerKnowledgeSet"
+import volunteerDetailedKnowledgeList from "./volunteerDetailedKnowledgeList"
import volunteerParticipationDetailsSet from "./volunteerParticipationDetailsSet"
import volunteerPersonalInfoSet from "./volunteerPersonalInfoSet"
import volunteerSet from "./volunteerSet"
@@ -52,6 +53,7 @@ export default (history: History) => ({
volunteerList,
volunteerLogin,
volunteerKnowledgeSet,
+ volunteerDetailedKnowledgeList,
volunteerParticipationDetailsSet,
volunteerPersonalInfoSet,
volunteerSet,
diff --git a/src/store/volunteerDetailedKnowledgeList.ts b/src/store/volunteerDetailedKnowledgeList.ts
new file mode 100644
index 0000000..36db999
--- /dev/null
+++ b/src/store/volunteerDetailedKnowledgeList.ts
@@ -0,0 +1,72 @@
+import { PayloadAction, createSlice, createSelector, createEntityAdapter } from "@reduxjs/toolkit"
+import { StateRequest, toastError, elementListFetch } from "./utils"
+import { VolunteerDetailedKnowledge } from "../services/volunteers"
+import { AppThunk, AppState, EntitiesRequest } from "."
+import { volunteerDetailedKnowledgeList } from "../services/volunteersAccessors"
+
+const knowledgeAdapter = createEntityAdapter()
+
+export const initialState = knowledgeAdapter.getInitialState({
+ readyStatus: "idle",
+} as StateRequest)
+
+const volunteerDetailedKnowledgeListSlice = createSlice({
+ name: "volunteerDetailedKnowledgeList",
+ initialState,
+ reducers: {
+ getRequesting: (state) => {
+ state.readyStatus = "request"
+ },
+ getSuccess: (state, { payload }: PayloadAction) => {
+ state.readyStatus = "success"
+ knowledgeAdapter.setAll(state, payload)
+ },
+ getFailure: (state, { payload }: PayloadAction) => {
+ state.readyStatus = "failure"
+ state.error = payload
+ },
+ },
+})
+
+export default volunteerDetailedKnowledgeListSlice.reducer
+export const { getRequesting, getSuccess, getFailure } = volunteerDetailedKnowledgeListSlice.actions
+
+export const fetchVolunteerDetailedKnowledgeList = elementListFetch(
+ volunteerDetailedKnowledgeList,
+ getRequesting,
+ getSuccess,
+ getFailure,
+ (error: Error) =>
+ toastError(
+ `Erreur lors du chargement de la liste de connaissances détaillée: ${error.message}`
+ )
+)
+
+const shouldFetchVolunteerDetailedKnowledgeList = (state: AppState) =>
+ state.volunteerDetailedKnowledgeList?.readyStatus !== "success"
+
+export const fetchVolunteerDetailedKnowledgeListIfNeed =
+ (id = 0): AppThunk =>
+ (dispatch, getState) => {
+ let jwt = ""
+
+ if (!id) {
+ ;({ jwt, id } = getState().auth)
+ }
+ if (shouldFetchVolunteerDetailedKnowledgeList(getState()))
+ return dispatch(fetchVolunteerDetailedKnowledgeList(jwt, id))
+
+ return null
+ }
+
+export const selectVolunteerDetailedKnowledgeListState = (
+ state: AppState
+): EntitiesRequest => state.volunteerDetailedKnowledgeList
+
+export const selectVolunteerDetailedKnowledgeList = createSelector(
+ selectVolunteerDetailedKnowledgeListState,
+ ({ ids, entities, readyStatus }) => {
+ if (readyStatus !== "success") return []
+ return ids.map((id) => entities[id]) as VolunteerDetailedKnowledge[]
+ }
+)