diff --git a/src/components/Modal/styles.module.scss b/src/components/Modal/styles.module.scss
index 847b196..de18f9d 100755
--- a/src/components/Modal/styles.module.scss
+++ b/src/components/Modal/styles.module.scss
@@ -15,6 +15,7 @@
bottom: auto;
right: auto;
padding: 15px;
+ max-height: 80vh;
outline: 0;
background-color: $color-white;
border-radius: 15px;
diff --git a/src/components/VolunteerBoard/Board.tsx b/src/components/VolunteerBoard/Board.tsx
index cb77bcf..944d269 100644
--- a/src/components/VolunteerBoard/Board.tsx
+++ b/src/components/VolunteerBoard/Board.tsx
@@ -3,6 +3,8 @@ import DayWishes from "./DayWishes/DayWishes"
import DayWishesFormModal from "./DayWishesForm/DayWishesFormModal"
import ParticipationDetails from "./ParticipationDetails/ParticipationDetails"
import ParticipationDetailsFormModal from "./ParticipationDetailsForm/ParticipationDetailsFormModal"
+import TeamWishes from "./TeamWishes/TeamWishes"
+import TeamWishesFormModal from "./TeamWishesForm/TeamWishesFormModal"
import withUserConnected from "../../utils/withUserConnected"
const Board: FC = (): JSX.Element => (
@@ -11,6 +13,8 @@ const Board: FC = (): JSX.Element => (
+
+
)
diff --git a/src/components/VolunteerBoard/DayWishes/DayWishes.tsx b/src/components/VolunteerBoard/DayWishes/DayWishes.tsx
index beac804..f001c1d 100644
--- a/src/components/VolunteerBoard/DayWishes/DayWishes.tsx
+++ b/src/components/VolunteerBoard/DayWishes/DayWishes.tsx
@@ -22,9 +22,7 @@ const DayWishes: FC = (): JSX.Element | null => {
{comment && (
Mon commentaire :
-
- {get(userWishes, "dayWishesComment", "")}
-
+ {comment}
)}
diff --git a/src/components/VolunteerBoard/ParticipationDetails/ParticipationDetails.tsx b/src/components/VolunteerBoard/ParticipationDetails/ParticipationDetails.tsx
index d54ddb2..f9019bb 100644
--- a/src/components/VolunteerBoard/ParticipationDetails/ParticipationDetails.tsx
+++ b/src/components/VolunteerBoard/ParticipationDetails/ParticipationDetails.tsx
@@ -9,7 +9,7 @@ type Props = {
afterSubmit?: () => void | undefined
}
-const ParticipationDetailsForm: FC
= (): JSX.Element | null => {
+const ParticipationDetails: FC = (): JSX.Element | null => {
const [participationDetails] = useUserParticipationDetails()
const age = get(participationDetails, "age", "")
const tShirtSize = get(participationDetails, "teeshirtSize", "")
@@ -44,4 +44,4 @@ const ParticipationDetailsForm: FC = (): JSX.Element | null => {
)
}
-export default memo(ParticipationDetailsForm)
+export default memo(ParticipationDetails)
diff --git a/src/components/VolunteerBoard/TeamWishes/TeamWishes.tsx b/src/components/VolunteerBoard/TeamWishes/TeamWishes.tsx
new file mode 100644
index 0000000..b4c9956
--- /dev/null
+++ b/src/components/VolunteerBoard/TeamWishes/TeamWishes.tsx
@@ -0,0 +1,51 @@
+import { FC, memo, useCallback } from "react"
+import { useSelector } from "react-redux"
+import get from "lodash/get"
+import styles from "./styles.module.scss"
+import { displayModal, MODAL_IDS } from "../../../store/ui"
+import useAction from "../../../utils/useAction"
+import { useUserTeamWishes } from "../teamWishes.utils"
+import { selectTeamList } from "../../../store/teamList"
+
+type Props = {
+ afterSubmit?: () => void | undefined
+}
+
+const TeamWishes: FC = (): JSX.Element | null => {
+ const teams = useSelector(selectTeamList)
+ const [teamWishesData] = useUserTeamWishes()
+ const teamWishesString = get(teamWishesData, "teamWishes", [])
+ .map((id: number): string =>
+ get(
+ teams.find((team) => team && team.id === id),
+ "name",
+ ""
+ )
+ )
+ .filter((name: string) => name)
+ .join(", ")
+ const comment = get(teamWishesData, "teamWishesComment", "")
+ const execDisplayModal = useAction(displayModal)
+ const onEdit = useCallback(() => execDisplayModal(MODAL_IDS.TEAMWISHES), [execDisplayModal])
+
+ return (
+
+
Mes choix d'équipes
+ {teamWishesString &&
{teamWishesString}}
+ {!teamWishesString &&
Non renseignés}
+ {comment && (
+
+ Mon commentaire :
+ {comment}
+
+ )}
+
+
+
+
+ )
+}
+
+export default memo(TeamWishes)
diff --git a/src/components/VolunteerBoard/TeamWishes/styles.module.scss b/src/components/VolunteerBoard/TeamWishes/styles.module.scss
new file mode 100755
index 0000000..979460e
--- /dev/null
+++ b/src/components/VolunteerBoard/TeamWishes/styles.module.scss
@@ -0,0 +1,44 @@
+@import "../../../theme/variables";
+@import "../../../theme/mixins";
+
+.root {
+ @include inner-content-wrapper();
+
+ position: relative;
+ padding-right: 130px;
+}
+
+.title {
+ padding-bottom: 5px;
+ font-weight: bold;
+}
+
+.line {
+ margin: 2px 0;
+}
+
+.lineEmpty {
+ color: $color-red;
+ font-style: italic;
+}
+
+.commentLine {
+ span {
+ display: inline-block;
+ }
+}
+
+.commentLineTitle {
+ padding-right: 5px;
+}
+
+.commentLineText {
+ font-style: italic;
+}
+
+.editButton {
+ @include vertical-center();
+
+ position: absolute;
+ right: 20px;
+}
diff --git a/src/components/VolunteerBoard/TeamWishesForm/TeamWishesForm.tsx b/src/components/VolunteerBoard/TeamWishesForm/TeamWishesForm.tsx
new file mode 100644
index 0000000..577ea80
--- /dev/null
+++ b/src/components/VolunteerBoard/TeamWishesForm/TeamWishesForm.tsx
@@ -0,0 +1,94 @@
+import { FC, memo, useCallback, useEffect, useRef, useState } from "react"
+import { useSelector } from "react-redux"
+import get from "lodash/get"
+import set from "lodash/set"
+import classnames from "classnames"
+import styles from "./styles.module.scss"
+import { useUserTeamWishes } from "../teamWishes.utils"
+import { selectTeamList } from "../../../store/teamList"
+import useSelection from "../useSelection"
+
+type Props = {
+ afterSubmit?: () => void | undefined
+}
+
+const TeamWishesForm: FC = ({ afterSubmit }): JSX.Element | null => {
+ const teams = useSelector(selectTeamList)
+ const { addToSelection, toggleToSelection, isInSelection } = useSelection()
+ const commentRef = useRef(null)
+ const [userWishes, saveWishes] = useUserTeamWishes()
+ const [extendedTeam, setExtendedTeam] = useState(null)
+
+ useEffect(() => {
+ if (!userWishes) return
+ addToSelection(...get(userWishes, "teamWishes", []))
+ set(commentRef, "current.value", get(userWishes, "teamWishesComment", ""))
+ }, [userWishes, addToSelection])
+
+ const onTeamClick = useCallback((id) => toggleToSelection(id), [toggleToSelection])
+
+ const onExtendClick = useCallback(
+ (id) => setExtendedTeam(extendedTeam === id ? null : id),
+ [extendedTeam, setExtendedTeam]
+ )
+
+ console.log("extendedTeam", extendedTeam)
+
+ const onSubmit = useCallback(() => {
+ const teamWishesComment = get(commentRef, "current.value", "")
+ const teamWishes = teams
+ .map((team) => team && team.id)
+ .filter((id) => id && isInSelection(id))
+ saveWishes({ teamWishes, teamWishesComment })
+ if (afterSubmit) afterSubmit()
+ }, [teams, isInSelection, saveWishes, afterSubmit])
+
+ return (
+
+
Mes choix d'équipes
+
+ {teams.map((team: any) => (
+ -
+
+
+
{team.description}
+
+ ))}
+
+
+
+
+
+
+
+
+
+ )
+}
+
+TeamWishesForm.defaultProps = {
+ afterSubmit: undefined,
+}
+
+export default memo(TeamWishesForm)
diff --git a/src/components/VolunteerBoard/TeamWishesForm/TeamWishesFormModal.tsx b/src/components/VolunteerBoard/TeamWishesForm/TeamWishesFormModal.tsx
new file mode 100644
index 0000000..cb4d318
--- /dev/null
+++ b/src/components/VolunteerBoard/TeamWishesForm/TeamWishesFormModal.tsx
@@ -0,0 +1,18 @@
+import { FC, memo, useCallback } from "react"
+import { hideModal, MODAL_IDS } from "../../../store/ui"
+import Modal from "../../Modal/Modal"
+import useAction from "../../../utils/useAction"
+import TeamWishesForm from "./TeamWishesForm"
+
+const TeamWishesFormModal: FC = (): JSX.Element => {
+ const execHideModal = useAction(hideModal)
+ const afterFormSubmit = useCallback(() => execHideModal(), [execHideModal])
+
+ return (
+
+
+
+ )
+}
+
+export default memo(TeamWishesFormModal)
diff --git a/src/components/VolunteerBoard/TeamWishesForm/styles.module.scss b/src/components/VolunteerBoard/TeamWishesForm/styles.module.scss
new file mode 100755
index 0000000..50f276a
--- /dev/null
+++ b/src/components/VolunteerBoard/TeamWishesForm/styles.module.scss
@@ -0,0 +1,100 @@
+@import "../../../theme/variables";
+@import "../../../theme/mixins";
+
+.root {
+ width: 470px;
+}
+
+.title {
+ padding: 4px;
+ font-weight: bold;
+ text-align: center;
+}
+
+.inputWrapper {
+ margin: 10px 0;
+
+ label {
+ display: inline-block;
+ width: 170px;
+ }
+ input {
+ width: 300px;
+ border: 1px solid $color-grey-medium;
+ outline: 0;
+ }
+}
+
+.teamList {
+ @include clear-ul-style;
+}
+
+.teamLine {
+ position: relative;
+ margin: 4px 0;
+ background-color: $color-grey-lighter;
+}
+
+.teamButton {
+ display: block;
+ padding: 4px 6px;
+ background: none;
+ color: $color-grey-medium;
+ border-radius: 0;
+ width: 100%;
+ text-align: left;
+
+ .active & {
+ background-color: $color-black;
+ color: $color-yellow;
+ }
+}
+
+.extendButton {
+ position: absolute;
+ top: 2px;
+ right: 4px;
+ padding: 2px;
+ background: none;
+ color: $color-grey-dark;
+ border-radius: 0;
+ font-size: 0.9em;
+ font-weight: normal;
+
+ .active & {
+ color: $color-grey-light;
+ }
+}
+
+.teamDescription {
+ display: none;
+ padding: 2px 4px 6px 8px;
+ color: $color-grey-dark;
+ font-size: 0.95em;
+
+ .extended & {
+ display: block;
+ }
+}
+
+.commentWrapper {
+ margin: 6px 0;
+
+ label {
+ display: block;
+ padding: 6px 0 2px 4px;
+ }
+ textarea {
+ width: 100%;
+ height: 50px;
+ padding: 5px;
+ border: 1px solid $color-grey-light;
+ background-color: $color-grey-lighter;
+ outline: 0;
+ }
+}
+
+.buttonWrapper {
+ margin-bottom: 10px;
+ text-align: center;
+}
diff --git a/src/components/VolunteerBoard/teamWishes.utils.ts b/src/components/VolunteerBoard/teamWishes.utils.ts
new file mode 100644
index 0000000..41fa2eb
--- /dev/null
+++ b/src/components/VolunteerBoard/teamWishes.utils.ts
@@ -0,0 +1,29 @@
+import { useCallback } from "react"
+import { shallowEqual, useSelector } from "react-redux"
+import useAction from "../../utils/useAction"
+import { selectUserJwtToken } from "../../store/auth"
+import { AppState } from "../../store"
+import { fetchVolunteerTeamWishesSet } from "../../store/volunteerTeamWishesSet"
+
+export const useUserTeamWishes = (): [any, any] => {
+ const save = useAction(fetchVolunteerTeamWishesSet)
+ const jwtToken = useSelector(selectUserJwtToken)
+ const userTeamWishes = useSelector(
+ (state: AppState) => state.volunteerTeamWishesSet?.entity,
+ shallowEqual
+ )
+
+ const saveTeamWishes = useCallback(
+ ({ teamWishes, teamWishesComment }) => {
+ if (!userTeamWishes) return
+ save(jwtToken, 0, {
+ id: userTeamWishes.id,
+ teamWishes,
+ teamWishesComment,
+ })
+ },
+ [userTeamWishes, save, jwtToken]
+ )
+
+ return [userTeamWishes, saveTeamWishes]
+}
diff --git a/src/components/VolunteerBoard/useSelection.ts b/src/components/VolunteerBoard/useSelection.ts
new file mode 100644
index 0000000..12a7fe0
--- /dev/null
+++ b/src/components/VolunteerBoard/useSelection.ts
@@ -0,0 +1,87 @@
+import { useCallback, useMemo, useReducer } from "react"
+
+type valueType = string | number
+
+type selectionType = {
+ [key: string]: boolean
+}
+
+type State = {
+ selection: selectionType
+}
+
+type Action = { type: "add"; payload: valueType[] } | { type: "toggle"; payload: valueType }
+
+interface selectionHook {
+ addToSelection: (...values: valueType[]) => void
+ toggleToSelection: (value: valueType) => void
+ isInSelection: (value: valueType) => boolean
+}
+
+const initialState: State = {
+ selection: {},
+}
+
+const buildIndex = (value: valueType) => `item_${value}`
+
+const reducer = (state: State, action: Action): State => {
+ switch (action.type) {
+ case "add": {
+ const values = action.payload
+ return {
+ selection: values.reduce(
+ (acc: selectionType, value: valueType) => ({
+ ...acc,
+ [buildIndex(value)]: true,
+ }),
+ state.selection
+ ),
+ }
+ }
+ case "toggle": {
+ const value = action.payload
+ const index = buildIndex(value)
+ return {
+ selection: {
+ ...state.selection,
+ [index]: !state.selection[index],
+ },
+ }
+ }
+ default:
+ return state
+ }
+}
+
+const useSelection = (): selectionHook => {
+ const [state, dispatch] = useReducer(reducer, initialState)
+
+ const addToSelection = useCallback(
+ (...values: valueType[]) => {
+ dispatch({ type: "add", payload: values })
+ },
+ [dispatch]
+ )
+
+ const toggleToSelection = useCallback(
+ (value: valueType) => {
+ dispatch({ type: "toggle", payload: value })
+ },
+ [dispatch]
+ )
+
+ const isInSelection = useCallback(
+ (value: valueType) => {
+ const index = buildIndex(value)
+ return state.selection[index]
+ },
+ [state.selection]
+ )
+
+ return useMemo(
+ () => ({ addToSelection, toggleToSelection, isInSelection }),
+ [addToSelection, toggleToSelection, isInSelection]
+ )
+}
+
+export default useSelection
diff --git a/src/pages/Board/Board.tsx b/src/pages/Board/Board.tsx
index aa4960d..dc93d7c 100644
--- a/src/pages/Board/Board.tsx
+++ b/src/pages/Board/Board.tsx
@@ -3,11 +3,13 @@ import { RouteComponentProps } from "react-router-dom"
import { useSelector } from "react-redux"
import { AppThunk } from "../../store"
-import { fetchVolunteerDayWishesSetIfNeed } from "../../store/volunteerDayWishesSet"
import { selectUserJwtToken } from "../../store/auth"
import Page from "../../components/Page/Page"
import Board from "../../components/VolunteerBoard/Board"
+import { fetchVolunteerDayWishesSetIfNeed } from "../../store/volunteerDayWishesSet"
import { fetchVolunteerParticipationDetailsSetIfNeed } from "../../store/volunteerParticipationDetailsSet"
+import { fetchVolunteerTeamWishesSetIfNeed } from "../../store/volunteerTeamWishesSet"
+import { fetchTeamListIfNeed } from "../../store/teamList"
export type Props = RouteComponentProps
@@ -29,6 +31,8 @@ const BoardPage: FC = (): JSX.Element => {
export const loadData = (): AppThunk[] => [
fetchVolunteerDayWishesSetIfNeed(),
fetchVolunteerParticipationDetailsSetIfNeed(),
+ fetchVolunteerTeamWishesSetIfNeed(),
+ fetchTeamListIfNeed(),
]
export default memo(BoardPage)
diff --git a/src/store/ui.ts b/src/store/ui.ts
index cd6cb9c..3148b24 100644
--- a/src/store/ui.ts
+++ b/src/store/ui.ts
@@ -29,4 +29,5 @@ export const selectActiveModalId = createSelector(selectUiData, (ui) => ui.modal
export const MODAL_IDS = {
DAYWISHES: "DAYWISHES",
PARTICIPATIONDETAILS: "PARTICIPATIONDETAILS",
+ TEAMWISHES: "TEAMWISHES",
}