Add participation to /profil and various improvements

This commit is contained in:
pikiou 2022-03-18 04:05:17 +01:00
parent 60b7824011
commit f65963d91c
23 changed files with 282 additions and 117 deletions

View File

@ -2,17 +2,23 @@ import { FC, ReactNode } from "react"
import styles from "./styles.module.scss"
type Props = {
type?: "grey"
children: ReactNode
onClick?: () => void | undefined
onClick?: () => void
}
const FormButton: FC<Props> = ({ children, onClick }): JSX.Element => (
<button type="button" className={styles.button} onClick={onClick}>
const FormButton: FC<Props> = ({ type, children, onClick }): JSX.Element => (
<button
type="button"
className={type === "grey" ? styles.greyButton : styles.button}
onClick={onClick}
>
{children}
</button>
)
FormButton.defaultProps = {
type: undefined,
onClick: undefined,
}

View File

@ -3,3 +3,6 @@
.button {
@include form-button;
}
.greyButton {
@include form-grey-button;
}

View File

@ -94,7 +94,7 @@ const Notifications = (): JSX.Element | null => {
<input
type="radio"
value="oui"
name="gender"
name="participation"
checked={participation === "oui"}
onChange={onChangeValue2}
/>{" "}
@ -104,7 +104,7 @@ const Notifications = (): JSX.Element | null => {
<input
type="radio"
value="non"
name="gender"
name="participation"
checked={participation === "non"}
onChange={onChangeValue2}
/>{" "}
@ -114,7 +114,7 @@ const Notifications = (): JSX.Element | null => {
<input
type="radio"
value="peut-etre"
name="gender"
name="participation"
checked={participation === "peut-etre"}
onChange={onChangeValue2}
/>{" "}

View File

@ -11,11 +11,9 @@ import { fetchVolunteerParticipationDetailsSetIfNeed } from "../../store/volunte
import { fetchTeamListIfNeed } from "../../store/teamList"
import { fetchVolunteerTeamWishesSetIfNeed } from "../../store/volunteerTeamWishesSet"
import ContentTitle from "../ui/Content/ContentTitle"
import VolunteerConfirmation from "../VolunteerConfirmation/VolunteerConfirmation"
const Board: FC = (): JSX.Element => (
<>
<VolunteerConfirmation />
<ContentTitle title="Profil spécifique au festival" />
<DayWishes />
<DayWishesFormModal />

View File

@ -7,6 +7,7 @@ import { displayModal, MODAL_IDS } from "../../../store/ui"
const DayWishes: FC = (): JSX.Element | null => {
const [userWishes] = useUserDayWishes()
const participation = get(userWishes, "active", "inconnu")
const dayWishesString = get(userWishes, "dayWishes", []).map(getDayLabel).join(", ")
const comment = get(userWishes, "dayWishesComment", "")
const execDisplayModal = useAction(displayModal)
@ -15,11 +16,34 @@ const DayWishes: FC = (): JSX.Element | null => {
return (
<div className={styles.dayWishes}>
<div className={styles.title}>Mes présences</div>
<div className={styles.daysLine}>
<span className={styles.dayLineTitle}>Mes jours :</span>
{dayWishesString && <b>{dayWishesString}</b>}
{!dayWishesString && <span className={styles.dayLineEmpty}>Non renseignés</span>}
</div>
{participation === "non" && (
<div className={styles.participationLabel}>
Je <b>ne participerai pas</b> à PeL 2022 :(
</div>
)}
{participation === "oui" && (
<div className={styles.participationLabel}>
Je <b className={styles.yesParticipation}>participerai</b> à PeL 2022 !
</div>
)}
{participation === "peut-etre" && (
<div className={styles.participationLabel}>
Je <b>ne sais pas encore</b> si je participerai à PeL 2022
</div>
)}
{participation === "inconnu" && (
<div className={styles.lineEmpty}>Participation à PeL 2022 non renseignée</div>
)}
{participation !== "non" && (
<div className={styles.daysLine}>
<span className={styles.dayLineTitle}>Mes jours :</span>
{dayWishesString && <b>{dayWishesString}</b>}
{!dayWishesString && (
<span className={styles.dayLineEmpty}>Non renseignés</span>
)}
</div>
)}
{comment && (
<div className={styles.commentLine}>
<span className={styles.commentLineTitle}>Mon commentaire :</span>

View File

@ -2,10 +2,19 @@
@import "../../../theme/mixins";
.title {
padding-bottom: 5px;
padding-bottom: 10px;
font-weight: bold;
}
.participationLabel {
margin-right: 5px;
font-style: bold;
}
.yesParticipation {
color: $color-orange;
}
.dayWishes {
@include inner-content-wrapper();
@ -13,8 +22,10 @@
padding-right: 90px;
}
.participationLabel,
.daysLine,
.commentLine {
margin-bottom: 5px;
span {
display: inline-block;
}
@ -24,7 +35,8 @@
padding-right: 5px;
}
.dayLineEmpty {
.lineEmpty {
margin: 0 5px 5px 0;
color: $color-red;
font-style: italic;
}

View File

@ -16,12 +16,17 @@ type Props = {
}
const DayWishesForm: FC<Props> = ({ afterSubmit }): JSX.Element => {
const [participationState, setParticipation] = useState("inconnu")
const [selection, setSelection] = useState(daysChoiceSelectionDefaultState)
const commentRef = useRef<HTMLTextAreaElement | null>(null)
const [userWishes, saveWishes] = useUserDayWishes()
const onParticipationChange = (e: React.ChangeEvent<HTMLInputElement>) =>
setParticipation(e.target.value)
useEffect(() => {
if (!userWishes) return
const participation = get(userWishes, "active", "inconnu")
const newSelection = get(userWishes, "dayWishes", []).reduce(
(acc: selectionChoices, day: string) => ({
...acc,
@ -29,9 +34,10 @@ const DayWishesForm: FC<Props> = ({ afterSubmit }): JSX.Element => {
}),
daysChoice
)
setParticipation(participation)
setSelection(newSelection)
set(commentRef, "current.value", get(userWishes, "dayWishesComment", ""))
}, [setSelection, commentRef, userWishes])
}, [setParticipation, setSelection, commentRef, userWishes])
const onChoiceClick = useCallback(
(id) => {
@ -45,35 +51,105 @@ const DayWishesForm: FC<Props> = ({ afterSubmit }): JSX.Element => {
const onChoiceSubmit = useCallback(() => {
const comment = get(commentRef, "current.value", "")
const days = daysChoice.map(({ id }) => id).filter((id) => selection[id])
saveWishes(days, comment)
saveWishes(participationState, days, comment)
if (afterSubmit) afterSubmit()
}, [selection, commentRef, saveWishes, afterSubmit])
}, [participationState, selection, commentRef, saveWishes, afterSubmit])
return (
<div>
<div className={styles.dayWishesTitle}>Mes jours de présence</div>
<ul className={styles.dayWishesList}>
{daysChoice.map(({ id, label }) => (
<li key={id} className={styles.dayWishesItem}>
<button
type="button"
onClick={() => onChoiceClick(id)}
className={classnames(
styles.dayWishesButton,
selection[id] && styles.active
)}
>
{label}
</button>
</li>
))}
</ul>
<div className={styles.title}>Mes jours de présence</div>
<div className={classnames(styles.inputWrapper, styles.noBottomMargin)}>
<div className={styles.leftCol}>
<div className={styles.participationTitle}>
Si les conditions sanitaires te le permettent, souhaites-tu être bénévole à
PeL 2022 ?
</div>
</div>
<div className={styles.rightCol}>
<label className={styles.participationLabel}>
<input
type="radio"
value="oui"
name="participation"
onChange={onParticipationChange}
checked={participationState === "oui"}
/>{" "}
Oui
</label>
<label className={styles.participationLabel}>
<input
type="radio"
value="non"
name="participation"
onChange={onParticipationChange}
checked={participationState === "non"}
/>{" "}
Non
</label>
<label className={styles.participationLabel}>
<input
type="radio"
value="peut-etre"
name="participation"
onChange={onParticipationChange}
checked={participationState === "peut-etre"}
/>{" "}
Je ne sais pas encore
</label>
</div>
</div>
{participationState === "peut-etre" ? (
<div>
On te le reproposera dans quelques temps.
<br />
Si tu as besoin d&apos;infos, viens nous en parler sur le serveur Discord ! Pour
le rejoindre,{" "}
<a
href="https://discord.com/invite/eXhjKxSBB4"
target="_blank"
rel="noreferrer"
>
clique ici{" "}
</a>
.
</div>
) : null}
<div className={styles.inputWrapper}>
<div className={styles.leftCol}>
<div className={styles.dayWishesTitle}>
Quels jours viendras-tu ?<br />
(Minimum 2 jours dont l'un sera samedi ou dimanche, idéalement samedi{" "}
<b>et</b> dimanche ^^)
</div>
</div>
<div className={styles.rightCol}>
<ul className={styles.dayWishesList}>
{daysChoice.map(({ id, label }) => (
<li key={id} className={styles.dayWishesItem}>
<button
type="button"
onClick={() => onChoiceClick(id)}
className={classnames(
styles.dayWishesButton,
selection[id] && styles.active
)}
>
{label}
</button>
</li>
))}
</ul>
</div>
</div>
<div className={styles.dayWishCommentWrapper}>
<label htmlFor="day-choice-comment">Un commentaire, une précision ?</label>
<textarea id="day-choice-comment" ref={commentRef} />
</div>
<div className={styles.dayWishesButtonWrapper}>
<FormButton onClick={onChoiceSubmit}>Enregistrer</FormButton>
<FormButton onClick={onChoiceSubmit}>Enregistrer</FormButton>{" "}
<FormButton onClick={afterSubmit} type="grey">
Annuler
</FormButton>
</div>
</div>
)

View File

@ -1,26 +1,67 @@
@import "../../../theme/variables";
@import "../../../theme/mixins";
.dayWishesTitle {
.title {
padding: 15px 0;
font-weight: bold;
text-align: center;
}
.inputWrapper {
margin: 25px 0;
@include desktop {
display: flex;
}
}
.noBottomMargin {
margin-bottom: 0;
}
.leftCol {
flex: 0 0 320px;
}
.rightCol {
text-align: center;
}
.participationTitle {
display: inline-block;
width: 320px;
margin-bottom: 10px;
}
.participationLabel {
text-align: left;
display: inline-block;
margin-bottom: 10px;
width: 180px;
}
.dayWishesTitle {
display: inline-block;
width: 320px;
margin-bottom: 10px;
}
.dayWishesList {
@include clear-ul-style;
display: inline-block;
width: 204px;
text-align: center;
}
.dayWishesItem {
display: inline-block;
margin: 2px;
margin: 3px;
}
.dayWishesButton {
margin: 0;
padding: 5px 0 4px;
padding: 7px 2px 6px;
border: 0;
border-radius: 0;
width: 90px;
@ -36,7 +77,7 @@
}
.dayWishCommentWrapper {
margin: 6px 0;
margin: 6px 0 14px;
label {
display: block;

View File

@ -26,27 +26,27 @@ const ParticipationDetails: FC<Props> = (): JSX.Element | null => {
<div className={styles.title}>Mes infos logistiques</div>
{tshirtCount === 0 && (
<div className={styles.line}>
Je n'ai <b>aucun t-shirt</b> et je suis taillé <b>{tshirtSize}</b>
Je n'ai <b>aucun t-shirt</b> et je suis taillé·e <b>{tshirtSize}</b>
</div>
)}
{tshirtCount === 1 && (
<div className={styles.line}>
J'ai déjà <b>1 t-shirt</b> et je suis taillé <b>{tshirtSize}</b>
J'ai <b>un seul t-shirt</b> et je suis taillé·e <b>{tshirtSize}</b>
</div>
)}
{tshirtCount === 2 && (
<div className={styles.line}>
J'ai déjà <b>2 t-shirts</b>
J'ai au moins <b>deux t-shirts</b>
</div>
)}
{adult === 0 && (
<div className={styles.line}>
Je serai <b>mineur</b> les 2-3 juillet 2022
Le 2 juillet 2022, je serai <b>mineur·e</b>
</div>
)}
{adult === 1 && (
<div className={styles.line}>
Je serai <b>majeur</b> les 2-3 juillet 2022
Le 2 juillet 2022, je serai <b>majeur·e</b>
</div>
)}
<div className={styles.line}>

View File

@ -9,12 +9,12 @@
}
.title {
padding-bottom: 5px;
padding-bottom: 10px;
font-weight: bold;
}
.line {
margin: 2px 0;
margin-bottom: 5px;
}
.editButton {

View File

@ -15,7 +15,7 @@ type Props = {
const ParticipationDetailsForm: FC<Props> = ({ afterSubmit }): JSX.Element | null => {
const sizeRef = useRef<HTMLSelectElement | null>(null)
const dietRef = useRef<HTMLInputElement | null>(null)
const dietRef = useRef<HTMLTextAreaElement | null>(null)
const [tshirtCountState, setTshirtCount] = useState<number>(0)
const [adultState, setAdult] = useState<number>(0)
@ -66,7 +66,7 @@ const ParticipationDetailsForm: FC<Props> = ({ afterSubmit }): JSX.Element | nul
<div className={styles.leftCol}>
<div className={styles.tshirtCountTitle}>Combien as-tu de t-shirts PeL ?</div>
</div>
<div>
<div className={styles.rightCol}>
<label className={styles.tshirtCountLabel}>
<input
type="radio"
@ -74,7 +74,7 @@ const ParticipationDetailsForm: FC<Props> = ({ afterSubmit }): JSX.Element | nul
onChange={() => onTshirtCountChange(0)}
checked={tshirtCountState === 0}
/>{" "}
0
Aucun
</label>
<label className={styles.tshirtCountLabel}>
<input
@ -83,7 +83,7 @@ const ParticipationDetailsForm: FC<Props> = ({ afterSubmit }): JSX.Element | nul
onChange={() => onTshirtCountChange(1)}
checked={tshirtCountState === 1}
/>{" "}
1
Un seul
</label>
<label className={styles.tshirtCountLabel}>
<input
@ -92,17 +92,17 @@ const ParticipationDetailsForm: FC<Props> = ({ afterSubmit }): JSX.Element | nul
onChange={() => onTshirtCountChange(2)}
checked={tshirtCountState === 2}
/>{" "}
2 ou plus
Au moins deux
</label>
</div>
</div>
<div className={styles.inputWrapper}>
<div className={styles.leftCol}>
<label htmlFor="tshirtSize" className={styles.tshirtSizesTitle}>
Taille
Quelle est ta taille de t-shirt ?
</label>
</div>
<div>
<div className={styles.rightCol}>
<select id="tshirtSize" ref={sizeRef} className={styles.tshirtCountSelect}>
{tshirtSizes.map((size) => (
<option key={size} value={size}>
@ -115,9 +115,9 @@ const ParticipationDetailsForm: FC<Props> = ({ afterSubmit }): JSX.Element | nul
<div className={styles.inputWrapper}>
<div className={styles.leftCol}>
<div className={styles.adultTitle}>Le 2 juillet 2022 tu auras :</div>
<div className={styles.adultTitle}>Seras-tu majeur·e au 2 juillet 2022 ?</div>
</div>
<div>
<div className={styles.rightCol}>
<label className={styles.adultLabel}>
<input
type="radio"
@ -125,7 +125,7 @@ const ParticipationDetailsForm: FC<Props> = ({ afterSubmit }): JSX.Element | nul
onChange={() => onAdultChange(0)}
checked={adultState === 0}
/>{" "}
17 ou moins
Non, je serai mineur·e
</label>
<label className={styles.adultLabel}>
<input
@ -134,27 +134,19 @@ const ParticipationDetailsForm: FC<Props> = ({ afterSubmit }): JSX.Element | nul
onChange={() => onAdultChange(1)}
checked={adultState === 1}
/>{" "}
18 ans ou plus
Oui, je serai majeur·e
</label>
</div>
</div>
<div className={styles.inputWrapper}>
<div className={styles.leftCol}>
<label className={styles.foodTitle} htmlFor="dday-diet">
Préférence alimentaire
</label>
</div>
<div>
<input
id="dday-diet"
type="text"
ref={dietRef}
placeholder="végétarien ? halal ? ..."
/>
</div>
<div className={styles.dietWrapper}>
<label htmlFor="diet">Préférence alimentaire ?</label>
<textarea id="diet" ref={dietRef} placeholder="végétarien ? halal ? ..." />
</div>
<div className={styles.buttonWrapper}>
<FormButton onClick={onSubmit}>Enregistrer</FormButton>
<FormButton onClick={onSubmit}>Enregistrer</FormButton>{" "}
<FormButton onClick={afterSubmit} type="grey">
Annuler
</FormButton>
</div>
</div>
)

View File

@ -15,10 +15,6 @@
display: flex;
}
label {
display: block;
width: 170px;
}
input[type="text"] {
min-width: 175px;
border: 1px solid $color-grey-medium;
@ -30,41 +26,40 @@
flex: 0 0 240px;
}
.tshirtCountTitle {
.rightCol {
text-align: center;
}
.tshirtCountTitle,
.tshirtSizesTitle,
.adultTitle {
display: inline-block;
width: 240px;
width: 280px;
margin-bottom: 10px;
}
.tshirtCountLabel {
margin-bottom: 10px;
width: 55px;
}
.tshirtSizesTitle {
text-align: left;
display: inline-block;
width: 240px;
margin-bottom: 10px;
width: 180px;
}
.tshirtCountSelect {
width: 120px;
margin-bottom: 10px;
margin-right: 60px;
border: 1px solid $color-grey-medium;
border-radius: 4px;
background-color: $color-white;
outline: 0;
}
.adultTitle {
display: inline-block;
width: 240px;
margin-bottom: 10px;
}
.adultLabel {
text-align: left;
display: inline-block;
margin-bottom: 10px;
width: 55px;
width: 180px;
}
.buttonWrapper {
@ -72,6 +67,19 @@
text-align: center;
}
.foodTitle {
margin-bottom: 10px;
.dietWrapper {
margin: 6px 0 14px;
label {
display: block;
padding: 6px 0 2px 4px;
}
textarea {
width: 100%;
height: 50px;
padding: 5px;
border: 1px solid $color-grey-light;
background-color: $color-grey-lighter;
outline: 0;
}
}

View File

@ -32,9 +32,9 @@ const TeamWishes: FC<Props> = (): JSX.Element | null => {
<div className={styles.root}>
<div className={styles.title}>Mon choix d'équipe</div>
{teamWishesString && (
<span>
<div className={styles.line}>
Mes équipes préférées : <b>{teamWishesString}</b>
</span>
</div>
)}
{!teamWishesString && <span className={styles.lineEmpty}>Non renseignés</span>}
{comment && (

View File

@ -9,12 +9,12 @@
}
.title {
padding-bottom: 5px;
padding-bottom: 10px;
font-weight: bold;
}
.line {
margin: 2px 0;
margin-bottom: 5px;
}
.lineEmpty {
@ -23,6 +23,7 @@
}
.commentLine {
margin-bottom: 5px;
span {
display: inline-block;
}

View File

@ -96,7 +96,10 @@ const TeamWishesForm: FC<Props> = ({ afterSubmit }): JSX.Element | null => {
</div>
</div>
<div className={styles.buttonWrapper}>
<FormButton onClick={onSubmit}>Enregistrer</FormButton>
<FormButton onClick={onSubmit}>Enregistrer</FormButton>{" "}
<FormButton onClick={afterSubmit} type="grey">
Annuler
</FormButton>
</div>
</div>
)

View File

@ -30,10 +30,11 @@ export const useUserDayWishes = (): [any, any] => {
)
const saveWishes = useCallback(
(days, comment) => {
(active, days, comment) => {
if (!userWishes) return
save(jwtToken, 0, {
id: userWishes.id,
active,
dayWishes: days,
dayWishesComment: comment,
})

View File

@ -1,8 +0,0 @@
import { FC, memo } from "react"
import styles from "./styles.module.scss"
const VolunteerConfirmation: FC = (): JSX.Element => (
<div className={styles.root}>&#10003; Tu es bénévole pour le festival de 2022. Merci !</div>
)
export default memo(VolunteerConfirmation)

View File

@ -1,7 +0,0 @@
@import "../../theme/variables";
.root {
margin-bottom: 10px;
text-align: center;
color: $color-green;
}

View File

@ -1,7 +1,7 @@
@import "../../../theme/mixins";
.title {
margin: 30px 10px 0;
margin: 15px 10px;
padding: 0;
font-weight: 600;
font-size: 1.1em;

View File

@ -186,6 +186,9 @@ export const volunteerDayWishesSet = expressAccessor.set(async (list, body, id)
}
const newVolunteer = _.cloneDeep(volunteer)
if (wishes.active !== undefined) {
newVolunteer.active = wishes.active
}
if (wishes.dayWishes !== undefined) {
newVolunteer.dayWishes = wishes.dayWishes
}
@ -197,6 +200,7 @@ export const volunteerDayWishesSet = expressAccessor.set(async (list, body, id)
toDatabase: newVolunteer,
toCaller: {
id: newVolunteer.id,
active: newVolunteer.active,
dayWishes: newVolunteer.dayWishes,
dayWishesComment: newVolunteer.dayWishesComment,
} as VolunteerDayWishes,

View File

@ -15,7 +15,7 @@ export class Volunteer {
roles: string[] = []
active = ""
active = "inconnu"
discordId = ""
@ -134,6 +134,7 @@ export interface VolunteerTeamWishes {
export interface VolunteerDayWishes {
id: Volunteer["id"]
active: Volunteer["active"]
dayWishes: Volunteer["dayWishes"]
dayWishesComment: Volunteer["dayWishesComment"]
}

View File

@ -98,3 +98,12 @@
border-radius: 16px;
font-weight: bold;
}
@mixin form-grey-button {
padding: 7px 20px;
background-color: $color-grey-medium;
border: 0;
color: $color-white;
border-radius: 16px;
font-weight: bold;
}

View File

@ -1,6 +1,7 @@
$color-white: #fff;
$color-black: #000;
$color-red: #f00;
$color-blue: rgb(43, 61, 223);
$color-orange: #ea4d0a;
$color-yellow: #fdd137;
$color-grey-dark: #555;