mirror of
https://github.com/Paris-est-Ludique/intranet.git
synced 2025-06-08 08:34:20 +02:00
Add Meals form and ask; Add disabling registration
This commit is contained in:
parent
fac06c1b41
commit
ff05fed345
38
src/components/Asks/AskMeals.tsx
Normal file
38
src/components/Asks/AskMeals.tsx
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import { get } from "lodash"
|
||||||
|
import { useCallback } from "react"
|
||||||
|
import { fetchVolunteerAsksSet } from "../../store/volunteerAsksSet"
|
||||||
|
import { useAskTools, addAsk, answerLaterOnProfile } from "./utils"
|
||||||
|
import MealsForm, { fetchFor as fetchForMealsForm } from "../VolunteerBoard/MealsForm/MealsForm"
|
||||||
|
import { useUserMeals } from "../VolunteerBoard/meals.utils"
|
||||||
|
|
||||||
|
export function AskMeals(asks: JSX.Element[], id: number): void {
|
||||||
|
const { dispatch, jwtToken, volunteerAsks } = useAskTools()
|
||||||
|
|
||||||
|
const onSubmit = useCallback((): void => {
|
||||||
|
dispatch(
|
||||||
|
fetchVolunteerAsksSet(jwtToken, 0, {
|
||||||
|
hiddenAsks: [...(volunteerAsks?.hiddenAsks || []), id],
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}, [dispatch, id, jwtToken, volunteerAsks?.hiddenAsks])
|
||||||
|
|
||||||
|
const [meals] = useUserMeals()
|
||||||
|
const needsMeals = get(meals, "needsMeals", false)
|
||||||
|
const canHostCount = get(meals, "canHostCount", 0)
|
||||||
|
const distanceToFestival = get(meals, "distanceToFestival", 0)
|
||||||
|
const mealsComment = get(meals, "mealsComment", "")
|
||||||
|
const needToShow =
|
||||||
|
!needsMeals && canHostCount === 0 && distanceToFestival === 0 && mealsComment === ""
|
||||||
|
|
||||||
|
addAsk(
|
||||||
|
asks,
|
||||||
|
id,
|
||||||
|
volunteerAsks,
|
||||||
|
false,
|
||||||
|
needToShow,
|
||||||
|
<MealsForm afterSubmit={onSubmit}>{answerLaterOnProfile}</MealsForm>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch server-side data here
|
||||||
|
export const fetchFor = [...fetchForMealsForm]
|
@ -6,6 +6,7 @@ import { AskWelcome } from "./AskWelcome"
|
|||||||
import { AskDiscord, fetchFor as fetchForDiscord } from "./AskDiscord"
|
import { AskDiscord, fetchFor as fetchForDiscord } from "./AskDiscord"
|
||||||
import { AskDayWishes, fetchFor as fetchForDayWishes } from "./AskDayWishes"
|
import { AskDayWishes, fetchFor as fetchForDayWishes } from "./AskDayWishes"
|
||||||
import { AskHosting, fetchFor as fetchForHosting } from "./AskHosting"
|
import { AskHosting, fetchFor as fetchForHosting } from "./AskHosting"
|
||||||
|
import { AskMeals, fetchFor as fetchForMeals } from "./AskMeals"
|
||||||
import { AskTeamWishes, fetchFor as fetchForTeamWishes } from "./AskTeamWishes"
|
import { AskTeamWishes, fetchFor as fetchForTeamWishes } from "./AskTeamWishes"
|
||||||
import {
|
import {
|
||||||
AskParticipationDetails,
|
AskParticipationDetails,
|
||||||
@ -24,6 +25,7 @@ const Asks = (): JSX.Element | null => {
|
|||||||
AskTeamWishes(asks, 11)
|
AskTeamWishes(asks, 11)
|
||||||
AskParticipationDetails(asks, 12)
|
AskParticipationDetails(asks, 12)
|
||||||
AskHosting(asks, 20)
|
AskHosting(asks, 20)
|
||||||
|
AskMeals(asks, 22)
|
||||||
|
|
||||||
AskPushNotif(asks, 99)
|
AskPushNotif(asks, 99)
|
||||||
|
|
||||||
@ -61,6 +63,7 @@ export const fetchFor = [
|
|||||||
...fetchForDiscord,
|
...fetchForDiscord,
|
||||||
...fetchForDayWishes,
|
...fetchForDayWishes,
|
||||||
...fetchForHosting,
|
...fetchForHosting,
|
||||||
|
...fetchForMeals,
|
||||||
...fetchForTeamWishes,
|
...fetchForTeamWishes,
|
||||||
...fetchForParticipationDetails,
|
...fetchForParticipationDetails,
|
||||||
]
|
]
|
||||||
|
@ -55,6 +55,8 @@ const RegisterForm = ({ dispatch }: Props): JSX.Element => {
|
|||||||
|
|
||||||
const meetingDateList = useSelector(selectMiscMeetingDateList)
|
const meetingDateList = useSelector(selectMiscMeetingDateList)
|
||||||
|
|
||||||
|
const enableRegistering = false
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const timer = setInterval(() => {
|
const timer = setInterval(() => {
|
||||||
setChangingBackground((changingBackground + 1) % animations.length)
|
setChangingBackground((changingBackground + 1) % animations.length)
|
||||||
@ -234,20 +236,33 @@ const RegisterForm = ({ dispatch }: Props): JSX.Element => {
|
|||||||
</p>
|
</p>
|
||||||
<div className={styles.beneImg}> </div>
|
<div className={styles.beneImg}> </div>
|
||||||
</dd>
|
</dd>
|
||||||
<dt>
|
|
||||||
Si l'expérience vous tente, remplissez le formulaire suivant pour devenir
|
{!enableRegistering && (
|
||||||
bénévole !<br />
|
<dt>
|
||||||
Vous pouvez aussi juste nous rencontrer avant de vous décider à devenir bénévole, on
|
L'inscription est clôturée pour l'édition 2022, mais si l'expérience vous tente,
|
||||||
comprend qu'un saut pareil dans l'inconnu soit difficile.
|
remplissez le formulaire suivant pour devenir bénévole à PeL 2023 !<br />
|
||||||
<br />
|
Dès septembre on se rencontrera sur Paris en petits groupes pour discuter du
|
||||||
Dans les deux cas, venez rencontrer une poignée d'entre nous dans un bar/resto près
|
festival, du bénévolat et surtout faire connaissance :)
|
||||||
de Châtelet ! :) Sur inscription uniquement...
|
<br />
|
||||||
<br />
|
</dt>
|
||||||
</dt>
|
)}
|
||||||
|
|
||||||
|
{enableRegistering && (
|
||||||
|
<dt>
|
||||||
|
Si l'expérience vous tente, remplissez le formulaire suivant pour devenir
|
||||||
|
bénévole !<br />
|
||||||
|
Vous pouvez aussi juste nous rencontrer avant de vous décider à devenir
|
||||||
|
bénévole, on comprend qu'un saut pareil dans l'inconnu soit difficile.
|
||||||
|
<br />
|
||||||
|
Dans les deux cas, venez rencontrer une poignée d'entre nous dans un bar/resto
|
||||||
|
près de Châtelet ! :) Sur inscription uniquement...
|
||||||
|
<br />
|
||||||
|
</dt>
|
||||||
|
)}
|
||||||
</dl>
|
</dl>
|
||||||
)
|
)
|
||||||
|
|
||||||
const potentialVolunteerQuestion = (
|
const potentialVolunteerQuestion = enableRegistering && (
|
||||||
<div className={styles.inputWrapper}>
|
<div className={styles.inputWrapper}>
|
||||||
<div className={styles.leftCol}>
|
<div className={styles.leftCol}>
|
||||||
<div className={styles.multipleChoiceTitle}>Je veux devenir bénévole :</div>
|
<div className={styles.multipleChoiceTitle}>Je veux devenir bénévole :</div>
|
||||||
@ -431,7 +446,7 @@ const RegisterForm = ({ dispatch }: Props): JSX.Element => {
|
|||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
||||||
const meeting = (
|
const meeting = enableRegistering && (
|
||||||
<>
|
<>
|
||||||
<dl className={styles.registerIntro}>
|
<dl className={styles.registerIntro}>
|
||||||
{!potentialVolunteer && <dt>Faisons connaissance !</dt>}
|
{!potentialVolunteer && <dt>Faisons connaissance !</dt>}
|
||||||
@ -535,7 +550,7 @@ const RegisterForm = ({ dispatch }: Props): JSX.Element => {
|
|||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
||||||
const helpBefore = !potentialVolunteer && (
|
const helpBefore = enableRegistering && !potentialVolunteer && (
|
||||||
<>
|
<>
|
||||||
<dl className={styles.registerIntro}>
|
<dl className={styles.registerIntro}>
|
||||||
<dt>Bénévolat en amont du festival</dt>
|
<dt>Bénévolat en amont du festival</dt>
|
||||||
@ -608,7 +623,7 @@ const RegisterForm = ({ dispatch }: Props): JSX.Element => {
|
|||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
||||||
const pelMemberQuestion = !potentialVolunteer && (
|
const pelMemberQuestion = enableRegistering && !potentialVolunteer && (
|
||||||
<>
|
<>
|
||||||
<dl className={styles.registerIntro}>
|
<dl className={styles.registerIntro}>
|
||||||
<dt>Association Paris est Ludique</dt>
|
<dt>Association Paris est Ludique</dt>
|
||||||
@ -784,7 +799,7 @@ const RegisterForm = ({ dispatch }: Props): JSX.Element => {
|
|||||||
|
|
||||||
{(potentialVolunteer || !alreadyVolunteer) && (
|
{(potentialVolunteer || !alreadyVolunteer) && (
|
||||||
<>
|
<>
|
||||||
{commentQuestion}
|
{enableRegistering && commentQuestion}
|
||||||
{cameAsVisitor}
|
{cameAsVisitor}
|
||||||
{meeting}
|
{meeting}
|
||||||
{helpBefore}
|
{helpBefore}
|
||||||
@ -792,6 +807,7 @@ const RegisterForm = ({ dispatch }: Props): JSX.Element => {
|
|||||||
{(potentialVolunteer || pelMember) && (
|
{(potentialVolunteer || pelMember) && (
|
||||||
<>
|
<>
|
||||||
{nameMobileEmail}
|
{nameMobileEmail}
|
||||||
|
{!enableRegistering && commentQuestion}
|
||||||
{howToContact !== "Aucun" && submitButton}
|
{howToContact !== "Aucun" && submitButton}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -3,6 +3,8 @@ import DayWishes from "./DayWishes/DayWishes"
|
|||||||
import DayWishesFormModal from "./DayWishesForm/DayWishesFormModal"
|
import DayWishesFormModal from "./DayWishesForm/DayWishesFormModal"
|
||||||
import Hosting from "./Hosting/Hosting"
|
import Hosting from "./Hosting/Hosting"
|
||||||
import HostingFormModal from "./HostingForm/HostingFormModal"
|
import HostingFormModal from "./HostingForm/HostingFormModal"
|
||||||
|
import Meals from "./Meals/Meals"
|
||||||
|
import MealsFormModal from "./MealsForm/MealsFormModal"
|
||||||
import ParticipationDetails from "./ParticipationDetails/ParticipationDetails"
|
import ParticipationDetails from "./ParticipationDetails/ParticipationDetails"
|
||||||
import ParticipationDetailsFormModal from "./ParticipationDetailsForm/ParticipationDetailsFormModal"
|
import ParticipationDetailsFormModal from "./ParticipationDetailsForm/ParticipationDetailsFormModal"
|
||||||
import TeamWishes from "./TeamWishes/TeamWishes"
|
import TeamWishes from "./TeamWishes/TeamWishes"
|
||||||
@ -11,6 +13,7 @@ import withUserConnected from "../../utils/withUserConnected"
|
|||||||
import ContentTitle from "../ui/Content/ContentTitle"
|
import ContentTitle from "../ui/Content/ContentTitle"
|
||||||
import { fetchFor as fetchForDayWishesForm } from "./DayWishesForm/DayWishesForm"
|
import { fetchFor as fetchForDayWishesForm } from "./DayWishesForm/DayWishesForm"
|
||||||
import { fetchFor as fetchForHostingForm } from "./HostingForm/HostingForm"
|
import { fetchFor as fetchForHostingForm } from "./HostingForm/HostingForm"
|
||||||
|
import { fetchFor as fetchForMealsForm } from "./MealsForm/MealsForm"
|
||||||
import { fetchFor as fetchForParticipationDetailsForm } from "./ParticipationDetailsForm/ParticipationDetailsForm"
|
import { fetchFor as fetchForParticipationDetailsForm } from "./ParticipationDetailsForm/ParticipationDetailsForm"
|
||||||
import { fetchFor as fetchForTeamWishesForm } from "./TeamWishesForm/TeamWishesForm"
|
import { fetchFor as fetchForTeamWishesForm } from "./TeamWishesForm/TeamWishesForm"
|
||||||
import VolunteerTeam from "./VolunteerTeam/VolunteerTeam"
|
import VolunteerTeam from "./VolunteerTeam/VolunteerTeam"
|
||||||
@ -27,6 +30,8 @@ const Board: FC = (): JSX.Element => (
|
|||||||
<VolunteerTeam />
|
<VolunteerTeam />
|
||||||
<Hosting />
|
<Hosting />
|
||||||
<HostingFormModal />
|
<HostingFormModal />
|
||||||
|
<Meals />
|
||||||
|
<MealsFormModal />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -35,6 +40,7 @@ export default memo(withUserConnected(Board))
|
|||||||
export const fetchFor = [
|
export const fetchFor = [
|
||||||
...fetchForDayWishesForm,
|
...fetchForDayWishesForm,
|
||||||
...fetchForHostingForm,
|
...fetchForHostingForm,
|
||||||
|
...fetchForMealsForm,
|
||||||
...fetchForParticipationDetailsForm,
|
...fetchForParticipationDetailsForm,
|
||||||
...fetchForTeamWishesForm,
|
...fetchForTeamWishesForm,
|
||||||
]
|
]
|
||||||
|
65
src/components/VolunteerBoard/Meals/Meals.tsx
Normal file
65
src/components/VolunteerBoard/Meals/Meals.tsx
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { FC, memo, useCallback } from "react"
|
||||||
|
import { find, get } from "lodash"
|
||||||
|
import styles from "./styles.module.scss"
|
||||||
|
import { useUserMeals, mealDays, MealOption } from "../meals.utils"
|
||||||
|
import useAction from "../../../utils/useAction"
|
||||||
|
import { displayModal, MODAL_IDS } from "../../../store/ui"
|
||||||
|
import { useUserDayWishes } from "../daysWishes.utils"
|
||||||
|
|
||||||
|
const Meals: FC = (): JSX.Element | null => {
|
||||||
|
const [userMeals] = useUserMeals()
|
||||||
|
const [userWishes] = useUserDayWishes()
|
||||||
|
const meals = get(userMeals, "meals", [])
|
||||||
|
const dayWishesString = get(userWishes, "dayWishes", [])
|
||||||
|
const execDisplayModal = useAction(displayModal)
|
||||||
|
const onEdit = useCallback(() => execDisplayModal(MODAL_IDS.MEALS), [execDisplayModal])
|
||||||
|
const mealChoices = mealDays.map((meal, i: number) =>
|
||||||
|
find(meal.options, { abbr: meals[i] || "" })
|
||||||
|
) as MealOption[]
|
||||||
|
|
||||||
|
function getMealElement(i: number): JSX.Element {
|
||||||
|
const mealChoice = mealChoices[i]
|
||||||
|
return (
|
||||||
|
<div className={styles.mealsLabel} key={mealDays[i].name}>
|
||||||
|
{mealDays[i].name}, {mealChoice.title}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.meals}>
|
||||||
|
<div className={styles.title}>Mes repas</div>
|
||||||
|
{dayWishesString.includes("S") ? (
|
||||||
|
<>
|
||||||
|
{getMealElement(0)}
|
||||||
|
<div className={styles.mealsLabel} key="SamediSoir">
|
||||||
|
Samedi soir, apéro dînatoire
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div className={styles.mealsLabel} key="Samedi">
|
||||||
|
Non bénévole le samedi
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{dayWishesString.includes("D") ? (
|
||||||
|
<>
|
||||||
|
{getMealElement(1)}
|
||||||
|
{getMealElement(2)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div className={styles.mealsLabel} key="Dimanche">
|
||||||
|
Non bénévole le dimanche
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className={styles.editButton} key="edit">
|
||||||
|
<button type="button" onClick={onEdit}>
|
||||||
|
Modifier
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(Meals)
|
53
src/components/VolunteerBoard/Meals/styles.module.scss
Executable file
53
src/components/VolunteerBoard/Meals/styles.module.scss
Executable file
@ -0,0 +1,53 @@
|
|||||||
|
@import "../../../theme/variables";
|
||||||
|
@import "../../../theme/mixins";
|
||||||
|
|
||||||
|
.title {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mealsLabel {
|
||||||
|
margin-right: 5px;
|
||||||
|
font-style: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meals {
|
||||||
|
@include inner-content-wrapper();
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
padding-right: 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mealsLabel,
|
||||||
|
.commentLine {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
span {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lineEmpty {
|
||||||
|
color: $color-red;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.commentLineTitle {
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.commentLineText {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editButton {
|
||||||
|
@include vertical-center();
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
right: 20px;
|
||||||
|
|
||||||
|
button {
|
||||||
|
color: $color-green;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
152
src/components/VolunteerBoard/MealsForm/MealsForm.tsx
Normal file
152
src/components/VolunteerBoard/MealsForm/MealsForm.tsx
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
import { get } from "lodash"
|
||||||
|
import { FC, memo, ReactNode, useCallback, useEffect, useState } from "react"
|
||||||
|
import classnames from "classnames"
|
||||||
|
import styles from "./styles.module.scss"
|
||||||
|
import { mealDays, MealOption, useUserMeals } from "../meals.utils"
|
||||||
|
import FormButton from "../../Form/FormButton/FormButton"
|
||||||
|
import { fetchVolunteerMealsSetIfNeed } from "../../../store/volunteerMealsSet"
|
||||||
|
import IgnoreButton from "../../Form/IgnoreButton/IgnoreButton"
|
||||||
|
import { useUserDayWishes } from "../daysWishes.utils"
|
||||||
|
import { fetchVolunteerDayWishesSetIfNeed } from "../../../store/volunteerDayWishesSet"
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
children?: ReactNode | undefined
|
||||||
|
afterSubmit?: () => void | undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const MealsForm: FC<Props> = ({ children, afterSubmit }): JSX.Element => {
|
||||||
|
const [saturdayLunchMeal, setSaturdayLunchMeal] = useState("")
|
||||||
|
const [sundayLunchMeal, setSundayLunchMeal] = useState("")
|
||||||
|
const [sundayDinnerMeal, setSundayDinnerMeal] = useState("")
|
||||||
|
const [userMeals, saveMeals] = useUserMeals()
|
||||||
|
const [userWishes] = useUserDayWishes()
|
||||||
|
const meals = get(userMeals, "meals", [])
|
||||||
|
const dayWishesString = get(userWishes, "dayWishes", [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSaturdayLunchMeal(meals[0] || "")
|
||||||
|
setSundayLunchMeal(meals[1] || "")
|
||||||
|
setSundayDinnerMeal(meals[2] || "")
|
||||||
|
}, [meals])
|
||||||
|
|
||||||
|
const onChoiceSubmit = useCallback(() => {
|
||||||
|
saveMeals([saturdayLunchMeal, sundayLunchMeal, sundayDinnerMeal])
|
||||||
|
if (afterSubmit) afterSubmit()
|
||||||
|
}, [saveMeals, saturdayLunchMeal, sundayLunchMeal, sundayDinnerMeal, afterSubmit])
|
||||||
|
|
||||||
|
const getBreakfeastElement = (dayName: string): JSX.Element => (
|
||||||
|
<div key={`${dayName}Matin`}>
|
||||||
|
<b>{dayName} matin</b>, petit dej à 8h avec jus de pomme, multifruit, café, brioches et
|
||||||
|
quatre-quarts, crêpes si bénévoles motivés.
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
const getMealElement = (i: number, meal: string, setMeal: (m: string) => void): JSX.Element => (
|
||||||
|
<div className={classnames(styles.inputWrapper, styles.noBottomMargin)}>
|
||||||
|
<div className={styles.leftCol}>
|
||||||
|
<div className={styles.needsMealsTitle}>
|
||||||
|
<b>{mealDays[i].name}</b>
|
||||||
|
{i === 0 && <>, accompagné d'un délicieux brownie tout chocolat</>}
|
||||||
|
{i === 1 && (
|
||||||
|
<>, accompagné du même brownie. Enfin, un autre que celui de la veille</>
|
||||||
|
)}{" "}
|
||||||
|
:
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.rightCol}>
|
||||||
|
{mealDays[i].options.map((option: MealOption) => (
|
||||||
|
<label className={styles.mealsLabel} key={option.abbr}>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name={`meal${i}`}
|
||||||
|
onChange={() => setMeal(option.abbr)}
|
||||||
|
checked={meal === option.abbr}
|
||||||
|
/>{" "}
|
||||||
|
{option.title}
|
||||||
|
</label>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
const getNotVolunteerElement = (dayName: string): JSX.Element => (
|
||||||
|
<div key={dayName}>
|
||||||
|
<b>{dayName} matin/midi/soir</b>, comme tu n'es pas bénévole ce jour-là, on a rien
|
||||||
|
prévu. Mais{" "}
|
||||||
|
<a href="mailto:benevoles@parisestludique.fr" target="_blank" rel="noreferrer">
|
||||||
|
contacte-nous
|
||||||
|
</a>{" "}
|
||||||
|
si tu veux qu'on te prévoie un dîner.{" "}
|
||||||
|
{dayName === "Dimanche" && (
|
||||||
|
<>
|
||||||
|
Surtout dimanche soir si tu redeviens bénévole pour nous aider à ranger un peu
|
||||||
|
le festival !
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className={styles.title}>Mes repas</div>
|
||||||
|
{dayWishesString.includes("S") ? (
|
||||||
|
<>
|
||||||
|
{getBreakfeastElement("Samedi")}
|
||||||
|
{getMealElement(0, saturdayLunchMeal, setSaturdayLunchMeal)}
|
||||||
|
<div className={styles.mealsLabel} key="SamediSoir">
|
||||||
|
<b>Samedi soir</b>, apéro dînatoire
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
getNotVolunteerElement("Samedi")
|
||||||
|
)}
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
{dayWishesString.includes("D") ? (
|
||||||
|
<>
|
||||||
|
{getBreakfeastElement("Dimanche")}
|
||||||
|
{getMealElement(1, sundayLunchMeal, setSundayLunchMeal)}
|
||||||
|
{getMealElement(2, sundayDinnerMeal, setSundayDinnerMeal)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
getNotVolunteerElement("Dimanche")
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className={classnames(styles.inputWrapper)}>
|
||||||
|
<div>
|
||||||
|
<b>Jeudi, vendredi et lundi</b>, chacun improvise. Peut-être resto à proximité.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.buttonWrapper}>
|
||||||
|
<FormButton onClick={onChoiceSubmit}>Enregistrer</FormButton>
|
||||||
|
{children === undefined && (
|
||||||
|
<>
|
||||||
|
{" "}
|
||||||
|
<FormButton onClick={afterSubmit} type="grey">
|
||||||
|
Annuler
|
||||||
|
</FormButton>{" "}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{children !== undefined && (
|
||||||
|
<>
|
||||||
|
{" "}
|
||||||
|
<IgnoreButton onClick={afterSubmit} text="Ignorer">
|
||||||
|
{children}
|
||||||
|
</IgnoreButton>{" "}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
MealsForm.defaultProps = {
|
||||||
|
children: undefined,
|
||||||
|
afterSubmit: undefined,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(MealsForm)
|
||||||
|
|
||||||
|
// Fetch server-side data here
|
||||||
|
export const fetchFor = [fetchVolunteerMealsSetIfNeed, fetchVolunteerDayWishesSetIfNeed]
|
18
src/components/VolunteerBoard/MealsForm/MealsFormModal.tsx
Normal file
18
src/components/VolunteerBoard/MealsForm/MealsFormModal.tsx
Normal file
@ -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 MealsForm from "./MealsForm"
|
||||||
|
|
||||||
|
const MealsFormModal: FC = (): JSX.Element => {
|
||||||
|
const execHideModal = useAction(hideModal)
|
||||||
|
const afterFormSubmit = useCallback(() => execHideModal(), [execHideModal])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal modalId={MODAL_IDS.MEALS}>
|
||||||
|
<MealsForm afterSubmit={afterFormSubmit} />
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(MealsFormModal)
|
122
src/components/VolunteerBoard/MealsForm/styles.module.scss
Executable file
122
src/components/VolunteerBoard/MealsForm/styles.module.scss
Executable file
@ -0,0 +1,122 @@
|
|||||||
|
@import "../../../theme/variables";
|
||||||
|
@import "../../../theme/mixins";
|
||||||
|
|
||||||
|
.title {
|
||||||
|
padding: 15px 0;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputWrapper {
|
||||||
|
margin: 25px 0;
|
||||||
|
|
||||||
|
@include desktop {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.leftCol {
|
||||||
|
flex: 0 0 320px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rightCol {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.needsMealsTitle {
|
||||||
|
display: inline-block;
|
||||||
|
width: 320px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mealsLabel {
|
||||||
|
text-align: left;
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
width: 220px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.canHostCountTitle {
|
||||||
|
display: inline-block;
|
||||||
|
width: 320px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.canHostCountLabel {
|
||||||
|
text-align: left;
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.distanceToFestivalTitle {
|
||||||
|
display: inline-block;
|
||||||
|
width: 320px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.distanceToFestivalLabel {
|
||||||
|
text-align: left;
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mealsTitle {
|
||||||
|
display: inline-block;
|
||||||
|
width: 320px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mealsList {
|
||||||
|
@include clear-ul-style;
|
||||||
|
|
||||||
|
display: inline-block;
|
||||||
|
width: 204px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mealsItem {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mealsButton {
|
||||||
|
margin: 0;
|
||||||
|
padding: 7px 2px 6px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
width: 90px;
|
||||||
|
text-align: center;
|
||||||
|
color: $color-grey-dark;
|
||||||
|
background-color: $color-grey-light;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: $color-yellow;
|
||||||
|
background-color: $color-black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mealsCommentWrapper {
|
||||||
|
margin: 6px 0 14px;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
@ -4,8 +4,16 @@ import { selectUserJwtToken } from "../../store/auth"
|
|||||||
import { AppState } from "../../store"
|
import { AppState } from "../../store"
|
||||||
import { fetchVolunteerHostingSet } from "../../store/volunteerHostingSet"
|
import { fetchVolunteerHostingSet } from "../../store/volunteerHostingSet"
|
||||||
import useAction from "../../utils/useAction"
|
import useAction from "../../utils/useAction"
|
||||||
|
import { VolunteerHosting } from "../../services/volunteers"
|
||||||
|
|
||||||
export const useUserHosting = (): [any, any] => {
|
type SetFunction = (
|
||||||
|
needsHosting: VolunteerHosting["needsHosting"],
|
||||||
|
canHostCount: VolunteerHosting["canHostCount"],
|
||||||
|
distanceToFestival: VolunteerHosting["distanceToFestival"],
|
||||||
|
hostingComment: VolunteerHosting["hostingComment"]
|
||||||
|
) => void
|
||||||
|
|
||||||
|
export const useUserHosting = (): [VolunteerHosting | undefined, SetFunction] => {
|
||||||
const save = useAction(fetchVolunteerHostingSet)
|
const save = useAction(fetchVolunteerHostingSet)
|
||||||
const jwtToken = useSelector(selectUserJwtToken)
|
const jwtToken = useSelector(selectUserJwtToken)
|
||||||
const userWishes = useSelector(
|
const userWishes = useSelector(
|
||||||
|
69
src/components/VolunteerBoard/meals.utils.ts
Normal file
69
src/components/VolunteerBoard/meals.utils.ts
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import { shallowEqual, useSelector } from "react-redux"
|
||||||
|
import { useCallback } from "react"
|
||||||
|
import { selectUserJwtToken } from "../../store/auth"
|
||||||
|
import { AppState } from "../../store"
|
||||||
|
import { fetchVolunteerMealsSet } from "../../store/volunteerMealsSet"
|
||||||
|
import useAction from "../../utils/useAction"
|
||||||
|
import { VolunteerMeals } from "../../services/volunteers"
|
||||||
|
|
||||||
|
export type MealOption = { abbr: string; title: string }
|
||||||
|
export type MealDay = {
|
||||||
|
name: string
|
||||||
|
options: MealOption[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mealDays: MealDay[] = [
|
||||||
|
{
|
||||||
|
name: "Samedi midi",
|
||||||
|
options: [
|
||||||
|
{ abbr: "V", title: "Sandwich végétarien" },
|
||||||
|
{ abbr: "F", title: "Sandwich fromage" },
|
||||||
|
{ abbr: "P", title: "Sandwich poulet" },
|
||||||
|
{ abbr: "", title: "Pas de repas" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Dimanche midi",
|
||||||
|
options: [
|
||||||
|
{ abbr: "V", title: "Sandwich végétarien" },
|
||||||
|
{ abbr: "F", title: "Sandwich fromage" },
|
||||||
|
{ abbr: "P", title: "Sandwich poulet" },
|
||||||
|
{ abbr: "", title: "Pas de repas" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Dimanche soir",
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
abbr: "V",
|
||||||
|
title: "Lasagnes végétariennes accompagnées de ratatouille et haricots verts",
|
||||||
|
},
|
||||||
|
{ abbr: "P", title: "Aiguillettes de poulet accompagnées de riz thaï" },
|
||||||
|
{ abbr: "", title: "Pas de repas" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
type SetFunction = (meals: VolunteerMeals["meals"]) => void
|
||||||
|
|
||||||
|
export const useUserMeals = (): [VolunteerMeals | undefined, SetFunction] => {
|
||||||
|
const save = useAction(fetchVolunteerMealsSet)
|
||||||
|
const jwtToken = useSelector(selectUserJwtToken)
|
||||||
|
const userWishes = useSelector(
|
||||||
|
(state: AppState) => state.volunteerMealsSet?.entity,
|
||||||
|
shallowEqual
|
||||||
|
)
|
||||||
|
|
||||||
|
const saveWishes = useCallback(
|
||||||
|
(meals) => {
|
||||||
|
if (!userWishes) return
|
||||||
|
save(jwtToken, 0, {
|
||||||
|
id: userWishes.id,
|
||||||
|
meals,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
[userWishes, save, jwtToken]
|
||||||
|
)
|
||||||
|
|
||||||
|
return [userWishes, saveWishes]
|
||||||
|
}
|
@ -71,8 +71,8 @@ async function sendMeetingEmail(
|
|||||||
to: email,
|
to: email,
|
||||||
from: "contact@parisestludique.fr",
|
from: "contact@parisestludique.fr",
|
||||||
subject: "Première rencontre Paris est Ludique",
|
subject: "Première rencontre Paris est Ludique",
|
||||||
text: `Salut ${firstname},\n\nNous allons te contacter prochainement pour trouver ensemble un moyen de se rencontrer.\n\nÀ bientôt :)\nPierre`,
|
text: `Salut ${firstname},\n\nTon inscription est bien prise en compte !\n\nNous te contacterons pour trouver un moyen de se rencontrer.\n\nÀ bientôt :)\nPierre`,
|
||||||
html: `Salut ${firstname},<br /><br />Nous allons te contacter prochainement pour trouver ensemble un moyen de se rencontrer.<br /><br />À bientôt :)<br />Pierre`,
|
html: `Salut ${firstname},<br /><br />Ton inscription est bien prise en compte !<br /><br />Nous te contacterons pour trouver un moyen de se rencontrer.<br /><br />À bientôt :)<br />Pierre`,
|
||||||
}
|
}
|
||||||
await sgMail.send(msg)
|
await sgMail.send(msg)
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
translationVolunteer,
|
translationVolunteer,
|
||||||
VolunteerDayWishes,
|
VolunteerDayWishes,
|
||||||
VolunteerHosting,
|
VolunteerHosting,
|
||||||
|
VolunteerMeals,
|
||||||
VolunteerParticipationDetails,
|
VolunteerParticipationDetails,
|
||||||
VolunteerTeamAssign,
|
VolunteerTeamAssign,
|
||||||
VolunteerKnowledge,
|
VolunteerKnowledge,
|
||||||
@ -362,6 +363,30 @@ export const volunteerHostingSet = expressAccessor.set(async (list, body, id) =>
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const volunteerMealsSet = expressAccessor.set(async (list, body, id) => {
|
||||||
|
const requestedId = +body[0] || id
|
||||||
|
if (requestedId !== id && requestedId !== 0) {
|
||||||
|
throw Error(`On ne peut acceder qu'à ses propres repas`)
|
||||||
|
}
|
||||||
|
const wishes = body[1] as VolunteerMeals
|
||||||
|
const volunteer: Volunteer | undefined = list.find((v) => v.id === requestedId)
|
||||||
|
if (!volunteer) {
|
||||||
|
throw Error(`Il n'y a aucun bénévole avec cet identifiant ${requestedId}`)
|
||||||
|
}
|
||||||
|
const newVolunteer = cloneDeep(volunteer)
|
||||||
|
|
||||||
|
if (wishes.meals !== undefined) {
|
||||||
|
newVolunteer.meals = wishes.meals
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
toDatabase: newVolunteer,
|
||||||
|
toCaller: {
|
||||||
|
id: newVolunteer.id,
|
||||||
|
meals: newVolunteer.meals,
|
||||||
|
} as VolunteerMeals,
|
||||||
|
}
|
||||||
|
})
|
||||||
export const volunteerParticipationDetailsSet = expressAccessor.set(async (list, body, id) => {
|
export const volunteerParticipationDetailsSet = expressAccessor.set(async (list, body, id) => {
|
||||||
const requestedId = +body[0] || id
|
const requestedId = +body[0] || id
|
||||||
if (requestedId !== id && requestedId !== 0) {
|
if (requestedId !== id && requestedId !== 0) {
|
||||||
|
@ -27,9 +27,9 @@ import {
|
|||||||
volunteerDayWishesSet,
|
volunteerDayWishesSet,
|
||||||
volunteerForgot,
|
volunteerForgot,
|
||||||
volunteerHostingSet,
|
volunteerHostingSet,
|
||||||
|
volunteerMealsSet,
|
||||||
volunteerDiscordId,
|
volunteerDiscordId,
|
||||||
volunteerLogin,
|
volunteerLogin,
|
||||||
volunteerPartialAdd,
|
|
||||||
volunteerParticipationDetailsSet,
|
volunteerParticipationDetailsSet,
|
||||||
volunteerSet,
|
volunteerSet,
|
||||||
volunteerTeamWishesSet,
|
volunteerTeamWishesSet,
|
||||||
@ -94,7 +94,7 @@ app.get("/MiscMeetingDateListGet", miscMeetingDateListGet)
|
|||||||
app.get("/WishListGet", wishListGet)
|
app.get("/WishListGet", wishListGet)
|
||||||
app.post("/WishAdd", wishAdd)
|
app.post("/WishAdd", wishAdd)
|
||||||
app.post("/PostulantAdd", postulantAdd)
|
app.post("/PostulantAdd", postulantAdd)
|
||||||
app.post("/VolunteerPartialAdd", volunteerPartialAdd)
|
// Disabling registration app.post("/VolunteerPartialAdd", volunteerPartialAdd)
|
||||||
app.post("/VolunteerLogin", volunteerLogin)
|
app.post("/VolunteerLogin", volunteerLogin)
|
||||||
app.post("/VolunteerForgot", volunteerForgot)
|
app.post("/VolunteerForgot", volunteerForgot)
|
||||||
app.get("/VolunteerListGet", secure as RequestHandler, volunteerListGet)
|
app.get("/VolunteerListGet", secure as RequestHandler, volunteerListGet)
|
||||||
@ -113,6 +113,7 @@ app.post(
|
|||||||
)
|
)
|
||||||
app.post("/VolunteerDayWishesSet", secure as RequestHandler, volunteerDayWishesSet)
|
app.post("/VolunteerDayWishesSet", secure as RequestHandler, volunteerDayWishesSet)
|
||||||
app.post("/VolunteerHostingSet", secure as RequestHandler, volunteerHostingSet)
|
app.post("/VolunteerHostingSet", secure as RequestHandler, volunteerHostingSet)
|
||||||
|
app.post("/VolunteerMealsSet", secure as RequestHandler, volunteerMealsSet)
|
||||||
app.post("/VolunteerTeamWishesSet", secure as RequestHandler, volunteerTeamWishesSet)
|
app.post("/VolunteerTeamWishesSet", secure as RequestHandler, volunteerTeamWishesSet)
|
||||||
app.post("/VolunteerTeamAssignSet", secure as RequestHandler, volunteerTeamAssignSet)
|
app.post("/VolunteerTeamAssignSet", secure as RequestHandler, volunteerTeamAssignSet)
|
||||||
|
|
||||||
|
@ -67,6 +67,8 @@ export class Volunteer implements VolunteerPartial {
|
|||||||
distanceToFestival = 0
|
distanceToFestival = 0
|
||||||
|
|
||||||
hostingComment = ""
|
hostingComment = ""
|
||||||
|
|
||||||
|
meals: string[] = []
|
||||||
}
|
}
|
||||||
|
|
||||||
export const translationVolunteer: { [k in keyof Volunteer]: string } = {
|
export const translationVolunteer: { [k in keyof Volunteer]: string } = {
|
||||||
@ -104,6 +106,7 @@ export const translationVolunteer: { [k in keyof Volunteer]: string } = {
|
|||||||
canHostCount: "nombreHébergés",
|
canHostCount: "nombreHébergés",
|
||||||
distanceToFestival: "distanceAuFestival",
|
distanceToFestival: "distanceAuFestival",
|
||||||
hostingComment: "commentaireHébergement",
|
hostingComment: "commentaireHébergement",
|
||||||
|
meals: "repas",
|
||||||
}
|
}
|
||||||
|
|
||||||
export class VolunteerPartial {
|
export class VolunteerPartial {
|
||||||
@ -153,6 +156,7 @@ export const volunteerExample: Volunteer = {
|
|||||||
canHostCount: 0,
|
canHostCount: 0,
|
||||||
distanceToFestival: 0,
|
distanceToFestival: 0,
|
||||||
hostingComment: "",
|
hostingComment: "",
|
||||||
|
meals: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
export const emailRegexp =
|
export const emailRegexp =
|
||||||
@ -205,6 +209,11 @@ export interface VolunteerHosting {
|
|||||||
hostingComment: Volunteer["hostingComment"]
|
hostingComment: Volunteer["hostingComment"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface VolunteerMeals {
|
||||||
|
id: Volunteer["id"]
|
||||||
|
meals: Volunteer["meals"]
|
||||||
|
}
|
||||||
|
|
||||||
export interface VolunteerParticipationDetails {
|
export interface VolunteerParticipationDetails {
|
||||||
id: Volunteer["id"]
|
id: Volunteer["id"]
|
||||||
tshirtSize: Volunteer["tshirtSize"]
|
tshirtSize: Volunteer["tshirtSize"]
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
VolunteerWithoutId,
|
VolunteerWithoutId,
|
||||||
VolunteerDiscordId,
|
VolunteerDiscordId,
|
||||||
VolunteerKnowledge,
|
VolunteerKnowledge,
|
||||||
|
VolunteerMeals,
|
||||||
} from "./volunteers"
|
} from "./volunteers"
|
||||||
|
|
||||||
const serviceAccessors = new ServiceAccessors<VolunteerWithoutId, Volunteer>(elementName)
|
const serviceAccessors = new ServiceAccessors<VolunteerWithoutId, Volunteer>(elementName)
|
||||||
@ -42,6 +43,9 @@ export const volunteerDayWishesSet =
|
|||||||
export const volunteerHostingSet =
|
export const volunteerHostingSet =
|
||||||
serviceAccessors.securedCustomPost<[number, Partial<VolunteerHosting>]>("HostingSet")
|
serviceAccessors.securedCustomPost<[number, Partial<VolunteerHosting>]>("HostingSet")
|
||||||
|
|
||||||
|
export const volunteerMealsSet =
|
||||||
|
serviceAccessors.securedCustomPost<[number, Partial<VolunteerMeals>]>("MealsSet")
|
||||||
|
|
||||||
export const volunteerParticipationDetailsSet =
|
export const volunteerParticipationDetailsSet =
|
||||||
serviceAccessors.securedCustomPost<[number, Partial<VolunteerParticipationDetails>]>(
|
serviceAccessors.securedCustomPost<[number, Partial<VolunteerParticipationDetails>]>(
|
||||||
"ParticipationDetailsSet"
|
"ParticipationDetailsSet"
|
||||||
|
@ -17,6 +17,7 @@ import volunteerDayWishesSet from "./volunteerDayWishesSet"
|
|||||||
import volunteerDiscordId from "./volunteerDiscordId"
|
import volunteerDiscordId from "./volunteerDiscordId"
|
||||||
import volunteerForgot from "./volunteerForgot"
|
import volunteerForgot from "./volunteerForgot"
|
||||||
import volunteerHostingSet from "./volunteerHostingSet"
|
import volunteerHostingSet from "./volunteerHostingSet"
|
||||||
|
import volunteerMealsSet from "./volunteerMealsSet"
|
||||||
import volunteerList from "./volunteerList"
|
import volunteerList from "./volunteerList"
|
||||||
import volunteerLogin from "./volunteerLogin"
|
import volunteerLogin from "./volunteerLogin"
|
||||||
import volunteerKnowledgeSet from "./volunteerKnowledgeSet"
|
import volunteerKnowledgeSet from "./volunteerKnowledgeSet"
|
||||||
@ -46,6 +47,7 @@ export default (history: History) => ({
|
|||||||
volunteerDiscordId,
|
volunteerDiscordId,
|
||||||
volunteerForgot,
|
volunteerForgot,
|
||||||
volunteerHostingSet,
|
volunteerHostingSet,
|
||||||
|
volunteerMealsSet,
|
||||||
volunteerList,
|
volunteerList,
|
||||||
volunteerLogin,
|
volunteerLogin,
|
||||||
volunteerKnowledgeSet,
|
volunteerKnowledgeSet,
|
||||||
|
@ -29,6 +29,7 @@ export const selectActiveModalId = createSelector(selectUiData, (ui) => ui.modal
|
|||||||
export const MODAL_IDS = {
|
export const MODAL_IDS = {
|
||||||
DAYWISHES: "DAYWISHES",
|
DAYWISHES: "DAYWISHES",
|
||||||
HOSTING: "HOSTING",
|
HOSTING: "HOSTING",
|
||||||
|
MEALS: "MEALS",
|
||||||
PARTICIPATIONDETAILS: "PARTICIPATIONDETAILS",
|
PARTICIPATIONDETAILS: "PARTICIPATIONDETAILS",
|
||||||
TEAMWISHES: "TEAMWISHES",
|
TEAMWISHES: "TEAMWISHES",
|
||||||
}
|
}
|
||||||
|
60
src/store/volunteerMealsSet.ts
Normal file
60
src/store/volunteerMealsSet.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import { PayloadAction, createSlice } from "@reduxjs/toolkit"
|
||||||
|
|
||||||
|
import { StateRequest, toastError, elementFetch } from "./utils"
|
||||||
|
import { VolunteerMeals } from "../services/volunteers"
|
||||||
|
import { AppThunk, AppState } from "."
|
||||||
|
import { volunteerMealsSet } from "../services/volunteersAccessors"
|
||||||
|
|
||||||
|
type StateVolunteerMealsSet = { entity?: VolunteerMeals } & StateRequest
|
||||||
|
|
||||||
|
export const initialState: StateVolunteerMealsSet = {
|
||||||
|
readyStatus: "idle",
|
||||||
|
}
|
||||||
|
|
||||||
|
const volunteerMealsSetSlice = createSlice({
|
||||||
|
name: "volunteerMealsSet",
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
getRequesting: (_) => ({
|
||||||
|
readyStatus: "request",
|
||||||
|
}),
|
||||||
|
getSuccess: (_, { payload }: PayloadAction<VolunteerMeals>) => ({
|
||||||
|
readyStatus: "success",
|
||||||
|
entity: payload,
|
||||||
|
}),
|
||||||
|
getFailure: (_, { payload }: PayloadAction<string>) => ({
|
||||||
|
readyStatus: "failure",
|
||||||
|
error: payload,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export default volunteerMealsSetSlice.reducer
|
||||||
|
export const { getRequesting, getSuccess, getFailure } = volunteerMealsSetSlice.actions
|
||||||
|
|
||||||
|
export const fetchVolunteerMealsSet = elementFetch(
|
||||||
|
volunteerMealsSet,
|
||||||
|
getRequesting,
|
||||||
|
getSuccess,
|
||||||
|
getFailure,
|
||||||
|
(error: Error) =>
|
||||||
|
toastError(`Erreur lors du chargement des choix de jours de présence: ${error.message}`)
|
||||||
|
)
|
||||||
|
|
||||||
|
const shouldFetchVolunteerMealsSet = (state: AppState, id: number) =>
|
||||||
|
state.volunteerMealsSet?.readyStatus !== "success" ||
|
||||||
|
(state.volunteerMealsSet?.entity && state.volunteerMealsSet?.entity?.id !== id)
|
||||||
|
|
||||||
|
export const fetchVolunteerMealsSetIfNeed =
|
||||||
|
(id = 0, wishes: Partial<VolunteerMeals> = {}): AppThunk =>
|
||||||
|
(dispatch, getState) => {
|
||||||
|
let jwt = ""
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
;({ jwt, id } = getState().auth)
|
||||||
|
}
|
||||||
|
if (shouldFetchVolunteerMealsSet(getState(), id))
|
||||||
|
return dispatch(fetchVolunteerMealsSet(jwt, id, wishes))
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user