Update meals, tee-shirt and hosting forms

This commit is contained in:
pikiou 2023-05-22 08:26:15 +02:00
parent d58c4ed3ea
commit 459ef4a85d
21 changed files with 991 additions and 384 deletions

View File

@ -19,12 +19,8 @@ export function AskHosting(asks: JSX.Element[], id: number): void {
}, [dispatch, id, jwtToken, volunteerAsks?.hiddenAsks])
const [hosting] = useUserHosting()
const needsHosting = get(hosting, "needsHosting", false)
const canHostCount = get(hosting, "canHostCount", 0)
const distanceToFestival = get(hosting, "distanceToFestival", 0)
const hostingComment = get(hosting, "hostingComment", "")
const needToShow =
!needsHosting && canHostCount === 0 && distanceToFestival === 0 && hostingComment === ""
const hostingType = get(hosting, "hostingType", false)
const needToShow = hostingType === ""
addAsk(
asks,

View File

@ -1,7 +1,7 @@
import { get } from "lodash"
import { useCallback } from "react"
import { fetchVolunteerAsksSet } from "../../store/volunteerAsksSet"
import { useAskTools, addAsk, answerLaterOnProfile } from "./utils"
import { useAskTools, addAsk, answerLaterOnProfileBefore } from "./utils"
import MealsForm, { fetchFor as fetchForMealsForm } from "../VolunteerBoard/MealsForm/MealsForm"
import { useUserMeals } from "../VolunteerBoard/meals.utils"
@ -16,13 +16,9 @@ export function AskMeals(asks: JSX.Element[], id: number): void {
)
}, [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 === ""
const [userMeals] = useUserMeals()
const meals = get(userMeals, "meals", [])
const needToShow = meals.length === 0
addAsk(
asks,
@ -30,7 +26,9 @@ export function AskMeals(asks: JSX.Element[], id: number): void {
volunteerAsks,
false,
needToShow,
<MealsForm afterSubmit={onSubmit}>{answerLaterOnProfile}</MealsForm>
<MealsForm afterSubmit={onSubmit}>
{answerLaterOnProfileBefore("31 mai à minuit pour commander les repas !")}
</MealsForm>
)
}

View File

@ -7,14 +7,14 @@ import { AskWelcome } from "./AskWelcome"
// import { AskRetex, fetchFor as fetchForRetex } from "./AskRetex"
import { AskDiscord, fetchFor as fetchForDiscord } from "./AskDiscord"
import { AskDayWishes, fetchFor as fetchForDayWishes } from "./AskDayWishes"
// import { AskHosting, fetchFor as fetchForHosting } from "./AskHosting"
// import { AskMeals, fetchFor as fetchForMeals } from "./AskMeals"
import { AskHosting, fetchFor as fetchForHosting } from "./AskHosting"
import { AskMeals, fetchFor as fetchForMeals } from "./AskMeals"
// import { AskPersonalInfo, fetchFor as fetchForPersonalInfo } from "./AskPersonalInfo"
import { AskTeamWishes, fetchFor as fetchForTeamWishes } from "./AskTeamWishes"
// import {
// AskParticipationDetails,
// fetchFor as fetchForParticipationDetails,
// } from "./AskParticipationDetails"
import {
AskParticipationDetails,
fetchFor as fetchForParticipationDetails,
} from "./AskParticipationDetails"
// import { AskPushNotif } from "./AskPushNotif"
const Asks = (): JSX.Element | null => {
@ -28,10 +28,10 @@ const Asks = (): JSX.Element | null => {
AskDayWishes(asks, 10)
AskTeamWishes(asks, 11)
// AskParticipationDetails(asks, 12)
// AskPersonalInfo(asks, 15)
// AskHosting(asks, 20)
// AskMeals(asks, 22)
AskMeals(asks, 15)
// AskPersonalInfo(asks, 16)
AskHosting(asks, 20)
AskParticipationDetails(asks, 22)
// AskPushNotif(asks, 99)
@ -42,6 +42,9 @@ const Asks = (): JSX.Element | null => {
<div className={styles.notificationsContent}>
<div className={styles.formLine}>
<label>
Si tu veux changer la réponse à l'une des questions posées ici, va
dans <a href="/profil">Mon profil</a> :)
<br />
Tu as fait le tour des dernières infos ou questions importantes,
merci ! :)
<br />
@ -70,9 +73,9 @@ export const fetchFor = [
// ...fetchForRetex,
...fetchForDiscord,
...fetchForDayWishes,
// ...fetchForHosting,
// ...fetchForMeals,
...fetchForHosting,
...fetchForMeals,
...fetchForTeamWishes,
// ...fetchForParticipationDetails,
...fetchForParticipationDetails,
// ...fetchForPersonalInfo,
]

View File

@ -61,3 +61,12 @@ export const answerLaterOnProfile = (
Tu pourras y répondre plus tard sur la page <a href="/profil">Mon profil</a>.
</>
)
export function answerLaterOnProfileBefore(textDate: string): JSX.Element {
return (
<>
Tu pourras y répondre plus tard sur la page <a href="/profil">Mon profil</a>.<br />
Il nous fait une réponse avant le {textDate}
</>
)
}

View File

@ -1,21 +1,21 @@
import { FC, memo } from "react"
import DayWishes from "./DayWishes/DayWishes"
import DayWishesFormModal from "./DayWishesForm/DayWishesFormModal"
// import Hosting from "./Hosting/Hosting"
// import HostingFormModal from "./HostingForm/HostingFormModal"
// import Meals from "./Meals/Meals"
// import MealsFormModal from "./MealsForm/MealsFormModal"
// import ParticipationDetails from "./ParticipationDetails/ParticipationDetails"
// import ParticipationDetailsFormModal from "./ParticipationDetailsForm/ParticipationDetailsFormModal"
import Hosting from "./Hosting/Hosting"
import HostingFormModal from "./HostingForm/HostingFormModal"
import Meals from "./Meals/Meals"
import MealsFormModal from "./MealsForm/MealsFormModal"
import ParticipationDetails from "./ParticipationDetails/ParticipationDetails"
import ParticipationDetailsFormModal from "./ParticipationDetailsForm/ParticipationDetailsFormModal"
import TeamWishes from "./TeamWishes/TeamWishes"
import TeamWishesFormModal from "./TeamWishesForm/TeamWishesFormModal"
import VolunteerTeam from "./VolunteerTeam/VolunteerTeam"
import withUserConnected from "../../utils/withUserConnected"
import ContentTitle from "../ui/Content/ContentTitle"
import { fetchFor as fetchForDayWishesForm } from "./DayWishesForm/DayWishesForm"
// import { fetchFor as fetchForHostingForm } from "./HostingForm/HostingForm"
// import { fetchFor as fetchForMealsForm } from "./MealsForm/MealsForm"
// import { fetchFor as fetchForParticipationDetailsForm } from "./ParticipationDetailsForm/ParticipationDetailsForm"
import { fetchFor as fetchForHostingForm } from "./HostingForm/HostingForm"
import { fetchFor as fetchForMealsForm } from "./MealsForm/MealsForm"
import { fetchFor as fetchForParticipationDetailsForm } from "./ParticipationDetailsForm/ParticipationDetailsForm"
import { fetchFor as fetchForTeamWishesForm } from "./TeamWishesForm/TeamWishesForm"
import { fetchFor as fetchForPersonalInfoForm } from "./PersonalInfoForm/PersonalInfoForm"
import PersonalInfo from "./PersonalInfo/PersonalInfo"
@ -42,15 +42,15 @@ const Board: FC = (): JSX.Element => (
{retex && <RetexFormModal />} */}
<DayWishes />
<DayWishesFormModal />
{/* <ParticipationDetails />
<ParticipationDetailsFormModal /> */}
<ParticipationDetails />
<ParticipationDetailsFormModal />
<Hosting />
<HostingFormModal />
<Meals />
<MealsFormModal />
<TeamWishes />
<TeamWishesFormModal />
<VolunteerTeam />
{/* <Hosting />
<HostingFormModal />
<Meals />
<MealsFormModal /> */}
</>
)
// )
@ -63,8 +63,8 @@ export const fetchFor = [
// ...fetchForRetexForm,
// ...fetchForBrunchForm,
...fetchForDayWishesForm,
// ...fetchForHostingForm,
// ...fetchForMealsForm,
// ...fetchForParticipationDetailsForm,
...fetchForHostingForm,
...fetchForMealsForm,
...fetchForParticipationDetailsForm,
...fetchForTeamWishesForm,
]

View File

@ -7,48 +7,31 @@ import { displayModal, MODAL_IDS } from "../../../store/ui"
const Hosting: FC = (): JSX.Element | null => {
const [userWishes] = useUserHosting()
const needsHosting = get(userWishes, "needsHosting", false)
const hostingType = get(userWishes, "hostingType", "")
const canHostCount = get(userWishes, "canHostCount", 0)
const distanceToFestival = get(userWishes, "distanceToFestival", 0)
const comment = get(userWishes, "hostingComment", "")
const execDisplayModal = useAction(displayModal)
const onEdit = useCallback(() => execDisplayModal(MODAL_IDS.HOSTING), [execDisplayModal])
return (
<div className={styles.hosting}>
<div className={styles.title}>Mon hébergement</div>
{!needsHosting && (
{(hostingType === "" || hostingType === "neither") && (
<div className={styles.hostingLabel}>
Je n'ai pas besoin d'un hébergement proche du festival
Je ne peux héberger personnes que ça arrangerait.
</div>
)}
{needsHosting && (
{hostingType === "need" && (
<div className={styles.hostingLabel}>
J'ai <b>besoin</b> d'un hébergement proche du festival
J'ai précisé mon <b>besoin</b> d'un hébergement par un bénévole proche du
festival
</div>
)}
{canHostCount === 0 && distanceToFestival === 0 && (
{hostingType === "can" && (
<div className={styles.hostingLabel}>
Je ne peux héberger personnes de manière utile.
</div>
)}
{canHostCount > 0 && (
<div className={styles.hostingLabel}>
Je peux héberger <b>{canHostCount} personnes</b> !
</div>
)}
{distanceToFestival > 0 && (
<div className={styles.hostingLabel}>
Je suis à <b>{distanceToFestival} minutes</b> du festival
Je peux héberger <b>{canHostCount} bénévole(s)</b> !
</div>
)}
{comment && (
<div className={styles.commentLine}>
<span className={styles.commentLineTitle}>Mon commentaire :</span>
<span className={styles.commentLineText}>{comment}</span>
</div>
)}
<div className={styles.editButton}>
<button type="button" onClick={onEdit}>
Modifier

View File

@ -1,9 +1,19 @@
import { FC, memo, ReactNode, useCallback, useEffect, useRef, useState } from "react"
import classnames from "classnames"
import get from "lodash/get"
import includes from "lodash/includes"
import without from "lodash/without"
import set from "lodash/set"
import styles from "./styles.module.scss"
import { useUserHosting } from "../hosting.utils"
import {
useUserHosting,
nightList,
NightOption,
nightChoiceSelectionDefaultState,
NightChoices,
bedList,
hostLocations,
} from "../hosting.utils"
import FormButton from "../../Form/FormButton/FormButton"
import { fetchVolunteerHostingSetIfNeed } from "../../../store/volunteerHostingSet"
import IgnoreButton from "../../Form/IgnoreButton/IgnoreButton"
@ -14,91 +24,522 @@ type Props = {
}
const HostingForm: FC<Props> = ({ children, afterSubmit }): JSX.Element => {
const [needsHosting, setNeedsHosting] = useState(false)
const [hostingType, setHostingType] = useState("")
const canHostCountRef = useRef<HTMLInputElement | null>(null)
const distanceRef = useRef<HTMLInputElement | null>(null)
const commentRef = useRef<HTMLTextAreaElement | null>(null)
const [nights, setNights] = useState(nightChoiceSelectionDefaultState)
const cohostVolunteerRef = useRef<HTMLInputElement | null>(null)
const petAllergiesRef = useRef<HTMLInputElement | null>(null)
const [backProblems, setBackProblems] = useState(false)
const [bedType, setBedType] = useState<string[]>([])
const [isolatedBed, setIsolatedBed] = useState(false)
const bedConfigurationRef = useRef<HTMLTextAreaElement | null>(null)
const hostAddressRef = useRef<HTMLTextAreaElement | null>(null)
const transportTypeRef = useRef<HTMLInputElement | null>(null)
const [festivalProximity, setFestivalProximity] = useState("")
const distanceToFestivalRef = useRef<HTMLInputElement | null>(null)
const [hostingAbsoluteNeed, setHostingAbsoluteNeed] = useState(false)
const hostingNeedReasonRef = useRef<HTMLTextAreaElement | null>(null)
const [userWishes, saveWishes] = useUserHosting()
const onNeedsHostingChange = (e: React.ChangeEvent<HTMLInputElement>) =>
setNeedsHosting(e.target.checked)
useEffect(() => {
if (!userWishes) return
setNeedsHosting(get(userWishes, "needsHosting", false))
setHostingType(get(userWishes, "hostingType", ""))
const hostingNights = get(userWishes, "hostingNights", "") as string
const newNights = hostingNights.split("").reduce(
(acc: NightChoices, abbr: string) => ({
...acc,
[abbr]: true,
}),
{} as NightChoices
)
setNights(newNights)
setBedType(get(userWishes, "bedType", []))
setBackProblems(get(userWishes, "backProblems", false))
set(canHostCountRef, "current.value", `${get(userWishes, "canHostCount", 0)}`)
set(distanceRef, "current.value", `${get(userWishes, "distanceToFestival", 0)}`)
set(commentRef, "current.value", get(userWishes, "hostingComment", ""))
}, [commentRef, userWishes])
set(cohostVolunteerRef, "current.value", get(userWishes, "cohostVolunteer", ""))
set(petAllergiesRef, "current.value", get(userWishes, "petAllergies", ""))
set(bedConfigurationRef, "current.value", get(userWishes, "bedConfiguration", ""))
set(hostAddressRef, "current.value", get(userWishes, "hostAddress", ""))
set(transportTypeRef, "current.value", get(userWishes, "transportType", ""))
setFestivalProximity(get(userWishes, "festivalProximity", ""))
set(distanceToFestivalRef, "current.value", get(userWishes, "distanceToFestival", ""))
set(hostingNeedReasonRef, "current.value", get(userWishes, "hostingNeedReason", ""))
setHostingAbsoluteNeed(get(userWishes, "hostingAbsoluteNeed", false))
}, [userWishes])
const onHostingTypeChange = useCallback((newHostingType: string) => {
setHostingType(newHostingType)
}, [])
const onBackProblemsChange = useCallback((newBackProblems: boolean) => {
setBackProblems(newBackProblems)
}, [])
const onNightClick = useCallback(
(changes: NightChoices) => {
setNights({
...nights,
...changes,
})
},
[nights, setNights]
)
function isNightUnselected(abbr: string): boolean {
return !nights[abbr] && !nights[abbr.toLowerCase()]
}
function isNightSelected(abbr: string): boolean {
return nights[abbr]
}
const onBedTypeChange = useCallback(
(bed: string) => {
if (includes(bedType, bed)) {
setBedType(without(bedType, bed))
} else {
setBedType([...bedType, bed])
}
},
[bedType]
)
const onIsolatedBedChange = useCallback((newIsolatedBed: boolean) => {
setIsolatedBed(newIsolatedBed)
}, [])
const onHostingAbsoluteNeedChange = useCallback((newHostingAbsoluteNeed: boolean) => {
setHostingAbsoluteNeed(newHostingAbsoluteNeed)
}, [])
const onFestivalProximityChange = useCallback((newFestivalProximity: string) => {
setFestivalProximity(newFestivalProximity)
}, [])
const onChoiceSubmit = useCallback(() => {
const canHostCount = +get(canHostCountRef, "current.value", "0")
const distanceToFestival = +get(distanceRef, "current.value", "0")
const hostingComment = get(commentRef, "current.value", "")
saveWishes(needsHosting, canHostCount, distanceToFestival, hostingComment)
const cohostVolunteer = get(cohostVolunteerRef, "current.value", "")
const bedConfiguration = get(bedConfigurationRef, "current.value", "")
const hostingNights = nightList.reduce((res, { abbr }) => {
if (nights[abbr]) {
res += abbr
}
if (nights[abbr.toLowerCase()]) {
res += abbr.toLowerCase()
}
return res
}, "")
const hostAddress = get(hostAddressRef, "current.value", "")
const petAllergies = get(petAllergiesRef, "current.value", "")
const transportType = get(transportTypeRef, "current.value", "")
const distanceToFestival = get(distanceToFestivalRef, "current.value", "")
const hostingNeedReason = get(hostingNeedReasonRef, "current.value", "")
saveWishes(
hostingType,
canHostCount,
cohostVolunteer,
backProblems,
hostingNights,
bedType,
isolatedBed,
bedConfiguration,
hostAddress,
petAllergies,
transportType,
festivalProximity,
distanceToFestival,
hostingNeedReason,
hostingAbsoluteNeed
)
if (afterSubmit) afterSubmit()
}, [needsHosting, commentRef, saveWishes, afterSubmit])
}, [
saveWishes,
hostingType,
backProblems,
bedType,
isolatedBed,
festivalProximity,
hostingAbsoluteNeed,
afterSubmit,
nights,
])
return (
<div>
<div className={styles.title}>Mon hébergement</div>
<div className={classnames(styles.inputWrapper, styles.noBottomMargin)}>
const getNightElement = (option: NightOption, maybeText: string): JSX.Element => (
<div className={classnames(styles.inputWrapper, styles.noBottomMargin)} key={option.abbr}>
<div className={styles.leftCol}>
<div className={styles.needsHostingTitle}>
Cela t'arrangerait-il d'avoir un hébergement proche du festival ?
</div>
<div className={styles.nightTitle}>{option.title}</div>
</div>
<div className={styles.rightCol}>
<label className={styles.needsHostingLabel}>
<label className={styles.nightLabel} key={`no${option.abbr}`}>
<input
type="checkbox"
value="oui"
name="needsHosting"
onChange={onNeedsHostingChange}
checked={needsHosting}
type="radio"
name={`no${option.abbr}`}
onChange={() =>
onNightClick({
[option.abbr]: false,
[option.abbr.toLowerCase()]: false,
})
}
checked={isNightUnselected(option.abbr)}
/>{" "}
Non
</label>
<label className={styles.nightLabelLong} key={option.abbr.toLowerCase()}>
<input
type="radio"
name={option.abbr.toLowerCase()}
onChange={() =>
onNightClick({
[option.abbr]: false,
[option.abbr.toLowerCase()]: true,
})
}
checked={isNightSelected(option.abbr.toLowerCase())}
/>
{maybeText}
</label>
<label className={styles.nightLabel} key={option.abbr}>
<input
type="radio"
name={option.abbr}
onChange={() =>
onNightClick({
[option.abbr]: true,
[option.abbr.toLowerCase()]: false,
})
}
checked={isNightSelected(option.abbr)}
/>{" "}
Oui
</label>
</div>
</div>
{needsHosting && (
<div className={classnames(styles.inputWrapper, styles.noBottomMargin)}>
)
return (
<div>
Il nous serait utile de savoir à quelle temps de transport tu te trouves
pour privilégier les bénévoles qui viennent de province à ceux qui viennent
de l'autre bout de Paris.
</div>
</div>
<div className={styles.title}>Mon hébergement</div>
<div
className={classnames(
styles.inputWrapper,
styles.noBottomMargin,
styles.hostingTypeForm
)}
<div className={styles.inputWrapper}>
>
<div className={styles.rightCol}>
<label className={styles.hostingTypeLabel}>
<input
type="radio"
name="can"
onChange={() => onHostingTypeChange("can")}
checked={hostingType === "can"}
/>{" "}
Je peux héberger au moins un bénévole
</label>
<label className={styles.hostingTypeLabel}>
<input
type="radio"
name="need"
onChange={() => onHostingTypeChange("need")}
checked={hostingType === "need"}
/>{" "}
J'aurais besoin d'un hébergement de la part d'un bénévole proche du festival
</label>
<label className={styles.hostingTypeLabel}>
<input
type="radio"
name="neither"
onChange={() => onHostingTypeChange("")}
checked={hostingType === ""}
/>{" "}
Aucun des deux
</label>
</div>
</div>
<div
className={classnames([styles.inputWrapper, hostingType !== "can" && styles.hide])}
>
<div className={styles.leftCol}>
<div className={styles.canHostCountTitle}>
Combien de bénévoles peux-tu héberger confortablement ?
Combien de bénévoles peux-tu héberger ?
</div>
</div>
<div className={styles.rightCol}>
<input className={styles.canHostCountLabel} type="text" ref={canHostCountRef} />
</div>
</div>
<div className={styles.inputWrapper}>
<div
className={classnames([styles.inputWrapper, hostingType !== "can" && styles.hide])}
>
<div className={styles.leftCol}>
<div className={styles.petAllergiesTitle}>
As-tu un animal de compagnie ? (Possibles allergies ou phobies) ?
</div>
</div>
<div className={styles.rightCol}>
<input className={styles.petAllergiesLabel} type="text" ref={petAllergiesRef} />
</div>
</div>
<div
className={classnames([
styles.inputWrapper,
styles.noBottomMargin,
hostingType !== "need" && styles.hide,
])}
>
<div className={styles.leftCol}>
<div className={styles.backProblemsTitle}>As-tu des problèmes de dos ?</div>
</div>
<div className={styles.rightCol}>
<label className={styles.backProblemsLabel}>
<input
type="radio"
name="backProblems"
onChange={() => onBackProblemsChange(true)}
checked={backProblems}
/>{" "}
Oui
</label>
<label className={styles.backProblemsLabel}>
<input
type="radio"
name="backProblems"
onChange={() => onBackProblemsChange(false)}
checked={!backProblems}
/>{" "}
Non
</label>
</div>
</div>
<div
className={classnames([
hostingType === "" || hostingType === "neither" ? styles.hide : null,
])}
>
{nightList.map((nightOption) =>
getNightElement(
nightOption,
hostingType === "need"
? " J'aimerai bien mais pas obligatoire"
: " Je peux mais ça ne m'arrange pas trop"
)
)}
</div>
<div
className={classnames([
styles.inputWrapper,
styles.noBottomMargin,
hostingType !== "can" && styles.hide,
])}
>
<div className={styles.leftCol}>
<div className={styles.bedTypeTitle}>Le couchage que tu proposes est-il :</div>
</div>
<div className={styles.rightCol}>
{bedList.map((bed) => (
<label className={styles.bedTypeLabel} key={bed}>
<input
type="checkbox"
value="oui"
name={bed}
onChange={() => onBedTypeChange(bed)}
checked={includes(bedType, bed)}
/>{" "}
{bed}
</label>
))}
</div>
</div>
<div
className={classnames([
styles.inputWrapper,
styles.noBottomMargin,
hostingType !== "can" && styles.hide,
])}
>
<div className={styles.leftCol}>
<div className={styles.isolatedBedTitle}>
Le couchage est-il dans une pièce séparée ?
</div>
</div>
<div className={styles.rightCol}>
<label className={styles.isolatedBedLabel}>
<input
type="radio"
name="isolatedBed"
onChange={() => onIsolatedBedChange(true)}
checked={isolatedBed}
/>{" "}
Oui
</label>
<label className={styles.isolatedBedLabel}>
<input
type="radio"
name="isolatedBed"
onChange={() => onIsolatedBedChange(false)}
checked={!isolatedBed}
/>{" "}
Non
</label>
</div>
</div>
<div
className={classnames([
styles.inputWrapper,
styles.bedConfigurationWrapper,
hostingType !== "can" && styles.hide,
])}
>
<div className={styles.leftCol}>
<div className={styles.bedConfigurationTitle}>
Si tu peux héberger plusieurs bénévoles, quelle est la configuration des
couchages proposés ?
</div>
</div>
<div className={styles.rightCol}>
<textarea id="bedConfiguration-comment" ref={bedConfigurationRef} />
</div>
</div>
<div
className={classnames([
styles.inputWrapper,
styles.hostAddressWrapper,
hostingType !== "can" && styles.hide,
])}
>
<div className={styles.leftCol}>
<div className={styles.hostAddressTitle}>
habites-tu ? Au minium, quelle ville ?
</div>
</div>
<div className={styles.rightCol}>
<textarea id="hostAddress" ref={hostAddressRef} />
</div>
</div>
<div
className={classnames([
styles.inputWrapper,
styles.noBottomMargin,
hostingType !== "need" && styles.hide,
])}
>
<div className={styles.leftCol}>
<div className={styles.festivalProximityTitle}> habites-tu ?</div>
</div>
<div className={styles.rightCol}>
{hostLocations.map((hostLocation) => (
<label className={styles.festivalProximityLabel} key={hostLocation}>
<input
type="radio"
name="festivalProximity"
onChange={() => onFestivalProximityChange(hostLocation)}
checked={hostLocation === festivalProximity}
/>{" "}
{hostLocation}
</label>
))}
</div>
</div>
<div
className={classnames([styles.inputWrapper, hostingType !== "can" && styles.hide])}
>
<div className={styles.leftCol}>
<div className={styles.transportTypeTitle}>
Par quel moyen de transport prévois-tu de venir avec le/les bénévole(s) ?
</div>
</div>
<div className={styles.rightCol}>
<input
className={styles.transportTypeLabel}
type="text"
ref={transportTypeRef}
/>
</div>
</div>
<div
className={classnames([
styles.inputWrapper,
(hostingType === "" ||
hostingType === "neither" ||
(hostingType === "need" &&
(festivalProximity === "hors région parisienne" ||
festivalProximity === ""))) &&
styles.hide,
])}
>
<div className={styles.leftCol}>
<div className={styles.distanceToFestivalTitle}>
À combien de minutes de transport es-tu du festival ? (En voiture si tu es
en voiture, à vélo si tu as des vélos, sinon en transport en commun.)
A combien de temps habites-tu de la pelouse de Reuilly porte à porte ?
</div>
</div>
<div className={styles.rightCol}>
<input
className={styles.distanceToFestivalLabel}
type="text"
ref={distanceRef}
ref={distanceToFestivalRef}
/>
</div>
</div>
<div className={styles.hostingCommentWrapper}>
<label htmlFor="hosting-comment">Un commentaire, une précision ?</label>
<textarea id="hosting-comment" ref={commentRef} />
<div
className={classnames([
styles.hostingNeedReasonWrapper,
(hostingType !== "need" ||
festivalProximity === "hors région parisienne" ||
festivalProximity === "") &&
styles.hide,
])}
>
<label htmlFor="hostingNeedReason">Pourquoi as-tu besoin d'un hébergement ?</label>
<textarea id="hostingNeedReason" ref={hostingNeedReasonRef} />
</div>
<div
className={classnames([
styles.inputWrapper,
styles.noBottomMargin,
hostingType !== "need" && styles.hide,
])}
>
<div className={styles.leftCol}>
<div className={styles.hostingAbsoluteNeedTitle}>
Pourras-tu venir au festival même si on ne te trouve pas dhébergement
bénévole ?
</div>
</div>
<div className={styles.rightCol}>
<label className={styles.hostingAbsoluteNeedLabel}>
<input
type="radio"
name="hostingAbsoluteNeed"
onChange={() => onHostingAbsoluteNeedChange(true)}
checked={hostingAbsoluteNeed}
/>{" "}
Oui
</label>
<label className={styles.hostingAbsoluteNeedLabel}>
<input
type="radio"
name="hostingAbsoluteNeed"
onChange={() => onHostingAbsoluteNeedChange(false)}
checked={!hostingAbsoluteNeed}
/>{" "}
Non
</label>
</div>
</div>
<div className={styles.buttonWrapper}>
<FormButton onClick={onChoiceSubmit}>Enregistrer</FormButton>
{children === undefined && (

View File

@ -15,6 +15,10 @@
}
}
.hide {
display: none;
}
.noBottomMargin {
margin-bottom: 0;
}
@ -28,82 +32,89 @@
text-align: center;
}
.needsHostingTitle {
.hostingTypeForm {
padding: 10px;
border: 1px solid #000;
}
.hostingTypeLabel {
text-align: left;
display: block;
margin-bottom: 10px;
}
.canHostCountTitle,
.backProblemsTitle,
.bedTypeTitle,
.nightTitle,
.isolatedBedTitle,
.bedConfigurationTitle,
.hostAddressTitle,
.petAllergiesTitle,
.transportTypeTitle,
.festivalProximityTitle,
.distanceToFestivalTitle,
.hostingAbsoluteNeedTitle {
display: inline-block;
width: 320px;
margin-bottom: 10px;
}
.needsHostingLabel {
.canHostCountLabel,
.backProblemsLabel,
.bedTypeLabel,
.isolatedBedLabel,
.bedConfigurationLabel,
.festivalProximityLabel,
.hostingAbsoluteNeedLabel {
text-align: left;
display: inline-block;
margin-bottom: 10px;
width: 80px;
}
.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;
}
.petAllergiesLabel,
.transportTypeLabel,
.distanceToFestivalLabel {
text-align: left;
display: inline-block;
margin-left: 10px;
margin-bottom: 10px;
width: 80px;
width: 180px;
}
.hostingTitle {
.nightLabel {
text-align: left;
display: inline-block;
width: 320px;
margin-bottom: 10px;
width: 50px;
}
.hostingList {
@include clear-ul-style;
.nightLabelLong {
text-align: left;
display: inline-block;
width: 204px;
text-align: center;
margin-left: 10px;
margin-bottom: 10px;
width: 180px;
}
.hostingItem {
display: inline-block;
margin: 3px;
}
.bedConfigurationWrapper,
.hostAddressWrapper {
margin: 6px 0;
.hostingButton {
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;
label {
display: block;
padding: 6px 0 2px 4px;
}
textarea {
width: 100%;
height: 60px;
padding: 5px;
border: 1px solid $color-grey-light;
background-color: $color-grey-lighter;
outline: 0;
}
}
.hostingCommentWrapper {
.hostingNeedReasonWrapper {
margin: 6px 0 14px;
label {

View File

@ -1,9 +1,9 @@
import { FC, memo } from "react"
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 useAction from "../../../utils/useAction"
import { displayModal, MODAL_IDS } from "../../../store/ui"
import { useUserDayWishes } from "../daysWishes.utils"
const Meals: FC = (): JSX.Element | null => {
@ -11,8 +11,8 @@ const Meals: FC = (): JSX.Element | null => {
const [userWishes] = useUserDayWishes()
const meals = get(userMeals, "meals", []) as string[]
const dayWishesString = get(userWishes, "dayWishes", []) as string[]
// const execDisplayModal = useAction(displayModal)
// const onEdit = useCallback(() => execDisplayModal(MODAL_IDS.MEALS), [execDisplayModal])
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[]
@ -32,9 +32,7 @@ const Meals: FC = (): JSX.Element | null => {
{dayWishesString.includes("S") ? (
<>
{getMealElement(0)}
<div className={styles.mealsLabel} key="SamediSoir">
Samedi soir, apéro dînatoire
</div>
{getMealElement(1)}
</>
) : (
<div className={styles.mealsLabel} key="Samedi">
@ -44,8 +42,8 @@ const Meals: FC = (): JSX.Element | null => {
{dayWishesString.includes("D") ? (
<>
{getMealElement(1)}
{getMealElement(2)}
{getMealElement(3)}
</>
) : (
<div className={styles.mealsLabel} key="Dimanche">
@ -53,14 +51,14 @@ const Meals: FC = (): JSX.Element | null => {
</div>
)}
{/* <div className={styles.editButton} key="edit">
<div className={styles.editButton} key="edit">
<button type="button" onClick={onEdit}>
Modifier
</button>
</div> */}
<div className={styles.editButton} key="edit">
Plus modifiable
</div>
{/* <div className={styles.editButton} key="edit">
Plus modifiable
</div> */}
</div>
)
}

View File

@ -1,5 +1,6 @@
import { get } from "lodash"
import { FC, memo, ReactNode, useCallback, useEffect, useState } from "react"
import set from "lodash/set"
import { FC, memo, ReactNode, useCallback, useEffect, useRef, useState } from "react"
import classnames from "classnames"
import styles from "./styles.module.scss"
import { mealDays, MealOption, useUserMeals } from "../meals.utils"
@ -16,28 +17,39 @@ type Props = {
const MealsForm: FC<Props> = ({ children, afterSubmit }): JSX.Element => {
const [saturdayLunchMeal, setSaturdayLunchMeal] = useState("")
const [saturdayDinnerMeal, setSaturdayDinnerMeal] = 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", []) as string[]
const foodRef = useRef<HTMLTextAreaElement | null>(null)
useEffect(() => {
setSaturdayLunchMeal(meals[0] || "")
setSundayLunchMeal(meals[1] || "")
setSundayDinnerMeal(meals[2] || "")
}, [meals])
setSaturdayDinnerMeal(meals[1] || "")
setSundayLunchMeal(meals[2] || "")
setSundayDinnerMeal(meals[3] || "")
set(foodRef, "current.value", get(userMeals, "food", ""))
}, [meals, userMeals])
const onChoiceSubmit = useCallback(() => {
saveMeals([saturdayLunchMeal, sundayLunchMeal, sundayDinnerMeal])
const food = get(foodRef, "current.value", "")
saveMeals([saturdayLunchMeal, saturdayDinnerMeal, sundayLunchMeal, sundayDinnerMeal], food)
if (afterSubmit) afterSubmit()
}, [saveMeals, saturdayLunchMeal, sundayLunchMeal, sundayDinnerMeal, afterSubmit])
}, [
saveMeals,
saturdayLunchMeal,
saturdayDinnerMeal,
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.
<b>{dayName} matin</b>, petit dej avec jus, café, thé, brioche, quatre-quart.
</div>
)
@ -45,9 +57,7 @@ const MealsForm: FC<Props> = ({ children, afterSubmit }): JSX.Element => {
<div className={classnames(styles.inputWrapper, styles.noBottomMargin)}>
<div className={styles.leftCol}>
<div className={styles.needsMealsTitle}>
<b>{mealDays[i].name}</b>
{(i === 0 || i === 1) && <>, accompagné d'un délicieux brownie tout chocolat</>}
{i === 2 && <>, accompagné d'une part de tarte indéterminée</>} :
<b>{mealDays[i].name}</b> :
</div>
</div>
<div className={styles.rightCol}>
@ -97,9 +107,7 @@ const MealsForm: FC<Props> = ({ children, afterSubmit }): JSX.Element => {
<>
{getBreakfeastElement("Samedi")}
{getMealElement(0, saturdayLunchMeal, setSaturdayLunchMeal)}
<div className={styles.mealsLabel} key="SamediSoir">
<b>Samedi soir</b>, apéro dînatoire
</div>
{getMealElement(1, saturdayDinnerMeal, setSaturdayDinnerMeal)}
</>
) : (
getNotVolunteerElement("Samedi")
@ -110,8 +118,8 @@ const MealsForm: FC<Props> = ({ children, afterSubmit }): JSX.Element => {
{dayWishesString.includes("D") ? (
<>
{getBreakfeastElement("Dimanche")}
{getMealElement(1, sundayLunchMeal, setSundayLunchMeal)}
{getMealElement(2, sundayDinnerMeal, setSundayDinnerMeal)}
{getMealElement(2, sundayLunchMeal, setSundayLunchMeal)}
{getMealElement(3, sundayDinnerMeal, setSundayDinnerMeal)}
</>
) : (
getNotVolunteerElement("Dimanche")
@ -119,9 +127,16 @@ const MealsForm: FC<Props> = ({ children, afterSubmit }): JSX.Element => {
<div className={classnames(styles.inputWrapper)}>
<div>
<b>Jeudi, vendredi et lundi</b>, chacun improvise. Peut-être resto à proximité.
<b>Jeudi, vendredi et lundi</b>, cocktail dejeunatoire avec salades composées,
charcuterie, fromage...
</div>
</div>
<div className={styles.foodWrapper}>
<label htmlFor="food">As-tu des restrictions alimentaires ?</label>
<textarea id="food" ref={foodRef} />
</div>
<div className={styles.buttonWrapper}>
<FormButton onClick={onChoiceSubmit}>Enregistrer</FormButton>
{children === undefined && (

View File

@ -32,7 +32,7 @@
.mealsLabel {
text-align: left;
display: inline-block;
display: block;
margin-bottom: 10px;
width: 220px;
}
@ -73,7 +73,7 @@
}
}
.mealsCommentWrapper {
.foodWrapper {
margin: 6px 0 14px;
label {

View File

@ -1,7 +1,7 @@
import { FC, memo, useCallback } from "react"
import get from "lodash/get"
import styles from "./styles.module.scss"
import { foodDefaultValue, useUserParticipationDetails } from "../participationDetails.utils"
import { useUserParticipationDetails } from "../participationDetails.utils"
import { displayModal, MODAL_IDS } from "../../../store/ui"
import useAction from "../../../utils/useAction"
@ -13,8 +13,6 @@ const ParticipationDetails: FC<Props> = (): JSX.Element | null => {
const [participationDetails] = useUserParticipationDetails()
const adult = get(participationDetails, "adult", "")
const tshirtSize = get(participationDetails, "tshirtSize", "")
const tshirtCount = get(participationDetails, "tshirtCount", "")
const food = get(participationDetails, "food", "")
const execDisplayModal = useAction(displayModal)
const onEdit = useCallback(
() => execDisplayModal(MODAL_IDS.PARTICIPATIONDETAILS),
@ -24,51 +22,28 @@ const ParticipationDetails: FC<Props> = (): JSX.Element | null => {
return (
<div className={styles.root}>
<div className={styles.title}>Mes infos logistiques</div>
{tshirtCount === 0 && (
<div className={styles.line}>
Je n'ai <b>aucun t-shirt</b> et{" "}
{tshirtSize ? (
<>
je suis taillé·e <b>{tshirtSize}</b>
</>
) : (
<>
ma taille est <span className={styles.lineEmpty}>non renseignées</span>
</>
)}
</div>
)}
{tshirtCount === 1 && (
<div className={styles.line}>
J'ai <b>un seul t-shirt</b> et{" "}
{tshirtSize ? (
<>
je suis taillé·e <b>{tshirtSize}</b>
</>
) : (
<>
ma taille est <span className={styles.lineEmpty}>non renseignées</span>
</>
)}
</div>
)}
{tshirtCount === 2 && (
<div className={styles.line}>
J'ai au moins <b>deux t-shirts</b>
</div>
)}
{adult === 0 && (
<div className={styles.line}>
Le 2 juillet 2022, je serai <b>mineur·e</b>
Le 1er juillet 2023, je serai <b>mineur·e</b>
<br />
Attention les bénévoles mineurs doivent être dans la même équipe que leur
responsable légal !
</div>
)}
{adult === 1 && (
<div className={styles.line}>
Le 2 juillet 2022, je serai <b>majeur·e</b>
Le 1er juillet 2023, je serai <b>majeur·e</b>
</div>
)}
<div className={styles.line}>
Préférence alimentaire : <b>{food || foodDefaultValue}</b>
{tshirtSize === "" && <>Je n'ai pas encore choisi de tee-shirt.</>}
{tshirtSize === "Aucun" && <>Je n'ai pas besoin de tee-shirt cette année.</>}
{tshirtSize !== "" && tshirtSize !== "Aucun" && (
<>
J'aimerai un teeshirt <b>{tshirtSize}</b>.
</>
)}
</div>
<div className={styles.editButton}>
<button type="button" onClick={onEdit}>

View File

@ -14,25 +14,15 @@ type Props = {
const ParticipationDetailsForm: FC<Props> = ({ children, afterSubmit }): JSX.Element | null => {
const sizeRef = useRef<HTMLSelectElement | null>(null)
const dietRef = useRef<HTMLTextAreaElement | null>(null)
const [tshirtCountState, setTshirtCount] = useState<number>(0)
const [adultState, setAdult] = useState<number>(0)
const [participationDetails, saveParticipationDetails] = useUserParticipationDetails()
const onSubmit = useCallback(() => {
const tshirtSize = get(sizeRef, "current.value", "")
const food = get(dietRef, "current.value", "")
saveParticipationDetails(tshirtSize, tshirtCountState, adultState, food)
saveParticipationDetails(tshirtSize, adultState)
if (afterSubmit) afterSubmit()
}, [tshirtCountState, adultState, saveParticipationDetails, afterSubmit])
const onTshirtCountChange = useCallback(
(value: number) => {
setTshirtCount(value)
},
[setTshirtCount]
)
}, [adultState, saveParticipationDetails, afterSubmit])
const onAdultChange = useCallback(
(value: number) => {
@ -43,75 +33,19 @@ const ParticipationDetailsForm: FC<Props> = ({ children, afterSubmit }): JSX.Ele
useEffect(() => {
const tshirtSize = get(participationDetails, "tshirtSize", "")
const tshirtCount = get(participationDetails, "tshirtCount", "")
const adult = get(participationDetails, "adult", "")
const food = get(participationDetails, "food", "")
if (tshirtSize) set(sizeRef, "current.value", tshirtSize)
if (tshirtCount) setTshirtCount(tshirtCount)
if (adult) setAdult(adult)
if (food) set(dietRef, "current.value", food)
}, [setTshirtCount, setAdult, participationDetails])
}, [setAdult, participationDetails])
return (
<div>
<div className={styles.title}>Mes infos logistiques</div>
<div className={styles.inputWrapper}>
<div className={styles.leftCol}>
<div className={styles.tshirtCountTitle}>Combien as-tu de t-shirts PeL ?</div>
</div>
<div className={styles.rightCol}>
<label className={styles.tshirtCountLabel}>
<input
type="radio"
name="tshirtCount"
onChange={() => onTshirtCountChange(0)}
checked={tshirtCountState === 0}
/>{" "}
Aucun
</label>
<label className={styles.tshirtCountLabel}>
<input
type="radio"
name="tshirtCount"
onChange={() => onTshirtCountChange(1)}
checked={tshirtCountState === 1}
/>{" "}
Un seul
</label>
<label className={styles.tshirtCountLabel}>
<input
type="radio"
name="tshirtCount"
onChange={() => onTshirtCountChange(2)}
checked={tshirtCountState === 2}
/>{" "}
Au moins deux
</label>
</div>
</div>
<div className={styles.inputWrapper}>
<div className={styles.leftCol}>
<label htmlFor="tshirtSize" className={styles.tshirtSizesTitle}>
Quelle est ta taille de t-shirt ?
</label>
</div>
<div className={styles.rightCol}>
<label className={styles.tshirtSizeLabel}>
<select id="tshirtSize" ref={sizeRef} className={styles.tshirtCountSelect}>
{tshirtSizes.map((size) => (
<option key={size} value={size}>
{size}
</option>
))}
</select>
</label>
</div>
</div>
<div className={styles.inputWrapper}>
<div className={styles.leftCol}>
<div className={styles.adultTitle}>Seras-tu majeur·e au 2 juillet 2022 ?</div>
<div className={styles.adultTitle}>Seras-tu majeur·e au 1 juillet 2023 ?</div>
</div>
<div className={styles.rightCol}>
<label className={styles.adultLabel}>
@ -134,10 +68,31 @@ const ParticipationDetailsForm: FC<Props> = ({ children, afterSubmit }): JSX.Ele
</label>
</div>
</div>
<div className={styles.dietWrapper}>
<label htmlFor="diet">Préférence alimentaire ?</label>
<textarea id="diet" ref={dietRef} placeholder="végétarien ? halal ? ..." />
<div>
Cette année comme il y a de nouveaux tee-shirts avec un col en V, tous les bénévoles
peuvent en commander un !<br />
Autre nouveauté, il y a des tee-shirts taille enfant !
</div>
<div className={styles.inputWrapper}>
<div className={styles.leftCol}>
<label htmlFor="tshirtSize" className={styles.tshirtSizesTitle}>
Que veux-tu comme tee-shirt ?
</label>
</div>
<div className={styles.rightCol}>
<label className={styles.tshirtSizeLabel}>
<select id="tshirtSize" ref={sizeRef} className={styles.tshirtCountSelect}>
{tshirtSizes.map((size) => (
<option key={size} value={size}>
{size}
</option>
))}
</select>
</label>
</div>
</div>
<div className={styles.buttonWrapper}>
<FormButton onClick={onSubmit}>Enregistrer</FormButton>
{children === undefined && (

View File

@ -71,8 +71,8 @@ const TeamWishesForm: FC<Props> = ({ children, afterSubmit }): JSX.Element | nul
})}
</ol>
<div className={styles.commentWrapper}>
<label htmlFor="day-choice-comment">Un commentaire, une précision ?</label>
<textarea id="day-choice-comment" ref={commentRef} />
<label htmlFor="team-choice-comment">Un commentaire, une précision ?</label>
<textarea id="team-choice-comment" ref={commentRef} />
</div>
</div>
<div className={styles.rightCol}>

View File

@ -7,10 +7,21 @@ import useAction from "../../utils/useAction"
import { VolunteerHosting } from "../../services/volunteers"
type SetFunction = (
needsHosting: VolunteerHosting["needsHosting"],
hostingType: VolunteerHosting["hostingType"],
canHostCount: VolunteerHosting["canHostCount"],
cohostVolunteer: VolunteerHosting["cohostVolunteer"],
backProblems: VolunteerHosting["backProblems"],
hostingNights: VolunteerHosting["hostingNights"],
bedType: VolunteerHosting["bedType"],
isolatedBed: VolunteerHosting["isolatedBed"],
bedConfiguration: VolunteerHosting["bedConfiguration"],
hostAddress: VolunteerHosting["hostAddress"],
petAllergies: VolunteerHosting["petAllergies"],
transportType: VolunteerHosting["transportType"],
festivalProximity: VolunteerHosting["festivalProximity"],
distanceToFestival: VolunteerHosting["distanceToFestival"],
hostingComment: VolunteerHosting["hostingComment"]
hostingNeedReason: VolunteerHosting["hostingNeedReason"],
hostingAbsoluteNeed: VolunteerHosting["hostingAbsoluteNeed"]
) => void
export const useUserHosting = (): [VolunteerHosting | undefined, SetFunction] => {
@ -22,14 +33,41 @@ export const useUserHosting = (): [VolunteerHosting | undefined, SetFunction] =>
)
const saveWishes: SetFunction = useCallback(
(needsHosting, canHostCount, distanceToFestival, hostingComment) => {
(
hostingType,
canHostCount,
cohostVolunteer,
backProblems,
hostingNights,
bedType,
isolatedBed,
bedConfiguration,
hostAddress,
petAllergies,
transportType,
festivalProximity,
distanceToFestival,
hostingNeedReason,
hostingAbsoluteNeed
) => {
if (!userWishes) return
save(jwtToken, 0, {
id: userWishes.id,
needsHosting,
hostingType,
canHostCount,
cohostVolunteer,
backProblems,
hostingNights,
bedType,
isolatedBed,
bedConfiguration,
hostAddress,
petAllergies,
transportType,
festivalProximity,
distanceToFestival,
hostingComment,
hostingNeedReason,
hostingAbsoluteNeed,
})
},
[userWishes, save, jwtToken]
@ -37,3 +75,57 @@ export const useUserHosting = (): [VolunteerHosting | undefined, SetFunction] =>
return [userWishes, saveWishes]
}
export const bedList: string[] = [
"un lit une place",
"un lit 2 places",
"un canapé ",
"un canapé-lit",
"un matelas au sol",
]
type HostLocation = "Paris" | "région parisienne" | "hors région parisienne" | ""
export const hostLocations: HostLocation[] = [
"Paris",
"région parisienne",
"hors région parisienne",
]
export type NightOption = { abbr: string; title: string }
export const nightList: NightOption[] = [
{
abbr: "M",
title: "Nuit du mercredi 28 au jeudi 29 juin",
},
{
abbr: "J",
title: "Nuit du jeudi 29 au vendredi 30 juin",
},
{
abbr: "V",
title: "Nuit du vendredi 30 juin au samedi 1er juillet",
},
{
abbr: "S",
title: "Nuit du samedi 1er au dimanche 2 juillet",
},
{
abbr: "D",
title: "Nuit du dimanche 2 au lundi 3 juillet",
},
{
abbr: "L",
title: "Nuit du lundi 3 au mardi 4 juillet",
},
]
export interface NightChoices {
[key: string]: boolean
}
export const nightChoiceSelectionDefaultState = nightList.reduce((state, { abbr }) => {
state[abbr] = false
state[abbr.toLowerCase()] = false
return state
}, <NightChoices>{})

View File

@ -16,18 +16,29 @@ 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: "V", title: "Taboulé" },
{ abbr: "F", title: "Quinoa, courgettes, fromage" },
{ abbr: "P", title: "Riz à la Niçoise (thon)" },
{ abbr: "", title: "Pas de repas" },
],
},
{
name: "Samedi soir",
options: [
{
abbr: "V",
title: "Aubergines fondantes avec égrené végétal",
},
{ abbr: "P", title: "Risotto 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: "V", title: "Sandwich aux légumes" },
{ abbr: "F", title: "Sandwich au fromage" },
{ abbr: "P", title: "Sandwich au poulet" },
{ abbr: "", title: "Pas de repas" },
],
},
@ -36,15 +47,15 @@ export const mealDays: MealDay[] = [
options: [
{
abbr: "V",
title: "Lasagnes végétariennes accompagnées de ratatouille et haricots verts",
title: "Risotto végétarien",
},
{ abbr: "P", title: "Aiguillettes de poulet accompagnées de riz thaï" },
{ abbr: "P", title: "Parmentier de canard" },
{ abbr: "", title: "Pas de repas" },
],
},
]
type SetFunction = (meals: VolunteerMeals["meals"]) => void
type SetFunction = (meals: VolunteerMeals["meals"], food: VolunteerMeals["food"]) => void
export const useUserMeals = (): [VolunteerMeals | undefined, SetFunction] => {
const save = useAction(fetchVolunteerMealsSet)
@ -55,11 +66,12 @@ export const useUserMeals = (): [VolunteerMeals | undefined, SetFunction] => {
)
const saveWishes: SetFunction = useCallback(
(meals) => {
(meals, food) => {
if (!userWishes) return
save(jwtToken, 0, {
id: userWishes.id,
meals,
food,
})
},
[userWishes, save, jwtToken]

View File

@ -7,30 +7,57 @@ import { fetchVolunteerParticipationDetailsSet } from "../../store/volunteerPart
import { VolunteerParticipationDetails } from "../../services/volunteers"
export const tshirtSizes = [
"XXS",
"XS",
"S",
"M",
"L",
"XL",
"XXL",
"3XL",
"4XL",
"Femme S",
"Femme M",
"Femme L",
"Femme XL",
"Femme XXL",
"Femme 3XL",
"Aucun",
"Enfant col rond 2 ans",
"Enfant col rond 3 ans",
"Enfant col rond 4 ans",
"Enfant col rond 5 ans",
"Enfant col rond 6 ans",
"Enfant col rond 7 ans",
"Enfant col rond 8 ans",
"Enfant col rond 9 ans",
"Enfant col rond 10 ans",
"Enfant col rond 11 ans",
"Enfant col rond 12 ans",
"Femme col V S",
"Femme col V M",
"Femme col V L",
"Femme col V XL",
"Femme col V XXL",
"Femme col V 3XL",
"Femme col rond XXS",
"Femme col rond XS",
"Femme col rond S",
"Femme col rond M",
"Femme col rond L",
"Femme col rond XL",
"Femme col rond XXL",
"Femme col rond 3XL",
"Femme col rond 4XL",
"Femme col rond 5XL",
"Homme col V S",
"Homme col V M",
"Homme col V L",
"Homme col V XL",
"Homme col V XXL",
"Homme col V 3XL",
"Homme col rond XXS",
"Homme col rond XS",
"Homme col rond S",
"Homme col rond M",
"Homme col rond L",
"Homme col rond XL",
"Homme col rond XXL",
"Homme col rond 3XL",
"Homme col rond 4XL",
"Homme col rond 5XL",
]
export const foodDefaultValue = "Aucune"
type SetFunction = (
tshirtSize: VolunteerParticipationDetails["tshirtSize"],
tshirtCount: VolunteerParticipationDetails["tshirtCount"],
adult: VolunteerParticipationDetails["adult"],
food: VolunteerParticipationDetails["food"]
adult: VolunteerParticipationDetails["adult"]
) => void
export const useUserParticipationDetails = (): [
@ -45,14 +72,12 @@ export const useUserParticipationDetails = (): [
)
const saveParticipationDetails: SetFunction = useCallback(
(tshirtSize, tshirtCount, adult, food) => {
(tshirtSize, adult) => {
if (!userParticipationDetails) return
save(jwtToken, 0, {
id: userParticipationDetails.id,
tshirtSize,
tshirtCount,
adult,
food,
})
},
[userParticipationDetails, save, jwtToken]

View File

@ -361,27 +361,71 @@ export const volunteerHostingSet = expressAccessor.set(async (list, body, id) =>
}
const newVolunteer: Volunteer = cloneDeep(volunteer)
if (wishes.needsHosting !== undefined) {
newVolunteer.needsHosting = wishes.needsHosting
if (wishes.hostingType !== undefined) {
newVolunteer.hostingType = wishes.hostingType
}
if (wishes.canHostCount !== undefined) {
newVolunteer.canHostCount = wishes.canHostCount
}
if (wishes.cohostVolunteer !== undefined) {
newVolunteer.cohostVolunteer = wishes.cohostVolunteer
}
if (wishes.backProblems !== undefined) {
newVolunteer.backProblems = wishes.backProblems
}
if (wishes.hostingNights !== undefined) {
newVolunteer.hostingNights = wishes.hostingNights
}
if (wishes.bedType !== undefined) {
newVolunteer.bedType = wishes.bedType
}
if (wishes.isolatedBed !== undefined) {
newVolunteer.isolatedBed = wishes.isolatedBed
}
if (wishes.bedConfiguration !== undefined) {
newVolunteer.bedConfiguration = wishes.bedConfiguration
}
if (wishes.hostAddress !== undefined) {
newVolunteer.hostAddress = wishes.hostAddress
}
if (wishes.petAllergies !== undefined) {
newVolunteer.petAllergies = wishes.petAllergies
}
if (wishes.transportType !== undefined) {
newVolunteer.transportType = wishes.transportType
}
if (wishes.festivalProximity !== undefined) {
newVolunteer.festivalProximity = wishes.festivalProximity
}
if (wishes.distanceToFestival !== undefined) {
newVolunteer.distanceToFestival = wishes.distanceToFestival
}
if (wishes.hostingComment !== undefined) {
newVolunteer.hostingComment = wishes.hostingComment
if (wishes.hostingNeedReason !== undefined) {
newVolunteer.hostingNeedReason = wishes.hostingNeedReason
}
if (wishes.hostingAbsoluteNeed !== undefined) {
newVolunteer.hostingAbsoluteNeed = wishes.hostingAbsoluteNeed
}
return {
toDatabase: newVolunteer,
toCaller: {
id: newVolunteer.id,
needsHosting: newVolunteer.needsHosting,
hostingType: newVolunteer.hostingType,
canHostCount: newVolunteer.canHostCount,
cohostVolunteer: newVolunteer.cohostVolunteer,
backProblems: newVolunteer.backProblems,
hostingNights: newVolunteer.hostingNights,
bedType: newVolunteer.bedType,
isolatedBed: newVolunteer.isolatedBed,
bedConfiguration: newVolunteer.bedConfiguration,
hostAddress: newVolunteer.hostAddress,
petAllergies: newVolunteer.petAllergies,
transportType: newVolunteer.transportType,
festivalProximity: newVolunteer.festivalProximity,
distanceToFestival: newVolunteer.distanceToFestival,
hostingComment: newVolunteer.hostingComment,
hostingNeedReason: newVolunteer.hostingNeedReason,
hostingAbsoluteNeed: newVolunteer.hostingAbsoluteNeed,
} as VolunteerHosting,
}
})
@ -458,20 +502,23 @@ export const volunteerMealsSet = expressAccessor.set(async (list, body, id) => {
newVolunteer.meals = wishes.meals
}
if (wishes.food !== undefined) {
newVolunteer.food = wishes.food
}
return {
toDatabase: newVolunteer,
toCaller: {
id: newVolunteer.id,
meals: newVolunteer.meals,
food: newVolunteer.food,
} as VolunteerMeals,
}
})
export const volunteerParticipationDetailsSet = 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 infos de t-shirt, de majorité et d'alimentation`
)
throw Error(`On ne peut acceder qu'à ses propres infos de t-shirt et de majorité`)
}
const wishes = body[1] as VolunteerParticipationDetails
const volunteer: Volunteer | undefined = list.find((v) => v.id === requestedId)
@ -483,24 +530,16 @@ export const volunteerParticipationDetailsSet = expressAccessor.set(async (list,
if (wishes.tshirtSize !== undefined) {
newVolunteer.tshirtSize = wishes.tshirtSize
}
if (wishes.tshirtCount !== undefined) {
newVolunteer.tshirtCount = wishes.tshirtCount
}
if (wishes.adult !== undefined) {
newVolunteer.adult = wishes.adult
}
if (wishes.food !== undefined) {
newVolunteer.food = wishes.food
}
return {
toDatabase: newVolunteer,
toCaller: {
id: newVolunteer.id,
tshirtSize: newVolunteer.tshirtSize,
tshirtCount: newVolunteer.tshirtCount,
adult: newVolunteer.adult,
food: newVolunteer.food,
} as VolunteerParticipationDetails,
}
})

View File

@ -107,10 +107,12 @@ export default class ServiceAccessors<
try {
const auth = { headers: { Authorization: `Bearer ${jwt}` } }
const fullAxiosConfig = _.defaultsDeep(auth, axiosConfig)
const { data } = await axios.get(
`${config.API_URL}/${this.elementName}${apiName}`,
{ ...fullAxiosConfig, params }
)
const rawData = await axios.get(`${config.API_URL}/${this.elementName}${apiName}`, {
...fullAxiosConfig,
params,
})
console.log("rawData", rawData)
const { data } = rawData
if (data.error) {
throw Error(data.error)
}

View File

@ -68,13 +68,35 @@ export class Volunteer implements VolunteerPartial {
noOpinion: number[] = []
needsHosting = false
hostingType = ""
canHostCount = 0
distanceToFestival = 0
cohostVolunteer = ""
hostingComment = ""
backProblems = false
hostingNights = ""
bedType: string[] = []
isolatedBed = false
bedConfiguration = ""
hostAddress = ""
petAllergies = ""
transportType = ""
festivalProximity = ""
distanceToFestival = ""
hostingNeedReason = ""
hostingAbsoluteNeed = true
meals: string[] = []
@ -116,10 +138,21 @@ export const translationVolunteer: { [k in keyof Volunteer]: string } = {
playable: "jouable",
giftable: "offrable",
noOpinion: "sansAvis",
needsHosting: "besoinHébergement",
hostingType: "typeHébergement",
canHostCount: "nombreHébergés",
cohostVolunteer: "colocBénévole",
backProblems: "malDeDos",
hostingNights: "nuitsHébergé",
bedType: "typeDeLit",
isolatedBed: "litIsolé",
bedConfiguration: "configurationLits",
hostAddress: "adresseHebergement",
petAllergies: "allergiesAnimaux",
transportType: "typeTransport",
festivalProximity: "proximitéAuFestival",
distanceToFestival: "distanceAuFestival",
hostingComment: "commentaireHébergement",
hostingNeedReason: "reasonDêtreHebergé",
hostingAbsoluteNeed: "besoinDhébergement",
meals: "repas",
charter: "charte",
}
@ -171,10 +204,21 @@ export const volunteerExample: Volunteer = {
playable: [34, 35, 36],
giftable: [13, 67],
noOpinion: [3, 4],
needsHosting: false,
hostingType: "neither",
canHostCount: 0,
distanceToFestival: 0,
hostingComment: "",
cohostVolunteer: "",
backProblems: false,
hostingNights: "",
bedType: [],
isolatedBed: false,
bedConfiguration: "",
hostAddress: "",
petAllergies: "",
transportType: "",
festivalProximity: "",
distanceToFestival: "",
hostingNeedReason: "",
hostingAbsoluteNeed: true,
meals: [],
charter: false,
}
@ -224,23 +268,33 @@ export interface VolunteerDayWishes {
export interface VolunteerHosting {
id: Volunteer["id"]
needsHosting: Volunteer["needsHosting"]
hostingType: Volunteer["hostingType"]
canHostCount: Volunteer["canHostCount"]
cohostVolunteer: Volunteer["cohostVolunteer"]
backProblems: Volunteer["backProblems"]
hostingNights: Volunteer["hostingNights"]
bedType: Volunteer["bedType"]
isolatedBed: Volunteer["isolatedBed"]
bedConfiguration: Volunteer["bedConfiguration"]
hostAddress: Volunteer["hostAddress"]
petAllergies: Volunteer["petAllergies"]
transportType: Volunteer["transportType"]
festivalProximity: Volunteer["festivalProximity"]
distanceToFestival: Volunteer["distanceToFestival"]
hostingComment: Volunteer["hostingComment"]
hostingNeedReason: Volunteer["hostingNeedReason"]
hostingAbsoluteNeed: Volunteer["hostingAbsoluteNeed"]
}
export interface VolunteerMeals {
id: Volunteer["id"]
meals: Volunteer["meals"]
food: Volunteer["food"]
}
export interface VolunteerParticipationDetails {
id: Volunteer["id"]
tshirtSize: Volunteer["tshirtSize"]
tshirtCount: Volunteer["tshirtCount"]
adult: Volunteer["adult"]
food: Volunteer["food"]
}
export interface VolunteerPersonalInfo {

View File

@ -37,8 +37,7 @@ export const fetchVolunteerMealsSet = elementFetch(
getRequesting,
getSuccess,
getFailure,
(error: Error) =>
toastError(`Erreur lors du chargement des choix de jours de présence: ${error.message}`)
(error: Error) => toastError(`Erreur lors du chargement des choix des repas: ${error.message}`)
)
const shouldFetchVolunteerMealsSet = (state: AppState, id: number) =>