Move Board in /profil, change age by adult, split teeshirt into tshirtSize and tshirtCount

This commit is contained in:
pikiou 2022-03-17 14:28:25 +01:00
parent 850d5e9da6
commit ce13e0c8b4
13 changed files with 215 additions and 127 deletions

View File

@ -24,6 +24,7 @@
@include desktop {
@include horizontal-vertical-center();
bottom: auto;
right: auto;
max-height: 80vh;

View File

@ -24,15 +24,15 @@ const MainMenu: FC = (): JSX.Element | null => {
</button>
<ul className={classnames(styles.mainMenu, opened && styles.opened)}>
{/* <li className={styles.mainMenuItem}>
<a href="/">Mon espace</a>
</li> */}
<li className={styles.mainMenuItem}>
<a href="/equipes">Equipes</a>
</li>
<li className={styles.mainMenuItem}>
<a href="/annonces">Annonces</a>
</li>
<li className={styles.mainMenuItem}>
<a href="/profil">Mon profil</a>
</li>
<li className={styles.mainMenuItem}>
<a href="/equipes">Equipes</a>
</li>
<button type="button" className={styles.close} onClick={onClose}>
×
</button>

View File

@ -47,6 +47,8 @@
display: none;
@include mobile {
@include vertical-center();
display: block;
position: absolute;
right: 10px;
@ -55,8 +57,6 @@
text-align: center;
font-size: 22px;
color: $color-black;
@include vertical-center();
}
}

View File

@ -11,9 +11,11 @@ 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="Pour le jour J" />
<DayWishes />
<DayWishesFormModal />

View File

@ -11,8 +11,9 @@ type Props = {
const ParticipationDetails: FC<Props> = (): JSX.Element | null => {
const [participationDetails] = useUserParticipationDetails()
const age = get(participationDetails, "age", "")
const tShirtSize = get(participationDetails, "teeshirtSize", "")
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(
@ -23,15 +24,31 @@ const ParticipationDetails: FC<Props> = (): JSX.Element | null => {
return (
<div className={styles.root}>
<div className={styles.title}>Mes informations pour le festival</div>
{!tShirtSize && <div className={styles.line}>J'ai déjà 2 t-shirts.</div>}
{tShirtSize && (
{tshirtCount === 0 && (
<div className={styles.line}>
J'ai besoin d'un t-shirt ! (Taille <b>{tShirtSize}</b>)
Je n'ai <b>aucun t-shirt</b>. (Taille <b>{tshirtSize}</b>)
</div>
)}
{tshirtCount === 1 && (
<div className={styles.line}>
J'ai déjà <b>1 t-shirt</b>. (Taille <b>{tshirtSize}</b>)
</div>
)}
{tshirtCount === 2 && (
<div className={styles.line}>
J'ai déjà <b>2 t-shirts</b>.
</div>
)}
{adult === 0 && (
<div className={styles.line}>
Je suis <b>mineur</b>
</div>
)}
{adult === 1 && (
<div className={styles.line}>
Je suis <b>majeur</b>
</div>
)}
<div className={styles.line}>
Age : <b>{age || "?"} ans</b>.
</div>
<div className={styles.line}>
Préférence alimentaire : <b>{food || foodDefaultValue}</b>
</div>

View File

@ -4,7 +4,7 @@ import set from "lodash/set"
import styles from "./styles.module.scss"
import {
foodDefaultValue,
tShirtSizes,
tshirtSizes,
useUserParticipationDetails,
} from "../participationDetails.utils"
import FormButton from "../../Form/FormButton/FormButton"
@ -16,85 +16,138 @@ type Props = {
const ParticipationDetailsForm: FC<Props> = ({ afterSubmit }): JSX.Element | null => {
const sizeRef = useRef<HTMLSelectElement | null>(null)
const dietRef = useRef<HTMLInputElement | null>(null)
const ageRef = useRef<HTMLInputElement | null>(null)
const [has2Shirts, setHas2Shirts] = useState<boolean>(true)
const [tshirtCountState, setTshirtCount] = useState<number>(0)
const [adultState, setAdult] = useState<number>(0)
const [participationDetails, saveParticipationDetails] = useUserParticipationDetails()
const onSubmit = useCallback(() => {
const age = get(ageRef, "current.value", "")
const teeshirtSize = has2Shirts ? "" : get(sizeRef, "current.value", "")
const tshirtSize = get(sizeRef, "current.value", "")
const food = get(dietRef, "current.value", "") || foodDefaultValue
saveParticipationDetails({ age, teeshirtSize, food })
saveParticipationDetails({
tshirtSize,
tshirtCount: tshirtCountState,
adult: adultState,
food,
})
if (afterSubmit) afterSubmit()
}, [has2Shirts, saveParticipationDetails, afterSubmit])
}, [tshirtCountState, adultState, saveParticipationDetails, afterSubmit])
const onHas2ShirtsClick = useCallback(
const onTshirtCountChange = useCallback(
(value) => {
setHas2Shirts(value)
setTshirtCount(value)
},
[setHas2Shirts]
[setTshirtCount]
)
const onAdultChange = useCallback(
(value) => {
setAdult(value)
},
[setAdult]
)
useEffect(() => {
const age = get(participationDetails, "age", "")
const teeshirtSize = get(participationDetails, "teeshirtSize", "")
const tshirtSize = get(participationDetails, "tshirtSize", "")
const tshirtCount = get(participationDetails, "tshirtCount", "")
const adult = get(participationDetails, "adult", "")
const food = get(participationDetails, "food", "")
if (age) set(ageRef, "current.value", age)
if (teeshirtSize) set(sizeRef, "current.value", teeshirtSize)
setHas2Shirts(!teeshirtSize)
if (tshirtSize) set(sizeRef, "current.value", tshirtSize)
if (tshirtCount) setTshirtCount(tshirtCount)
if (adult) setAdult(adult)
if (food) set(dietRef, "current.value", food)
}, [setHas2Shirts, participationDetails])
}, [setTshirtCount, setAdult, participationDetails])
return (
<div className={styles.root}>
<div>
<div className={styles.title}>Mes informations pour le festival</div>
<div className={styles.tShirtWrapper}>
<div className={styles.tShirtLabel}>J'ai déjà 2 t-shirts</div>
<label>
<input
type="radio"
name="hasShirt"
onChange={() => onHas2ShirtsClick(true)}
checked={has2Shirts}
/>{" "}
Oui
</label>
<label>
<input
type="radio"
name="hasShirt"
onChange={() => onHas2ShirtsClick(false)}
checked={!has2Shirts}
/>{" "}
Non
</label>
{has2Shirts === false && (
<div className={styles.tShirtSizes}>
<label>Taille</label>
<select ref={sizeRef}>
{tShirtSizes.map((size) => (
<option key={size} value={size}>
{size}
</option>
))}
</select>
</div>
)}
<div className={styles.inputWrapper}>
<div className={styles.leftCol}>
<div className={styles.tshirtCountTitle}>Combien as-tu de t-shirts PeL ?</div>
</div>
<div>
<label className={styles.tshirtCountLabel}>
<input
type="radio"
name="tshirtCount"
onChange={() => onTshirtCountChange(0)}
checked={tshirtCountState === 0}
/>{" "}
0
</label>
<label className={styles.tshirtCountLabel}>
<input
type="radio"
name="tshirtCount"
onChange={() => onTshirtCountChange(1)}
checked={tshirtCountState === 1}
/>{" "}
1
</label>
<label className={styles.tshirtCountLabel}>
<input
type="radio"
name="tshirtCount"
onChange={() => onTshirtCountChange(2)}
checked={tshirtCountState === 2}
/>{" "}
2 ou plus
</label>
</div>
</div>
<div className={styles.inputWrapper}>
<label htmlFor="ddday-age">Age</label>
<input type="number" id="ddday-age" ref={ageRef} />
<div className={styles.leftCol}>
<div className={styles.tshirtSizesTitle}>Taille</div>
</div>
<div>
<select ref={sizeRef} className={styles.tshirtCountSelect}>
{tshirtSizes.map((size) => (
<option key={size} value={size}>
{size}
</option>
))}
</select>
</div>
</div>
<div className={styles.inputWrapper}>
<div className={styles.leftCol}>
<div className={styles.adultTitle}>Le 2 juillet 2022 tu auras :</div>
</div>
<div>
<label className={styles.adultLabel}>
<input
type="radio"
name="majority"
onChange={() => onAdultChange(0)}
checked={adultState === 0}
/>{" "}
17 ou moins
</label>
<label className={styles.adultLabel}>
<input
type="radio"
name="majority"
onChange={() => onAdultChange(1)}
checked={adultState === 1}
/>{" "}
18 ans ou plus
</label>
</div>
</div>
<div className={styles.inputWrapper}>
<label htmlFor="dday-diet">Préférence alimentaire</label>
<input
id="dday-diet"
type="text"
ref={dietRef}
placeholder="végétarien ? halal ? ..."
/>
<div className={styles.leftCol}>
<label 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>
<div className={styles.buttonWrapper}>
<FormButton onClick={onSubmit}>Enregistrer</FormButton>

View File

@ -1,10 +1,6 @@
@import "../../../theme/variables";
@import "../../../theme/mixins";
.root {
width: 470px;
}
.title {
padding: 4px;
font-weight: bold;
@ -14,46 +10,61 @@
.inputWrapper {
margin: 10px 0;
@include desktop {
display: flex;
}
label {
display: inline-block;
display: block;
width: 170px;
}
input {
width: 300px;
input[type="text"] {
min-width: 175px;
border: 1px solid $color-grey-medium;
outline: 0;
}
}
.tShirtWrapper {
.leftCol {
flex: 0 0 240px;
}
.tshirtWrapper {
margin: 10px 0;
height: 28px;
label {
display: inline-block;
width: 55px;
}
}
.tShirtLabel {
.tshirtCountTitle {
display: inline-block;
margin-top: 6px;
width: 170px;
width: 240px;
}
.tShirtSizes {
display: inline-block;
width: 190px;
text-align: right;
.tshirtCountLabel {
width: 55px;
}
select {
margin-left: 10px;
width: 120px;
border: 1px solid $color-grey-medium;
border-radius: 4px;
background-color: $color-white;
outline: 0;
}
.tshirtSizesTitle {
display: inline-block;
width: 240px;
}
.tshirtCountSelect {
width: 120px;
border: 1px solid $color-grey-medium;
border-radius: 4px;
background-color: $color-white;
outline: 0;
}
.adultTitle {
display: inline-block;
margin-top: 6px;
width: 240px;
}
.adultLabel {
width: 55px;
}
.buttonWrapper {

View File

@ -42,6 +42,7 @@
.teamList {
@include clear-ul-style;
display: flex;
flex-wrap: wrap;
flex-direction: row;

View File

@ -5,7 +5,7 @@ import { selectUserJwtToken } from "../../store/auth"
import { AppState } from "../../store"
import { fetchVolunteerParticipationDetailsSet } from "../../store/volunteerParticipationDetailsSet"
export const tShirtSizes = [
export const tshirtSizes = [
"XS",
"S",
"M",
@ -29,12 +29,13 @@ export const useUserParticipationDetails = (): [any, any] => {
)
const saveParticipationDetails = useCallback(
({ age, teeshirtSize, food }) => {
({ tshirtSize, tshirtCount, adult, food }) => {
if (!userParticipationDetails) return
save(jwtToken, 0, {
id: userParticipationDetails.id,
age,
teeshirtSize,
tshirtSize,
tshirtCount,
adult,
food,
})
},

View File

@ -6,26 +6,21 @@ import { Helmet } from "react-helmet"
import { AppThunk } from "../../store"
import { LoginForm, Notifications, fetchForBoardForms } from "../../components"
import styles from "./styles.module.scss"
import { fetchVolunteerNotifsSetIfNeed, hasWaitingNotifs } from "../../store/volunteerNotifsSet"
import { fetchVolunteerNotifsSetIfNeed } from "../../store/volunteerNotifsSet"
import { selectUserJwtToken } from "../../store/auth"
import Board from "../../components/VolunteerBoard/Board"
import Page from "../../components/ui/Page/Page"
import VolunteerConfirmation from "../../components/VolunteerConfirmation/VolunteerConfirmation"
export type Props = RouteComponentProps
const HomePage: FC<Props> = (): JSX.Element => {
const jwtToken = useSelector(selectUserJwtToken)
const waitingNotifs = useSelector(hasWaitingNotifs)
if (jwtToken === undefined) return <p>Loading...</p>
if (jwtToken) {
return (
<Page>
{!waitingNotifs && <VolunteerConfirmation />}
<Notifications />
{!waitingNotifs && <Board />}
</Page>
)
}

View File

@ -57,7 +57,7 @@ export default [
loadData: loadWishData,
},
{
path: "/board",
path: "/profil",
component: AsyncBoard,
loadData: loadBoardData,
},

View File

@ -206,7 +206,9 @@ export const volunteerDayWishesSet = expressAccessor.set(async (list, body, id)
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 d'age, taille et alimentation`)
throw Error(
`On ne peut acceder qu'à ses propres infos de t-shirt, de majorité et d'alimentation`
)
}
const wishes = body[1] as VolunteerParticipationDetails
const volunteer = list.find((v) => v.id === requestedId)
@ -215,11 +217,14 @@ export const volunteerParticipationDetailsSet = expressAccessor.set(async (list,
}
const newVolunteer = _.cloneDeep(volunteer)
if (wishes.age !== undefined) {
newVolunteer.age = wishes.age
if (wishes.tshirtSize !== undefined) {
newVolunteer.tshirtSize = wishes.tshirtSize
}
if (wishes.teeshirtSize !== undefined) {
newVolunteer.teeshirtSize = wishes.teeshirtSize
if (wishes.tshirtCount !== undefined) {
newVolunteer.tshirtCount = wishes.tshirtCount
}
if (wishes.adult !== undefined) {
newVolunteer.adult = wishes.adult
}
if (wishes.food !== undefined) {
newVolunteer.food = wishes.food
@ -229,8 +234,9 @@ export const volunteerParticipationDetailsSet = expressAccessor.set(async (list,
toDatabase: newVolunteer,
toCaller: {
id: newVolunteer.id,
age: newVolunteer.age,
teeshirtSize: newVolunteer.teeshirtSize,
tshirtSize: newVolunteer.tshirtSize,
tshirtCount: newVolunteer.tshirtCount,
adult: newVolunteer.adult,
food: newVolunteer.food,
} as VolunteerParticipationDetails,
}

View File

@ -23,9 +23,9 @@ export class Volunteer {
dayWishesComment = ""
age = 0
tshirtCount = ""
teeshirtSize = ""
tshirtSize = ""
food = ""
@ -59,8 +59,8 @@ export const translationVolunteer: { [k in keyof Volunteer]: string } = {
discordId: "discordId",
dayWishes: "enviesJours",
dayWishesComment: "commentaireEnviesJours",
age: "age",
teeshirtSize: "teeshirt",
tshirtCount: "nbDeTshirts",
tshirtSize: "tailleDeTshirts",
food: "alimentation",
teamWishes: "enviesEquipe",
teamWishesComment: "commentaireEnviesEquipe",
@ -87,8 +87,8 @@ export const volunteerExample: Volunteer = {
discordId: "",
dayWishes: [],
dayWishesComment: "",
age: 33,
teeshirtSize: "FM",
tshirtCount: "1",
tshirtSize: "Femme M",
food: "Végétarien",
teamWishes: [],
teamWishesComment: "",
@ -140,7 +140,8 @@ export interface VolunteerDayWishes {
export interface VolunteerParticipationDetails {
id: Volunteer["id"]
age: Volunteer["age"]
teeshirtSize: Volunteer["teeshirtSize"]
tshirtSize: Volunteer["tshirtSize"]
tshirtCount: Volunteer["tshirtCount"]
adult: Volunteer["adult"]
food: Volunteer["food"]
}