mirror of
https://github.com/Paris-est-Ludique/intranet.git
synced 2025-06-08 08:34:20 +02:00
Add Brunch and Retex forms ans asks
This commit is contained in:
parent
bd7dc7578e
commit
72a633ae4f
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -18,7 +18,7 @@ jobs:
|
|||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [17.x]
|
node-version: [18.x]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
39
src/components/Asks/AskBrunch.tsx
Normal file
39
src/components/Asks/AskBrunch.tsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { get } from "lodash"
|
||||||
|
import { useCallback } from "react"
|
||||||
|
import { fetchVolunteerAsksSet } from "../../store/volunteerAsksSet"
|
||||||
|
import { useAskTools, addAsk, answerLaterOnProfile } from "./utils"
|
||||||
|
import BrunchForm, { fetchFor as fetchForBrunchForm } from "../VolunteerBoard/BrunchForm/BrunchForm"
|
||||||
|
import { useBrunch } from "../VolunteerBoard/brunch.utils"
|
||||||
|
|
||||||
|
export function AskBrunch(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 [retex] = useBrunch()
|
||||||
|
const question1Default = "-1"
|
||||||
|
const question1 = +get(retex, "question1", question1Default)
|
||||||
|
const needToShow = !!retex && question1 === -1
|
||||||
|
|
||||||
|
addAsk(
|
||||||
|
asks,
|
||||||
|
id,
|
||||||
|
volunteerAsks,
|
||||||
|
false,
|
||||||
|
needToShow,
|
||||||
|
<>
|
||||||
|
<BrunchForm afterSubmit={onSubmit}>{answerLaterOnProfile}</BrunchForm>
|
||||||
|
Nous avons besoin d'une réponse avant le jeudi 15 soir minuit pour commander les repas !
|
||||||
|
^^
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch server-side data here
|
||||||
|
export const fetchFor = [...fetchForBrunchForm]
|
59
src/components/Asks/AskRetex.tsx
Normal file
59
src/components/Asks/AskRetex.tsx
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { get } from "lodash"
|
||||||
|
import { useCallback } from "react"
|
||||||
|
import { fetchVolunteerAsksSet } from "../../store/volunteerAsksSet"
|
||||||
|
import { useAskTools, addAsk, answerLaterOnProfile } from "./utils"
|
||||||
|
import RetexForm, { fetchFor as fetchForRetexForm } from "../VolunteerBoard/RetexForm/RetexForm"
|
||||||
|
import { useRetex } from "../VolunteerBoard/retex.utils"
|
||||||
|
|
||||||
|
export function AskRetex(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 [retex] = useRetex()
|
||||||
|
const question1Default = "-1"
|
||||||
|
const dayWishes = get(retex, "dayWishes", "")
|
||||||
|
const question1 = +get(retex, "question1", question1Default)
|
||||||
|
const question2 = get(retex, "question2", "")
|
||||||
|
const question3 = get(retex, "question3", "")
|
||||||
|
const question4 = get(retex, "question4", "")
|
||||||
|
const question5 = get(retex, "question5", "")
|
||||||
|
const question6 = get(retex, "question6", "")
|
||||||
|
const question7 = get(retex, "question7", "")
|
||||||
|
const question8 = get(retex, "question8", "")
|
||||||
|
const question9 = get(retex, "question9", "")
|
||||||
|
const wasHereBeforeAfter = dayWishes.match(/M|J|V|L/)
|
||||||
|
const needToShow =
|
||||||
|
!!retex &&
|
||||||
|
(question1 === -1 ||
|
||||||
|
!question2 ||
|
||||||
|
!question3 ||
|
||||||
|
!question4 ||
|
||||||
|
(wasHereBeforeAfter && !question5) ||
|
||||||
|
!question6 ||
|
||||||
|
!question7 ||
|
||||||
|
!question8 ||
|
||||||
|
!question9)
|
||||||
|
|
||||||
|
addAsk(
|
||||||
|
asks,
|
||||||
|
id,
|
||||||
|
volunteerAsks,
|
||||||
|
false,
|
||||||
|
needToShow,
|
||||||
|
<>
|
||||||
|
<RetexForm afterSubmit={onSubmit}>{answerLaterOnProfile}</RetexForm>
|
||||||
|
Tes réponses sont modifiable sur la page <a href="/profil">Mon profil</a> jusqu'au 23
|
||||||
|
septembre.
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch server-side data here
|
||||||
|
export const fetchFor = [...fetchForRetexForm]
|
@ -3,16 +3,18 @@ import React, { memo } from "react"
|
|||||||
import styles from "./styles.module.scss"
|
import styles from "./styles.module.scss"
|
||||||
import { useAskTools } from "./utils"
|
import { useAskTools } from "./utils"
|
||||||
import { AskWelcome } from "./AskWelcome"
|
import { AskWelcome } from "./AskWelcome"
|
||||||
|
import { AskBrunch, fetchFor as fetchForBrunch } from "./AskBrunch"
|
||||||
|
import { AskRetex, fetchFor as fetchForRetex } from "./AskRetex"
|
||||||
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 { AskMeals, fetchFor as fetchForMeals } from "./AskMeals"
|
||||||
import { AskPersonalInfo, fetchFor as fetchForPersonalInfo } from "./AskPersonalInfo"
|
// import { AskPersonalInfo, fetchFor as fetchForPersonalInfo } from "./AskPersonalInfo"
|
||||||
import { AskTeamWishes, fetchFor as fetchForTeamWishes } from "./AskTeamWishes"
|
// import { AskTeamWishes, fetchFor as fetchForTeamWishes } from "./AskTeamWishes"
|
||||||
import {
|
// import {
|
||||||
AskParticipationDetails,
|
// AskParticipationDetails,
|
||||||
fetchFor as fetchForParticipationDetails,
|
// fetchFor as fetchForParticipationDetails,
|
||||||
} from "./AskParticipationDetails"
|
// } from "./AskParticipationDetails"
|
||||||
import { AskPushNotif } from "./AskPushNotif"
|
import { AskPushNotif } from "./AskPushNotif"
|
||||||
|
|
||||||
const Asks = (): JSX.Element | null => {
|
const Asks = (): JSX.Element | null => {
|
||||||
@ -20,13 +22,15 @@ const Asks = (): JSX.Element | null => {
|
|||||||
const asks: JSX.Element[] = []
|
const asks: JSX.Element[] = []
|
||||||
|
|
||||||
AskWelcome(asks, 1)
|
AskWelcome(asks, 1)
|
||||||
AskDiscord(asks, 3)
|
AskBrunch(asks, 2)
|
||||||
|
AskRetex(asks, 3)
|
||||||
|
AskDiscord(asks, 5)
|
||||||
|
|
||||||
AskDayWishes(asks, 10)
|
// AskDayWishes(asks, 10)
|
||||||
AskTeamWishes(asks, 11)
|
// AskTeamWishes(asks, 11)
|
||||||
AskParticipationDetails(asks, 12)
|
// AskParticipationDetails(asks, 12)
|
||||||
AskPersonalInfo(asks, 15)
|
// AskPersonalInfo(asks, 15)
|
||||||
AskHosting(asks, 20)
|
// AskHosting(asks, 20)
|
||||||
// AskMeals(asks, 22)
|
// AskMeals(asks, 22)
|
||||||
|
|
||||||
AskPushNotif(asks, 99)
|
AskPushNotif(asks, 99)
|
||||||
@ -62,11 +66,13 @@ export default memo(Asks)
|
|||||||
|
|
||||||
// Fetch server-side data here
|
// Fetch server-side data here
|
||||||
export const fetchFor = [
|
export const fetchFor = [
|
||||||
|
...fetchForBrunch,
|
||||||
|
...fetchForRetex,
|
||||||
...fetchForDiscord,
|
...fetchForDiscord,
|
||||||
...fetchForDayWishes,
|
// ...fetchForDayWishes,
|
||||||
...fetchForHosting,
|
// ...fetchForHosting,
|
||||||
// ...fetchForMeals,
|
// ...fetchForMeals,
|
||||||
...fetchForTeamWishes,
|
// ...fetchForTeamWishes,
|
||||||
...fetchForParticipationDetails,
|
// ...fetchForParticipationDetails,
|
||||||
...fetchForPersonalInfo,
|
// ...fetchForPersonalInfo,
|
||||||
]
|
]
|
||||||
|
@ -37,7 +37,7 @@ const FormButton: FC<Props> = ({ children, text, onClick }): JSX.Element => {
|
|||||||
</button>
|
</button>
|
||||||
<div>{children}</div>
|
<div>{children}</div>
|
||||||
<button type="button" className={styles.greyButton} onClick={onIgnore}>
|
<button type="button" className={styles.greyButton} onClick={onIgnore}>
|
||||||
Ok, ignorer
|
Vraiment passer au questionnaire suivant
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -52,7 +52,7 @@ const MainMenu: FC = (): JSX.Element => {
|
|||||||
<MenuItem name="Questions" pathname="/" />
|
<MenuItem name="Questions" pathname="/" />
|
||||||
<MenuItem name="Annonces" pathname="/annonces" />
|
<MenuItem name="Annonces" pathname="/annonces" />
|
||||||
<MenuItem name="Mon profil" pathname="/profil" />
|
<MenuItem name="Mon profil" pathname="/profil" />
|
||||||
<MenuItem name="Mes connaissances" pathname="/connaissances" />
|
{/* <MenuItem name="Mes connaissances" pathname="/connaissances" /> */}
|
||||||
<RestrictMenuItem
|
<RestrictMenuItem
|
||||||
role={ROLES.ASSIGNER}
|
role={ROLES.ASSIGNER}
|
||||||
name="Gestion équipes"
|
name="Gestion équipes"
|
||||||
|
@ -709,7 +709,7 @@ const RegisterForm = ({ dispatch }: Props): JSX.Element => {
|
|||||||
</div>
|
</div>
|
||||||
<div className={styles.rightCol}>
|
<div className={styles.rightCol}>
|
||||||
<div className={styles.rightColContainer}>
|
<div className={styles.rightColContainer}>
|
||||||
{["WhatsApp", "Signal", "SMS", "Email", "Appel", "Aucun"].map((option) => (
|
{["WhatsApp", "Signal", "SMS", "Email", "Aucun"].map((option) => (
|
||||||
<label className={styles.shortAnswerLabel} key={option}>
|
<label className={styles.shortAnswerLabel} key={option}>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
|
@ -1,32 +1,45 @@
|
|||||||
import { FC, memo } from "react"
|
import { FC, memo } from "react"
|
||||||
import DayWishes from "./DayWishes/DayWishes"
|
// 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 Meals from "./Meals/Meals"
|
||||||
import MealsFormModal from "./MealsForm/MealsFormModal"
|
// 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"
|
||||||
import TeamWishesFormModal from "./TeamWishesForm/TeamWishesFormModal"
|
// import TeamWishesFormModal from "./TeamWishesForm/TeamWishesFormModal"
|
||||||
|
// import VolunteerTeam from "./VolunteerTeam/VolunteerTeam"
|
||||||
import withUserConnected from "../../utils/withUserConnected"
|
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 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 fetchForPersonalInfoForm } from "./PersonalInfoForm/PersonalInfoForm"
|
import { fetchFor as fetchForPersonalInfoForm } from "./PersonalInfoForm/PersonalInfoForm"
|
||||||
import { fetchFor as fetchForTeamWishesForm } from "./TeamWishesForm/TeamWishesForm"
|
|
||||||
import VolunteerTeam from "./VolunteerTeam/VolunteerTeam"
|
|
||||||
import PersonalInfo from "./PersonalInfo/PersonalInfo"
|
import PersonalInfo from "./PersonalInfo/PersonalInfo"
|
||||||
import PersonalInfoFormModal from "./PersonalInfoForm/PersonalInfoFormModal"
|
import PersonalInfoFormModal from "./PersonalInfoForm/PersonalInfoFormModal"
|
||||||
|
import Brunch from "./Brunch/Brunch"
|
||||||
|
import BrunchFormModal from "./BrunchForm/BrunchFormModal"
|
||||||
|
import { fetchFor as fetchForBrunchForm } from "./BrunchForm/BrunchForm"
|
||||||
|
import Retex from "./Retex/Retex"
|
||||||
|
import RetexFormModal from "./RetexForm/RetexFormModal"
|
||||||
|
import { fetchFor as fetchForRetexForm } from "./RetexForm/RetexForm"
|
||||||
|
import { useRetex } from "./retex.utils"
|
||||||
|
|
||||||
const Board: FC = (): JSX.Element => (
|
const Board: FC = (): JSX.Element => {
|
||||||
|
const [retex] = useRetex()
|
||||||
|
return (
|
||||||
<>
|
<>
|
||||||
<ContentTitle title="Profil spécifique au festival" />
|
<ContentTitle title="Profil spécifique au festival" />
|
||||||
<PersonalInfo />
|
<PersonalInfo />
|
||||||
<PersonalInfoFormModal />
|
<PersonalInfoFormModal />
|
||||||
<DayWishes />
|
{retex && <Brunch />}
|
||||||
|
{retex && <BrunchFormModal />}
|
||||||
|
{retex && <Retex />}
|
||||||
|
{retex && <RetexFormModal />}
|
||||||
|
{/* <DayWishes />
|
||||||
<DayWishesFormModal />
|
<DayWishesFormModal />
|
||||||
<ParticipationDetails />
|
<ParticipationDetails />
|
||||||
<ParticipationDetailsFormModal />
|
<ParticipationDetailsFormModal />
|
||||||
@ -36,17 +49,20 @@ const Board: FC = (): JSX.Element => (
|
|||||||
<Hosting />
|
<Hosting />
|
||||||
<HostingFormModal />
|
<HostingFormModal />
|
||||||
<Meals />
|
<Meals />
|
||||||
<MealsFormModal />
|
<MealsFormModal /> */}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export default memo(withUserConnected(Board))
|
export default memo(withUserConnected(Board))
|
||||||
|
|
||||||
export const fetchFor = [
|
export const fetchFor = [
|
||||||
...fetchForDayWishesForm,
|
|
||||||
...fetchForHostingForm,
|
|
||||||
...fetchForMealsForm,
|
|
||||||
...fetchForParticipationDetailsForm,
|
|
||||||
...fetchForPersonalInfoForm,
|
...fetchForPersonalInfoForm,
|
||||||
...fetchForTeamWishesForm,
|
...fetchForRetexForm,
|
||||||
|
...fetchForBrunchForm,
|
||||||
|
// ...fetchForDayWishesForm,
|
||||||
|
// ...fetchForHostingForm,
|
||||||
|
// ...fetchForMealsForm,
|
||||||
|
// ...fetchForParticipationDetailsForm,
|
||||||
|
// ...fetchForTeamWishesForm,
|
||||||
]
|
]
|
||||||
|
42
src/components/VolunteerBoard/Brunch/Brunch.tsx
Normal file
42
src/components/VolunteerBoard/Brunch/Brunch.tsx
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { FC, memo, useCallback } from "react"
|
||||||
|
import get from "lodash/get"
|
||||||
|
import styles from "./styles.module.scss"
|
||||||
|
import { useBrunch } from "../brunch.utils"
|
||||||
|
import { displayModal, MODAL_IDS } from "../../../store/ui"
|
||||||
|
import useAction from "../../../utils/useAction"
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
afterSubmit?: () => void | undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const Brunch: FC<Props> = (): JSX.Element | null => {
|
||||||
|
const [retex] = useBrunch()
|
||||||
|
const question1 = get(retex, "question1", -1)
|
||||||
|
const execDisplayModal = useAction(displayModal)
|
||||||
|
const onEdit = useCallback(() => execDisplayModal(MODAL_IDS.BRUNCH), [execDisplayModal])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.root}>
|
||||||
|
<div className={styles.title}>Inscription au brunch</div>
|
||||||
|
<div className={styles.line}>
|
||||||
|
{question1 === -1 && (
|
||||||
|
<>
|
||||||
|
Ma présence au brunch est{" "}
|
||||||
|
<span className={styles.lineEmpty}>non renseignée</span>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{question1 === 0 && <>Je ne viendrai pas au brunch </>}
|
||||||
|
{question1 > 0 && (
|
||||||
|
<>Je viendrai au brunch{question1 > 1 && <> avec {question1} personne(s)</>}</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className={styles.editButton}>
|
||||||
|
<button type="button" onClick={onEdit}>
|
||||||
|
Modifier
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(Brunch)
|
36
src/components/VolunteerBoard/Brunch/styles.module.scss
Executable file
36
src/components/VolunteerBoard/Brunch/styles.module.scss
Executable file
@ -0,0 +1,36 @@
|
|||||||
|
@import "../../../theme/variables";
|
||||||
|
@import "../../../theme/mixins";
|
||||||
|
|
||||||
|
.root {
|
||||||
|
@include inner-content-wrapper();
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
padding-right: 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lineEmpty {
|
||||||
|
color: $color-red;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editButton {
|
||||||
|
@include vertical-center();
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
right: 20px;
|
||||||
|
|
||||||
|
button {
|
||||||
|
color: $color-green;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
142
src/components/VolunteerBoard/BrunchForm/BrunchForm.tsx
Normal file
142
src/components/VolunteerBoard/BrunchForm/BrunchForm.tsx
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
import { FC, memo, ReactNode, useCallback, useEffect, useRef, useState } from "react"
|
||||||
|
import classnames from "classnames"
|
||||||
|
import get from "lodash/get"
|
||||||
|
import set from "lodash/set"
|
||||||
|
import styles from "./styles.module.scss"
|
||||||
|
import { useBrunch } from "../brunch.utils"
|
||||||
|
import FormButton from "../../Form/FormButton/FormButton"
|
||||||
|
import { fetchRetexSetIfNeed } from "../../../store/retexSet"
|
||||||
|
import IgnoreButton from "../../Form/IgnoreButton/IgnoreButton"
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
children?: ReactNode | undefined
|
||||||
|
afterSubmit?: () => void | undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const BrunchForm: FC<Props> = ({ children, afterSubmit }): JSX.Element | null => {
|
||||||
|
const [brunchPresence, setBrunchPresence] = useState<string>("inconnue")
|
||||||
|
const question1Ref = useRef<HTMLInputElement | null>(null)
|
||||||
|
const question1Default = "-1"
|
||||||
|
|
||||||
|
const [retex, saveBrunch] = useBrunch()
|
||||||
|
|
||||||
|
const onSubmit = useCallback(() => {
|
||||||
|
if (!retex) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const question1 = +get(question1Ref, "current.value", question1Default)
|
||||||
|
saveBrunch(retex.id, question1)
|
||||||
|
if (afterSubmit) afterSubmit()
|
||||||
|
}, [afterSubmit, retex, saveBrunch])
|
||||||
|
|
||||||
|
const onBrunchPresenceChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const presence = e.target.value
|
||||||
|
setBrunchPresence(presence)
|
||||||
|
const guestCountDefault = { oui: 1, non: 0, "peut-etre": -1 }[presence]
|
||||||
|
set(question1Ref, "current.value", `${guestCountDefault}`)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const question1 = +get(retex, "question1", question1Default)
|
||||||
|
|
||||||
|
set(question1Ref, "current.value", `${question1}`)
|
||||||
|
if (question1 >= 1) setBrunchPresence("oui")
|
||||||
|
else if (question1 === 0) setBrunchPresence("non")
|
||||||
|
else setBrunchPresence("peut-etre")
|
||||||
|
}, [setBrunchPresence, retex])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className={styles.title}>Inscription au brunch</div>
|
||||||
|
<div className={styles.inputWrapper}>
|
||||||
|
<div className={styles.leftCol}>
|
||||||
|
<div className={styles.brunchTitle}>
|
||||||
|
Viendras-tu au brunch samedi 1er octobre ? Le boulodrome (19 route des
|
||||||
|
fortifications) nous sera réservé de 10h à 18h.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.rightCol}>
|
||||||
|
<label className={styles.brunchLabel}>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value="oui"
|
||||||
|
name="brunchPresence"
|
||||||
|
onChange={onBrunchPresenceChange}
|
||||||
|
checked={brunchPresence === "oui"}
|
||||||
|
/>{" "}
|
||||||
|
Oui
|
||||||
|
</label>
|
||||||
|
<label className={styles.brunchLabel}>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value="non"
|
||||||
|
name="brunchPresence"
|
||||||
|
onChange={onBrunchPresenceChange}
|
||||||
|
checked={brunchPresence === "non"}
|
||||||
|
/>{" "}
|
||||||
|
Non
|
||||||
|
</label>
|
||||||
|
<label className={styles.brunchLabel}>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value="peut-etre"
|
||||||
|
name="brunchPresence"
|
||||||
|
onChange={onBrunchPresenceChange}
|
||||||
|
checked={brunchPresence === "peut-etre"}
|
||||||
|
/>{" "}
|
||||||
|
Je ne sais pas encore
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className={classnames(
|
||||||
|
styles.inputWrapper,
|
||||||
|
brunchPresence === "oui" ? null : styles.invisible
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div className={styles.leftCol}>
|
||||||
|
<div className={styles.guestCountTitle}>
|
||||||
|
À combien viendras-tu ? Le brunch est pour les bénévoles ayant participé à
|
||||||
|
la dernière édition (y compris ceux empêchés à la dernière minute), ainsi
|
||||||
|
qu'aux éventuels +1 conjoints et enfants. Mais pas les amis, pour lesquels
|
||||||
|
d'autres rdv seront proposés au cours de l'année.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.rightCol}>
|
||||||
|
<input className={styles.guestCountLabel} type="text" ref={question1Ref} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.buttonWrapper}>
|
||||||
|
<FormButton onClick={onSubmit}>Enregistrer</FormButton>
|
||||||
|
{children === undefined && (
|
||||||
|
<>
|
||||||
|
{" "}
|
||||||
|
<FormButton onClick={afterSubmit} type="grey">
|
||||||
|
Annuler
|
||||||
|
</FormButton>{" "}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{children !== undefined && (
|
||||||
|
<>
|
||||||
|
{" "}
|
||||||
|
<IgnoreButton onClick={afterSubmit} text="Ignorer pour l'instant">
|
||||||
|
{children}
|
||||||
|
</IgnoreButton>{" "}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
BrunchForm.defaultProps = {
|
||||||
|
children: undefined,
|
||||||
|
afterSubmit: undefined,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(BrunchForm)
|
||||||
|
|
||||||
|
// Fetch server-side data here
|
||||||
|
export const fetchFor = [fetchRetexSetIfNeed]
|
18
src/components/VolunteerBoard/BrunchForm/BrunchFormModal.tsx
Normal file
18
src/components/VolunteerBoard/BrunchForm/BrunchFormModal.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 BrunchForm from "./BrunchForm"
|
||||||
|
|
||||||
|
const BrunchFormModal: FC = (): JSX.Element => {
|
||||||
|
const execHideModal = useAction(hideModal)
|
||||||
|
const afterFormSubmit = useCallback(() => execHideModal(), [execHideModal])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal modalId={MODAL_IDS.BRUNCH}>
|
||||||
|
<BrunchForm afterSubmit={afterFormSubmit} />
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(BrunchFormModal)
|
109
src/components/VolunteerBoard/BrunchForm/styles.module.scss
Executable file
109
src/components/VolunteerBoard/BrunchForm/styles.module.scss
Executable file
@ -0,0 +1,109 @@
|
|||||||
|
@import "../../../theme/variables";
|
||||||
|
@import "../../../theme/mixins";
|
||||||
|
|
||||||
|
.title {
|
||||||
|
padding: 4px;
|
||||||
|
margin: 15px 0;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputWrapper {
|
||||||
|
margin: 25px 0;
|
||||||
|
|
||||||
|
@include desktop {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"] {
|
||||||
|
min-width: 175px;
|
||||||
|
border: 1px solid $color-grey-medium;
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.leftCol {
|
||||||
|
flex: 0 0 240px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rightCol {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brunchTitle {
|
||||||
|
display: inline-block;
|
||||||
|
width: 320px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.invisible {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brunchLabel {
|
||||||
|
text-align: left;
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
width: 280px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brunchPresenceTitle {
|
||||||
|
display: inline-block;
|
||||||
|
width: 320px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brunchPresenceLabel {
|
||||||
|
text-align: left;
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guestCountTitle {
|
||||||
|
display: inline-block;
|
||||||
|
width: 320px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guestCountLabel {
|
||||||
|
text-align: left;
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.questionWrapper {
|
||||||
|
margin: 6px 0 14px;
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
padding: 6px 0 2px 4px;
|
||||||
|
}
|
||||||
|
textarea {
|
||||||
|
width: 100%;
|
||||||
|
height: 75px;
|
||||||
|
padding: 5px;
|
||||||
|
border: 1px solid $color-grey-light;
|
||||||
|
background-color: $color-grey-lighter;
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonWrapper {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preAnswerWrapper {
|
||||||
|
margin-bottom: 3px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preAnswerButton {
|
||||||
|
@include form-button;
|
||||||
|
|
||||||
|
margin-left: 2px;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
@ -164,7 +164,7 @@ const DayWishesForm: FC<Props> = ({ children, afterSubmit }): JSX.Element => {
|
|||||||
{children !== undefined && (
|
{children !== undefined && (
|
||||||
<>
|
<>
|
||||||
{" "}
|
{" "}
|
||||||
<IgnoreButton onClick={afterSubmit} text="Ignorer">
|
<IgnoreButton onClick={afterSubmit} text="Ignorer pour l'instant">
|
||||||
{children}
|
{children}
|
||||||
</IgnoreButton>{" "}
|
</IgnoreButton>{" "}
|
||||||
</>
|
</>
|
||||||
|
@ -112,7 +112,7 @@ const HostingForm: FC<Props> = ({ children, afterSubmit }): JSX.Element => {
|
|||||||
{children !== undefined && (
|
{children !== undefined && (
|
||||||
<>
|
<>
|
||||||
{" "}
|
{" "}
|
||||||
<IgnoreButton onClick={afterSubmit} text="Ignorer">
|
<IgnoreButton onClick={afterSubmit} text="Ignorer pour l'instant">
|
||||||
{children}
|
{children}
|
||||||
</IgnoreButton>{" "}
|
</IgnoreButton>{" "}
|
||||||
</>
|
</>
|
||||||
|
@ -135,7 +135,7 @@ const MealsForm: FC<Props> = ({ children, afterSubmit }): JSX.Element => {
|
|||||||
{children !== undefined && (
|
{children !== undefined && (
|
||||||
<>
|
<>
|
||||||
{" "}
|
{" "}
|
||||||
<IgnoreButton onClick={afterSubmit} text="Ignorer">
|
<IgnoreButton onClick={afterSubmit} text="Ignorer pour l'instant">
|
||||||
{children}
|
{children}
|
||||||
</IgnoreButton>{" "}
|
</IgnoreButton>{" "}
|
||||||
</>
|
</>
|
||||||
|
@ -37,32 +37,6 @@
|
|||||||
width: 220px;
|
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 {
|
.mealsTitle {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 320px;
|
width: 320px;
|
||||||
|
@ -151,7 +151,7 @@ const ParticipationDetailsForm: FC<Props> = ({ children, afterSubmit }): JSX.Ele
|
|||||||
{children !== undefined && (
|
{children !== undefined && (
|
||||||
<>
|
<>
|
||||||
{" "}
|
{" "}
|
||||||
<IgnoreButton onClick={afterSubmit} text="Ignorer">
|
<IgnoreButton onClick={afterSubmit} text="Ignorer pour l'instant">
|
||||||
{children}
|
{children}
|
||||||
</IgnoreButton>{" "}
|
</IgnoreButton>{" "}
|
||||||
</>
|
</>
|
||||||
|
@ -96,7 +96,6 @@ const PersonalInfoForm: FC<Props> = ({ children, afterSubmit }): JSX.Element =>
|
|||||||
type="file"
|
type="file"
|
||||||
name="myImage"
|
name="myImage"
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
console.log(event?.target?.files?.[0])
|
|
||||||
setSelectedImage(event?.target?.files?.[0] || null)
|
setSelectedImage(event?.target?.files?.[0] || null)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -134,7 +133,7 @@ const PersonalInfoForm: FC<Props> = ({ children, afterSubmit }): JSX.Element =>
|
|||||||
{children !== undefined && (
|
{children !== undefined && (
|
||||||
<>
|
<>
|
||||||
{" "}
|
{" "}
|
||||||
<IgnoreButton onClick={afterSubmit} text="Ignorer">
|
<IgnoreButton onClick={afterSubmit} text="Ignorer pour l'instant">
|
||||||
{children}
|
{children}
|
||||||
</IgnoreButton>{" "}
|
</IgnoreButton>{" "}
|
||||||
</>
|
</>
|
||||||
|
56
src/components/VolunteerBoard/Retex/Retex.tsx
Normal file
56
src/components/VolunteerBoard/Retex/Retex.tsx
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import { FC, memo, useCallback } from "react"
|
||||||
|
import get from "lodash/get"
|
||||||
|
import styles from "./styles.module.scss"
|
||||||
|
import { useRetex } from "../retex.utils"
|
||||||
|
import { displayModal, MODAL_IDS } from "../../../store/ui"
|
||||||
|
import useAction from "../../../utils/useAction"
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
afterSubmit?: () => void | undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const Retex: FC<Props> = (): JSX.Element | null => {
|
||||||
|
const [retex] = useRetex()
|
||||||
|
const dayWishes = get(retex, "dayWishes", "")
|
||||||
|
const question2 = get(retex, "question2", "")
|
||||||
|
const question3 = get(retex, "question3", "")
|
||||||
|
const question4 = get(retex, "question4", "")
|
||||||
|
const question5 = get(retex, "question5", "")
|
||||||
|
const question6 = get(retex, "question6", "")
|
||||||
|
const question7 = get(retex, "question7", "")
|
||||||
|
const question8 = get(retex, "question8", "")
|
||||||
|
const execDisplayModal = useAction(displayModal)
|
||||||
|
const onEdit = useCallback(() => execDisplayModal(MODAL_IDS.RETEX), [execDisplayModal])
|
||||||
|
const weekDays = `,${dayWishes}`.replace(/,S|,D/g, "").replace(/^,/, "")
|
||||||
|
const answeredQuestionCount =
|
||||||
|
(question2 ? 1 : 0) +
|
||||||
|
(question3 ? 1 : 0) +
|
||||||
|
(question4 ? 1 : 0) +
|
||||||
|
(question5 ? 1 : 0) +
|
||||||
|
(question6 ? 1 : 0) +
|
||||||
|
(question7 ? 1 : 0) +
|
||||||
|
(question8 ? 1 : 0)
|
||||||
|
const expectedAnswerCount = weekDays ? 7 : 6
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.root}>
|
||||||
|
<div className={styles.title}>Retour sur PeL 2022</div>
|
||||||
|
<div className={styles.line}>
|
||||||
|
<span
|
||||||
|
className={answeredQuestionCount < expectedAnswerCount ? styles.lineEmpty : ""}
|
||||||
|
>
|
||||||
|
{answeredQuestionCount} réponses{" "}
|
||||||
|
</span>
|
||||||
|
sur {expectedAnswerCount}
|
||||||
|
{answeredQuestionCount >= expectedAnswerCount && <> !</>}
|
||||||
|
</div>
|
||||||
|
<div className={styles.editButton}>
|
||||||
|
<button type="button" onClick={onEdit}>
|
||||||
|
Modifier
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(Retex)
|
36
src/components/VolunteerBoard/Retex/styles.module.scss
Executable file
36
src/components/VolunteerBoard/Retex/styles.module.scss
Executable file
@ -0,0 +1,36 @@
|
|||||||
|
@import "../../../theme/variables";
|
||||||
|
@import "../../../theme/mixins";
|
||||||
|
|
||||||
|
.root {
|
||||||
|
@include inner-content-wrapper();
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
padding-right: 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lineEmpty {
|
||||||
|
color: $color-red;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editButton {
|
||||||
|
@include vertical-center();
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
right: 20px;
|
||||||
|
|
||||||
|
button {
|
||||||
|
color: $color-green;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
374
src/components/VolunteerBoard/RetexForm/RetexForm.tsx
Normal file
374
src/components/VolunteerBoard/RetexForm/RetexForm.tsx
Normal file
@ -0,0 +1,374 @@
|
|||||||
|
import { FC, memo, ReactNode, useCallback, useEffect, useRef } from "react"
|
||||||
|
import get from "lodash/get"
|
||||||
|
import set from "lodash/set"
|
||||||
|
import styles from "./styles.module.scss"
|
||||||
|
import { useRetex } from "../retex.utils"
|
||||||
|
import FormButton from "../../Form/FormButton/FormButton"
|
||||||
|
import { fetchRetexSetIfNeed } from "../../../store/retexSet"
|
||||||
|
import IgnoreButton from "../../Form/IgnoreButton/IgnoreButton"
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
children?: ReactNode | undefined
|
||||||
|
afterSubmit?: () => void | undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const RetexForm: FC<Props> = ({ children, afterSubmit }): JSX.Element | null => {
|
||||||
|
const question2Ref = useRef<HTMLTextAreaElement | null>(null)
|
||||||
|
const question3Ref = useRef<HTMLTextAreaElement | null>(null)
|
||||||
|
const question4Ref = useRef<HTMLTextAreaElement | null>(null)
|
||||||
|
const question5Ref = useRef<HTMLTextAreaElement | null>(null)
|
||||||
|
const question6Ref = useRef<HTMLTextAreaElement | null>(null)
|
||||||
|
const question7Ref = useRef<HTMLTextAreaElement | null>(null)
|
||||||
|
const question8Ref = useRef<HTMLTextAreaElement | null>(null)
|
||||||
|
const question9Ref = useRef<HTMLTextAreaElement | null>(null)
|
||||||
|
|
||||||
|
const [retex, saveRetex] = useRetex()
|
||||||
|
const dayWishes = get(retex, "dayWishes", "")
|
||||||
|
const weekDaysText = `,${dayWishes}`
|
||||||
|
.replace(/,S|,D/g, "")
|
||||||
|
.replace("M", "mercredi")
|
||||||
|
.replace("J", "jeudi")
|
||||||
|
.replace("V", "vendredi")
|
||||||
|
.replace("L", "lundi")
|
||||||
|
.replace(/^,/, "")
|
||||||
|
const weekDays = weekDaysText ? weekDaysText.split(",") : []
|
||||||
|
|
||||||
|
const onSubmit = useCallback(() => {
|
||||||
|
if (!retex) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const question2 = get(question2Ref, "current.value", "")
|
||||||
|
const question3 = get(question3Ref, "current.value", "")
|
||||||
|
const question4 = get(question4Ref, "current.value", "")
|
||||||
|
const question5 = get(question5Ref, "current.value", "")
|
||||||
|
const question6 = get(question6Ref, "current.value", "")
|
||||||
|
const question7 = get(question7Ref, "current.value", "")
|
||||||
|
const question8 = get(question8Ref, "current.value", "")
|
||||||
|
const question9 = get(question9Ref, "current.value", "")
|
||||||
|
saveRetex(
|
||||||
|
retex.id,
|
||||||
|
question2,
|
||||||
|
question3,
|
||||||
|
question4,
|
||||||
|
question5,
|
||||||
|
question6,
|
||||||
|
question7,
|
||||||
|
question8,
|
||||||
|
question9
|
||||||
|
)
|
||||||
|
if (afterSubmit) afterSubmit()
|
||||||
|
}, [afterSubmit, retex, saveRetex])
|
||||||
|
|
||||||
|
const preAnswer = useCallback(
|
||||||
|
(ref: React.MutableRefObject<HTMLTextAreaElement | null>) =>
|
||||||
|
(e: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
|
const answer = e.currentTarget.innerText
|
||||||
|
const currentAnswer = get(ref, "current.value", "")
|
||||||
|
const newAnswer = `${currentAnswer}${currentAnswer ? "\n" : ""}${answer.replace(
|
||||||
|
/_+$/,
|
||||||
|
""
|
||||||
|
)}`
|
||||||
|
set(ref, "current.value", newAnswer)
|
||||||
|
ref?.current?.focus()
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const question2 = get(retex, "question2", "")
|
||||||
|
const question3 = get(retex, "question3", "")
|
||||||
|
const question4 = get(retex, "question4", "")
|
||||||
|
const question5 = get(retex, "question5", "")
|
||||||
|
const question6 = get(retex, "question6", "")
|
||||||
|
const question7 = get(retex, "question7", "")
|
||||||
|
const question8 = get(retex, "question8", "")
|
||||||
|
const question9 = get(retex, "question9", "")
|
||||||
|
|
||||||
|
if (question2) set(question2Ref, "current.value", question2)
|
||||||
|
if (question3) set(question3Ref, "current.value", question3)
|
||||||
|
if (question4) set(question4Ref, "current.value", question4)
|
||||||
|
if (question5) set(question5Ref, "current.value", question5)
|
||||||
|
if (question6) set(question6Ref, "current.value", question6)
|
||||||
|
if (question7) set(question7Ref, "current.value", question7)
|
||||||
|
if (question8) set(question8Ref, "current.value", question8)
|
||||||
|
if (question9) set(question9Ref, "current.value", question9)
|
||||||
|
}, [retex])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className={styles.title}>Retour sur PeL 2022</div>
|
||||||
|
|
||||||
|
<div className={styles.questionWrapper}>
|
||||||
|
On aimerait savoir comment s'est passé ton festival !<br />
|
||||||
|
L'orga lira tes réponses et répondra à son tour à tes questions soit
|
||||||
|
individuellement, soit dans la prochaine gazette. Puis toutes les réponses seront
|
||||||
|
anonymisées et une synthèse sera diffusée dans la gazette.
|
||||||
|
<br />
|
||||||
|
Tu peux répondre par 3 mots ou 3 pages, on a tous vécu le festival différemment !
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.questionWrapper}>
|
||||||
|
<label htmlFor="question2">
|
||||||
|
As-tu un avis positif/négatif ou une recommandation au sujet des repas, des WC,
|
||||||
|
de tes besoins en tee-shirt, chapeau, eau, bière, crème solaire ?
|
||||||
|
</label>
|
||||||
|
<div className={styles.preAnswerWrapper}>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question2Ref)}
|
||||||
|
>
|
||||||
|
Tout était top.
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question2Ref)}
|
||||||
|
>
|
||||||
|
On m’a rapporté que __
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question2Ref)}
|
||||||
|
>
|
||||||
|
J’ai eu un problème concernant __
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<textarea id="question2" ref={question2Ref} placeholder="..." />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.questionWrapper}>
|
||||||
|
<label htmlFor="question3">
|
||||||
|
As-tu, comme prévu et en accord avec ton équipe, pris du temps pour profiter des
|
||||||
|
espaces visiteurs du festival, des badges inter-équipes, des crêpes/glaces à
|
||||||
|
l’espace bénévole ?
|
||||||
|
</label>
|
||||||
|
<div className={styles.preAnswerWrapper}>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question3Ref)}
|
||||||
|
>
|
||||||
|
J’ai joué X temps sur des stands éditeurs.
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question3Ref)}
|
||||||
|
>
|
||||||
|
Je me suis baladé sans jouer.
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question3Ref)}
|
||||||
|
>
|
||||||
|
Il y avait des crêpes ?
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<textarea id="question3" ref={question3Ref} placeholder="..." />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.questionWrapper}>
|
||||||
|
<label htmlFor="question4">
|
||||||
|
Gestion du stress, de la fatigue : as-tu fait des pauses (à notre espace sieste,
|
||||||
|
à l’espace Shiatsu) ? T’es-tu senti épuisé lors du festival, après, et sais-tu
|
||||||
|
pourquoi ?
|
||||||
|
</label>
|
||||||
|
<div className={styles.preAnswerWrapper}>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question4Ref)}
|
||||||
|
>
|
||||||
|
J’étais en forme tout du long.
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question4Ref)}
|
||||||
|
>
|
||||||
|
Les jours de préparatifs m’ont fatigués.
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question4Ref)}
|
||||||
|
>
|
||||||
|
Il y avait des massages gratuits ?
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<textarea id="question4" ref={question4Ref} placeholder="..." />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{weekDays.length > 0 && (
|
||||||
|
<div className={styles.questionWrapper}>
|
||||||
|
<label htmlFor="question5">
|
||||||
|
{weekDays.length > 1
|
||||||
|
? `Comment se sont passés les ${weekDays.join(", ")} ?`
|
||||||
|
: `Comment s'est passé le ${weekDays.join(", ")} ?`}{" "}
|
||||||
|
As-tu eu assez d’infos, te sentais-tu utile ? Y compris au sein de ton
|
||||||
|
équipe ?
|
||||||
|
</label>
|
||||||
|
<div className={styles.preAnswerWrapper}>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question5Ref)}
|
||||||
|
>
|
||||||
|
Je n’ai pas pu venir.
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question5Ref)}
|
||||||
|
>
|
||||||
|
Je n’ai pas arrêté.
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question5Ref)}
|
||||||
|
>
|
||||||
|
Je manquais d’infos.
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<textarea id="question5" ref={question5Ref} placeholder="..." />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className={styles.questionWrapper}>
|
||||||
|
<label htmlFor="question6">
|
||||||
|
As-tu trouvé ton compte vis-à-vis des raisons qui t'ont poussées à être bénévole
|
||||||
|
(faire découvrir sa passion, se rendre utile, découvrir l’envers du décor,
|
||||||
|
sympathiser, apprendre, simplement kiffer, etc) ?
|
||||||
|
</label>
|
||||||
|
<div className={styles.preAnswerWrapper}>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question6Ref)}
|
||||||
|
>
|
||||||
|
Oui, objectifs atteints.
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question6Ref)}
|
||||||
|
>
|
||||||
|
Je n’avais pas d’attente.
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question6Ref)}
|
||||||
|
>
|
||||||
|
Il m’a manqué __
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<textarea id="question6" ref={question6Ref} placeholder="..." />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.questionWrapper}>
|
||||||
|
<label htmlFor="question7">
|
||||||
|
Si d’autres bénévoles sont partants pour te soutenir, que mettrais-tu en œuvre
|
||||||
|
autrement ou mieux pour la prochaine édition du festival ?
|
||||||
|
</label>
|
||||||
|
<div className={styles.preAnswerWrapper}>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question7Ref)}
|
||||||
|
>
|
||||||
|
Dans l’équipe __ j’aimerais __
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question7Ref)}
|
||||||
|
>
|
||||||
|
B. La réponse B.
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question7Ref)}
|
||||||
|
>
|
||||||
|
Je manque de temps.
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<textarea id="question7" ref={question7Ref} placeholder="..." />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.questionWrapper}>
|
||||||
|
<label htmlFor="question8">
|
||||||
|
Envisages-tu d’être bénévole pour PeL 2023 ? Dans la même équipe, ou tu aurais
|
||||||
|
envie d’en changer ? Libre à toi d’expliquer ou non pourquoi.
|
||||||
|
</label>
|
||||||
|
<div className={styles.preAnswerWrapper}>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question8Ref)}
|
||||||
|
>
|
||||||
|
Oui, si je suis dispo.
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question8Ref)}
|
||||||
|
>
|
||||||
|
Oui, mais dans l’équipe __
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.preAnswerButton}
|
||||||
|
onClick={preAnswer(question8Ref)}
|
||||||
|
>
|
||||||
|
Hélas non.
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<textarea id="question8" ref={question8Ref} placeholder="..." />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.questionWrapper}>
|
||||||
|
<label htmlFor="question9">
|
||||||
|
As-tu un conseil, une remarque, une idée non couverte par les précédentes
|
||||||
|
questions ? Laisse ton imagination déborder ^^
|
||||||
|
</label>
|
||||||
|
<textarea id="question9" ref={question9Ref} placeholder="..." />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.buttonWrapper}>
|
||||||
|
<FormButton onClick={onSubmit}>Enregistrer</FormButton>
|
||||||
|
{children === undefined && (
|
||||||
|
<>
|
||||||
|
{" "}
|
||||||
|
<FormButton onClick={afterSubmit} type="grey">
|
||||||
|
Annuler
|
||||||
|
</FormButton>{" "}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{children !== undefined && (
|
||||||
|
<>
|
||||||
|
{" "}
|
||||||
|
<IgnoreButton onClick={afterSubmit} text="Ignorer pour l'instant">
|
||||||
|
{children}
|
||||||
|
</IgnoreButton>{" "}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
RetexForm.defaultProps = {
|
||||||
|
children: undefined,
|
||||||
|
afterSubmit: undefined,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(RetexForm)
|
||||||
|
|
||||||
|
// Fetch server-side data here
|
||||||
|
export const fetchFor = [fetchRetexSetIfNeed]
|
18
src/components/VolunteerBoard/RetexForm/RetexFormModal.tsx
Normal file
18
src/components/VolunteerBoard/RetexForm/RetexFormModal.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 RetexForm from "./RetexForm"
|
||||||
|
|
||||||
|
const RetexFormModal: FC = (): JSX.Element => {
|
||||||
|
const execHideModal = useAction(hideModal)
|
||||||
|
const afterFormSubmit = useCallback(() => execHideModal(), [execHideModal])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal modalId={MODAL_IDS.RETEX}>
|
||||||
|
<RetexForm afterSubmit={afterFormSubmit} />
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(RetexFormModal)
|
109
src/components/VolunteerBoard/RetexForm/styles.module.scss
Executable file
109
src/components/VolunteerBoard/RetexForm/styles.module.scss
Executable file
@ -0,0 +1,109 @@
|
|||||||
|
@import "../../../theme/variables";
|
||||||
|
@import "../../../theme/mixins";
|
||||||
|
|
||||||
|
.title {
|
||||||
|
padding: 4px;
|
||||||
|
margin: 15px 0;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputWrapper {
|
||||||
|
margin: 25px 0;
|
||||||
|
|
||||||
|
@include desktop {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"] {
|
||||||
|
min-width: 175px;
|
||||||
|
border: 1px solid $color-grey-medium;
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.leftCol {
|
||||||
|
flex: 0 0 240px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rightCol {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brunchTitle {
|
||||||
|
display: inline-block;
|
||||||
|
width: 320px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.invisible {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brunchLabel {
|
||||||
|
text-align: left;
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
width: 280px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brunchPresenceTitle {
|
||||||
|
display: inline-block;
|
||||||
|
width: 320px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brunchPresenceLabel {
|
||||||
|
text-align: left;
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guestCountTitle {
|
||||||
|
display: inline-block;
|
||||||
|
width: 320px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guestCountLabel {
|
||||||
|
text-align: left;
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.questionWrapper {
|
||||||
|
margin: 6px 0 14px;
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
padding: 6px 0 2px 4px;
|
||||||
|
}
|
||||||
|
textarea {
|
||||||
|
width: 100%;
|
||||||
|
height: 75px;
|
||||||
|
padding: 5px;
|
||||||
|
border: 1px solid $color-grey-light;
|
||||||
|
background-color: $color-grey-lighter;
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonWrapper {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preAnswerWrapper {
|
||||||
|
margin-bottom: 3px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preAnswerButton {
|
||||||
|
@include form-button;
|
||||||
|
|
||||||
|
margin-left: 2px;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
@ -110,7 +110,7 @@ const TeamWishesForm: FC<Props> = ({ children, afterSubmit }): JSX.Element | nul
|
|||||||
{children !== undefined && (
|
{children !== undefined && (
|
||||||
<>
|
<>
|
||||||
{" "}
|
{" "}
|
||||||
<IgnoreButton onClick={afterSubmit} text="Ignorer">
|
<IgnoreButton onClick={afterSubmit} text="Ignorer pour l'instant">
|
||||||
{children}
|
{children}
|
||||||
</IgnoreButton>{" "}
|
</IgnoreButton>{" "}
|
||||||
</>
|
</>
|
||||||
|
25
src/components/VolunteerBoard/brunch.utils.ts
Normal file
25
src/components/VolunteerBoard/brunch.utils.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { useCallback } from "react"
|
||||||
|
import { shallowEqual, useSelector } from "react-redux"
|
||||||
|
import useAction from "../../utils/useAction"
|
||||||
|
import { selectUserJwtToken } from "../../store/auth"
|
||||||
|
import { AppState } from "../../store"
|
||||||
|
import { fetchRetexSet } from "../../store/retexSet"
|
||||||
|
import { Retex } from "../../services/retex"
|
||||||
|
|
||||||
|
type SetFunction = (id: Retex["id"], question1: Retex["question1"]) => void
|
||||||
|
|
||||||
|
export const useBrunch = (): [Retex | undefined, SetFunction] => {
|
||||||
|
const save = useAction(fetchRetexSet)
|
||||||
|
const jwtToken = useSelector(selectUserJwtToken)
|
||||||
|
const retex = useSelector((state: AppState) => state.retexSet?.entity, shallowEqual)
|
||||||
|
|
||||||
|
const saveBrunch: SetFunction = useCallback(
|
||||||
|
(id, question1) => {
|
||||||
|
if (!retex) return
|
||||||
|
save(jwtToken, { id, question1 })
|
||||||
|
},
|
||||||
|
[retex, save, jwtToken]
|
||||||
|
)
|
||||||
|
|
||||||
|
return [retex, saveBrunch]
|
||||||
|
}
|
55
src/components/VolunteerBoard/retex.utils.ts
Normal file
55
src/components/VolunteerBoard/retex.utils.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { useCallback } from "react"
|
||||||
|
import { shallowEqual, useSelector } from "react-redux"
|
||||||
|
import useAction from "../../utils/useAction"
|
||||||
|
import { selectUserJwtToken } from "../../store/auth"
|
||||||
|
import { AppState } from "../../store"
|
||||||
|
import { fetchRetexSet } from "../../store/retexSet"
|
||||||
|
import { Retex } from "../../services/retex"
|
||||||
|
|
||||||
|
type SetFunction = (
|
||||||
|
id: Retex["id"],
|
||||||
|
question2: Retex["question2"],
|
||||||
|
question3: Retex["question3"],
|
||||||
|
question4: Retex["question4"],
|
||||||
|
question5: Retex["question5"],
|
||||||
|
question6: Retex["question6"],
|
||||||
|
question7: Retex["question7"],
|
||||||
|
question8: Retex["question8"],
|
||||||
|
question9: Retex["question9"]
|
||||||
|
) => void
|
||||||
|
|
||||||
|
export const useRetex = (): [Retex | undefined, SetFunction] => {
|
||||||
|
const save = useAction(fetchRetexSet)
|
||||||
|
const jwtToken = useSelector(selectUserJwtToken)
|
||||||
|
const retex = useSelector((state: AppState) => state.retexSet?.entity, shallowEqual)
|
||||||
|
|
||||||
|
const saveRetex: SetFunction = useCallback(
|
||||||
|
(
|
||||||
|
id,
|
||||||
|
question2,
|
||||||
|
question3,
|
||||||
|
question4,
|
||||||
|
question5,
|
||||||
|
question6,
|
||||||
|
question7,
|
||||||
|
question8,
|
||||||
|
question9
|
||||||
|
) => {
|
||||||
|
if (!retex) return
|
||||||
|
save(jwtToken, {
|
||||||
|
id,
|
||||||
|
question2,
|
||||||
|
question3,
|
||||||
|
question4,
|
||||||
|
question5,
|
||||||
|
question6,
|
||||||
|
question7,
|
||||||
|
question8,
|
||||||
|
question9,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
[retex, save, jwtToken]
|
||||||
|
)
|
||||||
|
|
||||||
|
return [retex, saveRetex]
|
||||||
|
}
|
@ -20,6 +20,8 @@ export class SheetNames {
|
|||||||
|
|
||||||
Postulants = "Postulants"
|
Postulants = "Postulants"
|
||||||
|
|
||||||
|
Retex = "Retex"
|
||||||
|
|
||||||
Teams = "Equipes"
|
Teams = "Equipes"
|
||||||
|
|
||||||
Volunteers = "Membres"
|
Volunteers = "Membres"
|
||||||
|
59
src/server/gsheets/retex.ts
Normal file
59
src/server/gsheets/retex.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { cloneDeep } from "lodash"
|
||||||
|
|
||||||
|
import ExpressAccessors from "./expressAccessors"
|
||||||
|
import { Retex, RetexWithoutId, translationRetex } from "../../services/retex"
|
||||||
|
|
||||||
|
const expressAccessor = new ExpressAccessors<RetexWithoutId, Retex>(
|
||||||
|
"Retex",
|
||||||
|
new Retex(),
|
||||||
|
translationRetex
|
||||||
|
)
|
||||||
|
|
||||||
|
export const retexSet = expressAccessor.set(async (list, body, id, _roles) => {
|
||||||
|
const receivedRetex = body[0] as Record<keyof Retex, string>
|
||||||
|
if (id !== +receivedRetex.id) {
|
||||||
|
throw Error(`Retex modifié pour un autre member que soit`)
|
||||||
|
}
|
||||||
|
const retex: Retex | undefined = list.find((v) => v.id === +receivedRetex.id)
|
||||||
|
if (!retex) {
|
||||||
|
throw Error(`Il n'y a aucun bénévole avec cet identifiant ${receivedRetex.id}`)
|
||||||
|
}
|
||||||
|
const newRetex: Retex = cloneDeep(retex)
|
||||||
|
|
||||||
|
const parsedPartialRetex = expressAccessor.parseRawPartialElement(receivedRetex)
|
||||||
|
if (parsedPartialRetex === undefined) {
|
||||||
|
throw Error(`Erreur au parsing dans retexSet`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsedPartialRetex.question1 !== undefined)
|
||||||
|
newRetex.question1 = parsedPartialRetex.question1
|
||||||
|
|
||||||
|
if (parsedPartialRetex.question2 !== undefined)
|
||||||
|
newRetex.question2 = parsedPartialRetex.question2
|
||||||
|
|
||||||
|
if (parsedPartialRetex.question3 !== undefined)
|
||||||
|
newRetex.question3 = parsedPartialRetex.question3
|
||||||
|
|
||||||
|
if (parsedPartialRetex.question4 !== undefined)
|
||||||
|
newRetex.question4 = parsedPartialRetex.question4
|
||||||
|
|
||||||
|
if (parsedPartialRetex.question5 !== undefined)
|
||||||
|
newRetex.question5 = parsedPartialRetex.question5
|
||||||
|
|
||||||
|
if (parsedPartialRetex.question6 !== undefined)
|
||||||
|
newRetex.question6 = parsedPartialRetex.question6
|
||||||
|
|
||||||
|
if (parsedPartialRetex.question7 !== undefined)
|
||||||
|
newRetex.question7 = parsedPartialRetex.question7
|
||||||
|
|
||||||
|
if (parsedPartialRetex.question8 !== undefined)
|
||||||
|
newRetex.question8 = parsedPartialRetex.question8
|
||||||
|
|
||||||
|
if (parsedPartialRetex.question9 !== undefined)
|
||||||
|
newRetex.question9 = parsedPartialRetex.question9
|
||||||
|
|
||||||
|
return {
|
||||||
|
toDatabase: newRetex,
|
||||||
|
toCaller: newRetex,
|
||||||
|
}
|
||||||
|
})
|
@ -47,6 +47,7 @@ import checkAccess from "./checkAccess"
|
|||||||
import { hasGSheetsAccess } from "./gsheets/accessors"
|
import { hasGSheetsAccess } from "./gsheets/accessors"
|
||||||
import { addStatus, showStatusAt } from "./status"
|
import { addStatus, showStatusAt } from "./status"
|
||||||
import { miscMeetingDateListGet, miscDiscordInvitation } from "./gsheets/miscs"
|
import { miscMeetingDateListGet, miscDiscordInvitation } from "./gsheets/miscs"
|
||||||
|
import { retexSet } from "./gsheets/retex"
|
||||||
|
|
||||||
checkAccess()
|
checkAccess()
|
||||||
|
|
||||||
@ -108,6 +109,7 @@ app.get("/VolunteerListGet", secure as RequestHandler, volunteerListGet)
|
|||||||
// Secured APIs
|
// Secured APIs
|
||||||
app.get("/AnnouncementListGet", secure as RequestHandler, announcementListGet)
|
app.get("/AnnouncementListGet", secure as RequestHandler, announcementListGet)
|
||||||
app.get("/MiscDiscordInvitationGet", secure as RequestHandler, miscDiscordInvitation)
|
app.get("/MiscDiscordInvitationGet", secure as RequestHandler, miscDiscordInvitation)
|
||||||
|
app.post("/RetexSet", secure as RequestHandler, retexSet)
|
||||||
app.get("/TeamListGet", teamListGet)
|
app.get("/TeamListGet", teamListGet)
|
||||||
app.get("/VolunteerDiscordId", secure as RequestHandler, volunteerDiscordId)
|
app.get("/VolunteerDiscordId", secure as RequestHandler, volunteerDiscordId)
|
||||||
app.post("/VolunteerAsksSet", secure as RequestHandler, volunteerAsksSet)
|
app.post("/VolunteerAsksSet", secure as RequestHandler, volunteerAsksSet)
|
||||||
|
56
src/services/retex.ts
Normal file
56
src/services/retex.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/* eslint-disable max-classes-per-file */
|
||||||
|
export class Retex {
|
||||||
|
id = 0
|
||||||
|
|
||||||
|
dayWishes = ""
|
||||||
|
|
||||||
|
question1 = -1
|
||||||
|
|
||||||
|
question2 = ""
|
||||||
|
|
||||||
|
question3 = ""
|
||||||
|
|
||||||
|
question4 = ""
|
||||||
|
|
||||||
|
question5 = ""
|
||||||
|
|
||||||
|
question6 = ""
|
||||||
|
|
||||||
|
question7 = ""
|
||||||
|
|
||||||
|
question8 = ""
|
||||||
|
|
||||||
|
question9 = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
export const translationRetex: { [k in keyof Retex]: string } = {
|
||||||
|
id: "id",
|
||||||
|
dayWishes: "enviesJours",
|
||||||
|
question1: "question1",
|
||||||
|
question2: "question2",
|
||||||
|
question3: "question3",
|
||||||
|
question4: "question4",
|
||||||
|
question5: "question5",
|
||||||
|
question6: "question6",
|
||||||
|
question7: "question7",
|
||||||
|
question8: "question8",
|
||||||
|
question9: "question9",
|
||||||
|
}
|
||||||
|
|
||||||
|
export const elementName = "Retex"
|
||||||
|
|
||||||
|
export const volunteerExample: Retex = {
|
||||||
|
id: 1,
|
||||||
|
dayWishes: "J,S,D",
|
||||||
|
question1: 1,
|
||||||
|
question2: "Amélie",
|
||||||
|
question3: "sadasdsa",
|
||||||
|
question4: "",
|
||||||
|
question5: "sadasdsa",
|
||||||
|
question6: "",
|
||||||
|
question7: "",
|
||||||
|
question8: "sadasdsa",
|
||||||
|
question9: "sadasdsa",
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RetexWithoutId = Omit<Retex, "id">
|
6
src/services/retexAccessors.ts
Normal file
6
src/services/retexAccessors.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import ServiceAccessors from "./accessors"
|
||||||
|
import { elementName, Retex, RetexWithoutId } from "./retex"
|
||||||
|
|
||||||
|
const serviceAccessors = new ServiceAccessors<RetexWithoutId, Retex>(elementName)
|
||||||
|
|
||||||
|
export const retexSet = serviceAccessors.securedCustomPost<[Partial<Retex>]>("Set")
|
53
src/store/retexSet.ts
Normal file
53
src/store/retexSet.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { PayloadAction, createSlice, createSelector } from "@reduxjs/toolkit"
|
||||||
|
|
||||||
|
import { StateRequest, toastError, elementFetch } from "./utils"
|
||||||
|
import { Retex } from "../services/retex"
|
||||||
|
import { retexSet } from "../services/retexAccessors"
|
||||||
|
import { AppState, AppThunk } from "."
|
||||||
|
|
||||||
|
type StateRetex = { entity?: Retex } & StateRequest
|
||||||
|
|
||||||
|
export const initialState: StateRetex = {
|
||||||
|
readyStatus: "idle",
|
||||||
|
}
|
||||||
|
|
||||||
|
const retexSetSlice = createSlice({
|
||||||
|
name: "retexSet",
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
getRequesting: (_) => ({
|
||||||
|
readyStatus: "request",
|
||||||
|
}),
|
||||||
|
getSuccess: (_, { payload }: PayloadAction<Retex>) => ({
|
||||||
|
readyStatus: "success",
|
||||||
|
entity: payload,
|
||||||
|
}),
|
||||||
|
getFailure: (_, { payload }: PayloadAction<string>) => ({
|
||||||
|
readyStatus: "failure",
|
||||||
|
error: payload,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export default retexSetSlice.reducer
|
||||||
|
export const { getRequesting, getSuccess, getFailure } = retexSetSlice.actions
|
||||||
|
|
||||||
|
export const fetchRetexSet = elementFetch(
|
||||||
|
retexSet,
|
||||||
|
getRequesting,
|
||||||
|
getSuccess,
|
||||||
|
getFailure,
|
||||||
|
(error: Error) => toastError(`Erreur lors de la modification d'un retex: ${error.message}`)
|
||||||
|
)
|
||||||
|
|
||||||
|
export const fetchRetexSetIfNeed =
|
||||||
|
(newPartialRetex?: Partial<Retex>): AppThunk =>
|
||||||
|
(dispatch, getState) => {
|
||||||
|
const { jwt, id } = getState().auth
|
||||||
|
return dispatch(fetchRetexSet(jwt, newPartialRetex || { id }))
|
||||||
|
}
|
||||||
|
|
||||||
|
export const selectRetexSet = createSelector(
|
||||||
|
(state: AppState) => state,
|
||||||
|
(state): Retex | undefined => state.retexSet?.entity
|
||||||
|
)
|
@ -9,6 +9,7 @@ import gameDetailsUpdate from "./gameDetailsUpdate"
|
|||||||
import miscDiscordInvitation from "./miscDiscordInvitation"
|
import miscDiscordInvitation from "./miscDiscordInvitation"
|
||||||
import miscMeetingDateList from "./miscMeetingDateList"
|
import miscMeetingDateList from "./miscMeetingDateList"
|
||||||
import postulantAdd from "./postulantAdd"
|
import postulantAdd from "./postulantAdd"
|
||||||
|
import retexSet from "./retexSet"
|
||||||
import teamList from "./teamList"
|
import teamList from "./teamList"
|
||||||
import ui from "./ui"
|
import ui from "./ui"
|
||||||
import volunteerPartialAdd from "./volunteerPartialAdd"
|
import volunteerPartialAdd from "./volunteerPartialAdd"
|
||||||
@ -41,6 +42,7 @@ export default (history: History) => ({
|
|||||||
miscDiscordInvitation,
|
miscDiscordInvitation,
|
||||||
miscMeetingDateList,
|
miscMeetingDateList,
|
||||||
postulantAdd,
|
postulantAdd,
|
||||||
|
retexSet,
|
||||||
teamList,
|
teamList,
|
||||||
ui,
|
ui,
|
||||||
volunteerPartialAdd,
|
volunteerPartialAdd,
|
||||||
|
@ -27,10 +27,12 @@ const selectUiData = (state: AppState) => state.ui
|
|||||||
export const selectActiveModalId = createSelector(selectUiData, (ui) => ui.modalId)
|
export const selectActiveModalId = createSelector(selectUiData, (ui) => ui.modalId)
|
||||||
|
|
||||||
export const MODAL_IDS = {
|
export const MODAL_IDS = {
|
||||||
|
BRUNCH: "BRUNCH",
|
||||||
DAYWISHES: "DAYWISHES",
|
DAYWISHES: "DAYWISHES",
|
||||||
HOSTING: "HOSTING",
|
HOSTING: "HOSTING",
|
||||||
MEALS: "MEALS",
|
MEALS: "MEALS",
|
||||||
PARTICIPATIONDETAILS: "PARTICIPATIONDETAILS",
|
PARTICIPATIONDETAILS: "PARTICIPATIONDETAILS",
|
||||||
PERSONALINFO: "PERSONALINFO",
|
PERSONALINFO: "PERSONALINFO",
|
||||||
|
RETEX: "RETEX",
|
||||||
TEAMWISHES: "TEAMWISHES",
|
TEAMWISHES: "TEAMWISHES",
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user