From 7fc3ec08ba884091f5e19794a27cdc3523eb7075 Mon Sep 17 00:00:00 2001
From: pikiou
Date: Thu, 17 Mar 2022 00:22:34 +0100
Subject: [PATCH 1/5] =?UTF-8?q?Add=20register=20form,=20missing=20proper?=
=?UTF-8?q?=20feedback=20on=20error=20or=20success=C2=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../index.tsx | 120 +++++++++++++-----
.../styles.module.scss | 0
src/components/index.ts | 4 +-
src/pages/PreRegister/PreRegister.tsx | 48 -------
src/pages/Register/Register.tsx | 27 ++++
src/pages/{PreRegister => Register}/index.tsx | 6 +-
.../styles.module.scss | 4 +-
src/routes/index.ts | 10 +-
src/server/gsheets/accessors.ts | 4 +-
src/server/gsheets/expressAccessors.ts | 40 +++++-
src/server/gsheets/localDb.ts | 12 +-
src/server/gsheets/postulants.ts | 44 +++++++
src/server/gsheets/preVolunteers.ts | 19 ---
src/server/gsheets/volunteers.ts | 37 +++++-
src/server/index.ts | 19 +--
.../{preVolunteers.ts => postulants.ts} | 12 +-
src/services/postulantsAccessors.ts | 9 ++
src/services/preVolunteersAccessors.ts | 10 --
src/services/volunteers.ts | 23 +++-
src/services/volunteersAccessors.ts | 2 +-
src/store/postulantAdd.ts | 39 ++++++
src/store/preVolunteerAdd.ts | 39 ------
src/store/preVolunteerCount.ts | 46 -------
src/store/rootReducer.ts | 8 +-
src/store/utils.ts | 10 +-
...volunteerAdd.ts => volunteerPartialAdd.ts} | 18 +--
26 files changed, 350 insertions(+), 260 deletions(-)
rename src/components/{PreRegisterForm => RegisterForm}/index.tsx (68%)
rename src/components/{PreRegisterForm => RegisterForm}/styles.module.scss (100%)
delete mode 100644 src/pages/PreRegister/PreRegister.tsx
create mode 100644 src/pages/Register/Register.tsx
rename src/pages/{PreRegister => Register}/index.tsx (62%)
rename src/pages/{PreRegister => Register}/styles.module.scss (73%)
create mode 100644 src/server/gsheets/postulants.ts
delete mode 100644 src/server/gsheets/preVolunteers.ts
rename src/services/{preVolunteers.ts => postulants.ts} (60%)
create mode 100644 src/services/postulantsAccessors.ts
delete mode 100644 src/services/preVolunteersAccessors.ts
create mode 100644 src/store/postulantAdd.ts
delete mode 100644 src/store/preVolunteerAdd.ts
delete mode 100644 src/store/preVolunteerCount.ts
rename src/store/{volunteerAdd.ts => volunteerPartialAdd.ts} (66%)
diff --git a/src/components/PreRegisterForm/index.tsx b/src/components/RegisterForm/index.tsx
similarity index 68%
rename from src/components/PreRegisterForm/index.tsx
rename to src/components/RegisterForm/index.tsx
index 39b79cd..6bf819f 100644
--- a/src/components/PreRegisterForm/index.tsx
+++ b/src/components/RegisterForm/index.tsx
@@ -4,15 +4,16 @@ import { toast } from "react-toastify"
import _ from "lodash"
import styles from "./styles.module.scss"
-import { fetchPreVolunteerAdd } from "../../store/preVolunteerAdd"
+import { fetchPostulantAdd } from "../../store/postulantAdd"
import { AppDispatch, AppState } from "../../store"
+import { fetchVolunteerPartialAdd } from "../../store/volunteerPartialAdd"
interface Props {
dispatch: AppDispatch
- preVolunteerCount: number | undefined
}
-const PreRegisterForm = ({ dispatch, preVolunteerCount }: Props): JSX.Element => {
+const RegisterForm = ({ dispatch }: Props): JSX.Element => {
+ const [potentialVolunteer, setPotentialVolunteer] = useState(true)
const [firstname, setFirstname] = useState("")
const [lastname, setLastname] = useState("")
const [email, setEmail] = useState("")
@@ -21,31 +22,60 @@ const PreRegisterForm = ({ dispatch, preVolunteerCount }: Props): JSX.Element =>
const [comment, setComment] = useState("")
const [sending, setSending] = useState(false)
+ const onNewVolunteer = (e: React.ChangeEvent) =>
+ setPotentialVolunteer(!e.target.value)
+ const onPotentialVolunteer = (e: React.ChangeEvent) =>
+ setPotentialVolunteer(!!e.target.value)
+
const onFirstnameChanged = (e: React.ChangeEvent) =>
setFirstname(e.target.value)
const onLastnameChanged = (e: React.ChangeEvent) =>
setLastname(e.target.value)
+
const onEmailChanged = (e: React.ChangeEvent) => setEmail(e.target.value)
const onMobileChanged = (e: React.ChangeEvent) => setMobile(e.target.value)
+
const onAlreadyVolunteer = (e: React.ChangeEvent) =>
setAlreadyVolunteer(!!e.target.value)
const onNotYesVolunteer = (e: React.ChangeEvent) =>
setAlreadyVolunteer(!e.target.value)
+
const onCommentChanged = (e: React.ChangeEvent) =>
setComment(e.target.value)
const onSubmit = () => {
if (firstname && lastname && email && mobile && !sending) {
- dispatch(
- fetchPreVolunteerAdd({
- firstname,
- lastname,
- email,
- mobile,
- alreadyVolunteer,
- comment,
- })
- )
+ if (potentialVolunteer) {
+ dispatch(
+ fetchPostulantAdd({
+ firstname,
+ lastname,
+ email,
+ mobile,
+ potential: true,
+ comment,
+ })
+ )
+ } else {
+ dispatch(
+ fetchPostulantAdd({
+ firstname,
+ lastname,
+ email,
+ mobile,
+ potential: false,
+ comment,
+ })
+ )
+ dispatch(
+ fetchVolunteerPartialAdd({
+ firstname,
+ lastname,
+ email,
+ mobile,
+ })
+ )
+ }
setSending(true)
} else {
@@ -61,13 +91,13 @@ const PreRegisterForm = ({ dispatch, preVolunteerCount }: Props): JSX.Element =>
}
}
- const { error, entities: preVolunteer } = useSelector(
- (state: AppState) => state.preVolunteerAdd,
+ const { error, entities: postulant } = useSelector(
+ (state: AppState) => state.postulantAdd,
shallowEqual
)
let sendSuccess
- if (!_.isEmpty(preVolunteer)) {
+ if (!_.isEmpty(postulant)) {
if (sending) {
setSending(false)
}
@@ -75,7 +105,7 @@ const PreRegisterForm = ({ dispatch, preVolunteerCount }: Props): JSX.Element =>
}
let sendError
- if (error && _.isEmpty(preVolunteer)) {
+ if (error && _.isEmpty(postulant)) {
if (sending) {
setSending(false)
}
@@ -140,31 +170,53 @@ const PreRegisterForm = ({ dispatch, preVolunteerCount }: Props): JSX.Element =>
confort avant tout !
- Certains bénévoles sont visiteurs le samedi ou le dimanche pour vivre le
- festival de l'intérieur. Les deux jours avant et le jour après le
- festival, ceux qui le peuvent viennent préparer et ranger. Bref, chacun
- participe à la hauteur de ses wishes et disponibilités !
+ La majorité d'entre nous sommes bénévoles les samedi et dimanche
+ , mais certains bénévoles ne sont pas disponibles les deux jours. On leur
+ demande alors d'aider à la mise en place jeudi ou vendredi, ou au
+ rangement le lundi. Bref, chacun participe comme il peut mais deux jours
+ minimum !
Le samedi soir quand les visiteurs sont partis, nous prolongeons la fête en
- dînant avec les auteurs, illustrateurs et éditeurs présents sur le festival.
+ dînant avec les exposants présents sur le festival.
- Si l'expérience pourrait vous tenter, remplissez le formulaire suivant pour
- en discuter lors d'un des gros apéros mensuels !
- Cette inscription ne vous oblige en rien il s'agit juste d'une prise
- de contact.
+ Si l'expérience vous tente, remplissez le formulaire suivant pour devenir
+ bénévoles !
+ Vous pouvez aussi juste nous rencontrer avant de vous décider à devenir
+ bénévole, on comprend qu'un saut dans l'inconnu soit difficile.
- Les prochains sont les 21 décembre et 27 janvier, mais nous vous appelerons
- d'ici là pour les détails :)
+ Dans les deux cas, venez nous rencontrer mardi 22 mars près de Châtelet, détails
+ après l'inscription :)
- {/* */}
-
- (Déjà {preVolunteerCount} inscrits !)
-
+
Prénom
@@ -253,4 +305,4 @@ const PreRegisterForm = ({ dispatch, preVolunteerCount }: Props): JSX.Element =>
)
}
-export default memo(PreRegisterForm)
+export default memo(RegisterForm)
diff --git a/src/components/PreRegisterForm/styles.module.scss b/src/components/RegisterForm/styles.module.scss
similarity index 100%
rename from src/components/PreRegisterForm/styles.module.scss
rename to src/components/RegisterForm/styles.module.scss
diff --git a/src/components/index.ts b/src/components/index.ts
index 4368455..d0892e4 100755
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -11,7 +11,7 @@ import Asks, { fetchFor as fetchForAsks } from "./Asks"
import ParticipationDetailsForm, {
fetchFor as fetchForParticipationDetailsForm,
} from "./VolunteerBoard/ParticipationDetailsForm/ParticipationDetailsForm"
-import PreRegisterForm from "./PreRegisterForm"
+import RegisterForm from "./RegisterForm"
import TeamWishesForm, {
fetchFor as fetchForTeamWishesForm,
} from "./VolunteerBoard/TeamWishesForm/TeamWishesForm"
@@ -34,7 +34,7 @@ export {
fetchForAsks,
ParticipationDetailsForm,
fetchForParticipationDetailsForm,
- PreRegisterForm,
+ RegisterForm,
TeamWishesForm,
fetchForTeamWishesForm,
VolunteerInfo,
diff --git a/src/pages/PreRegister/PreRegister.tsx b/src/pages/PreRegister/PreRegister.tsx
deleted file mode 100644
index a262c5d..0000000
--- a/src/pages/PreRegister/PreRegister.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import { FC, useEffect, memo } from "react"
-import { RouteComponentProps } from "react-router-dom"
-import { useDispatch, useSelector, shallowEqual } from "react-redux"
-import { Helmet } from "react-helmet"
-
-import { AppState, AppThunk, ValueRequest } from "../../store"
-import { fetchPreVolunteerCountIfNeed } from "../../store/preVolunteerCount"
-import { PreRegisterForm } from "../../components"
-import styles from "./styles.module.scss"
-
-export type Props = RouteComponentProps
-
-function useList(
- stateToProp: (state: AppState) => ValueRequest
,
- fetchDataIfNeed: () => AppThunk
-) {
- const dispatch = useDispatch()
- const { readyStatus, value } = useSelector(stateToProp, shallowEqual)
-
- // Fetch client-side data here
- useEffect(() => {
- dispatch(fetchDataIfNeed())
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [dispatch])
-
- return () => {
- if (!readyStatus || readyStatus === "idle" || readyStatus === "request")
- return Loading...
-
- if (readyStatus === "failure") return Oops, Failed to load!
-
- return
- }
-}
-
-const PreRegisterPage: FC = (): JSX.Element => (
-
-
-
- {useList((state: AppState) => state.preVolunteerCount, fetchPreVolunteerCountIfNeed)()}
-
-
-)
-
-// Fetch server-side data here
-export const loadData = (): AppThunk[] => [fetchPreVolunteerCountIfNeed()]
-
-export default memo(PreRegisterPage)
diff --git a/src/pages/Register/Register.tsx b/src/pages/Register/Register.tsx
new file mode 100644
index 0000000..588bb88
--- /dev/null
+++ b/src/pages/Register/Register.tsx
@@ -0,0 +1,27 @@
+import { FC, memo } from "react"
+import { RouteComponentProps } from "react-router-dom"
+import { useDispatch } from "react-redux"
+import { Helmet } from "react-helmet"
+
+import { AppThunk } from "../../store"
+import { RegisterForm } from "../../components"
+import styles from "./styles.module.scss"
+
+export type Props = RouteComponentProps
+
+const RegisterPage: FC = (): JSX.Element => {
+ const dispatch = useDispatch()
+ return (
+
+ )
+}
+
+// Fetch server-side data here
+export const loadData = (): AppThunk[] => []
+
+export default memo(RegisterPage)
diff --git a/src/pages/PreRegister/index.tsx b/src/pages/Register/index.tsx
similarity index 62%
rename from src/pages/PreRegister/index.tsx
rename to src/pages/Register/index.tsx
index 0c8f838..fdb32ba 100755
--- a/src/pages/PreRegister/index.tsx
+++ b/src/pages/Register/index.tsx
@@ -1,15 +1,15 @@
import loadable from "@loadable/component"
import { Loading, ErrorBoundary } from "../../components"
-import { Props, loadData } from "./PreRegister"
+import { Props, loadData } from "./Register"
-const PreRegister = loadable(() => import("./PreRegister"), {
+const Register = loadable(() => import("./Register"), {
fallback: ,
})
export default (props: Props): JSX.Element => (
-
+
)
diff --git a/src/pages/PreRegister/styles.module.scss b/src/pages/Register/styles.module.scss
similarity index 73%
rename from src/pages/PreRegister/styles.module.scss
rename to src/pages/Register/styles.module.scss
index 7d678c1..c7f3efb 100755
--- a/src/pages/PreRegister/styles.module.scss
+++ b/src/pages/Register/styles.module.scss
@@ -1,9 +1,9 @@
@import "../../theme/mixins";
-.preRegisterPage {
+.registerPage {
@include page-wrapper-center;
}
-.preRegisterContent {
+.registerContent {
@include page-content-wrapper(600px);
}
diff --git a/src/routes/index.ts b/src/routes/index.ts
index b72a123..9eb2b1d 100755
--- a/src/routes/index.ts
+++ b/src/routes/index.ts
@@ -3,7 +3,7 @@ import { RouteConfig } from "react-router-config"
import App from "../app"
import AsyncHome, { loadData as loadHomeData } from "../pages/Home"
import AsyncAnnouncements, { loadData as loadAnnouncementsData } from "../pages/Announcements"
-import AsyncPreRegisterPage, { loadData as loadPreRegisterPage } from "../pages/PreRegister"
+import AsyncRegisterPage, { loadData as loadRegisterPage } from "../pages/Register"
import AsyncTeams, { loadData as loadTeamsData } from "../pages/Teams"
import AsyncBoard, { loadData as loadBoardData } from "../pages/Board"
import AsyncVolunteers, { loadData as loadVolunteersData } from "../pages/Volunteers"
@@ -25,13 +25,13 @@ export default [
},
{
path: "/preRegister",
- component: AsyncPreRegisterPage,
- loadData: loadPreRegisterPage,
+ component: AsyncRegisterPage,
+ loadData: loadRegisterPage,
},
{
path: "/sinscrire",
- component: AsyncPreRegisterPage,
- loadData: loadPreRegisterPage,
+ component: AsyncRegisterPage,
+ loadData: loadRegisterPage,
},
{
path: "/VolunteerPage/:id",
diff --git a/src/server/gsheets/accessors.ts b/src/server/gsheets/accessors.ts
index db502e7..1109c43 100644
--- a/src/server/gsheets/accessors.ts
+++ b/src/server/gsheets/accessors.ts
@@ -7,7 +7,7 @@ import { SheetNames, saveLocalDb, loadLocalDb } from "./localDb"
export { SheetNames } from "./localDb"
-// Test write attack with: wget --header='Content-Type:application/json' --post-data='{"prenom":"Pierre","nom":"SCELLES","email":"test@gmail.com","telephone":"0601010101","dejaBenevole":false,"commentaire":""}' http://localhost:3000/PreVolunteerAdd
+// Test write attack with: wget --header='Content-Type:application/json' --post-data='{"prenom":"Pierre","nom":"SCELLES","email":"test@gmail.com","telephone":"0601010101","dejaBenevole":false,"commentaire":""}' http://localhost:3000/PostulantAdd
const CRED_PATH = path.resolve(process.cwd(), "access/gsheets.json")
@@ -122,7 +122,7 @@ export class Sheet<
return (_.max(ids) || 0) + 1
}
- async add(elementWithoutId: ElementNoId): Promise {
+ async add(elementWithoutId: Omit): Promise {
const elements: Element[] = (await this.getList()) || []
// eslint-disable-next-line @typescript-eslint/ban-types
const element: Element = { id: await this.nextId(), ...elementWithoutId } as Element
diff --git a/src/server/gsheets/expressAccessors.ts b/src/server/gsheets/expressAccessors.ts
index 56c7fc2..c3dfe18 100644
--- a/src/server/gsheets/expressAccessors.ts
+++ b/src/server/gsheets/expressAccessors.ts
@@ -3,6 +3,7 @@ import { SheetNames, ElementWithId, getSheet, Sheet } from "./accessors"
export type RequestBody = Request["body"]
export type CustomSetReturn = { toDatabase: Element; toCaller: any }
+export type CustomAddReturn = { toDatabase: Omit; toCaller: any }
export default class ExpressAccessors<
// eslint-disable-next-line @typescript-eslint/ban-types
@@ -88,13 +89,44 @@ export default class ExpressAccessors<
}
}
- add() {
+ add(
+ custom?: (
+ list: Element[],
+ body: RequestBody,
+ id: number,
+ roles: string[]
+ ) => Promise> | CustomAddReturn
+ ) {
return async (request: Request, response: Response, _next: NextFunction): Promise => {
try {
const sheet = await this.getSheet()
- const element: Element = await sheet.add(request.body)
- if (element) {
- response.status(200).json(element)
+ if (!custom) {
+ await sheet.add(request.body)
+ response.status(200)
+ } else {
+ const memberId = response?.locals?.jwt?.id || -1
+ const roles: string[] = response?.locals?.jwt?.roles || []
+ const list = (await sheet.getList()) || []
+ const { toDatabase, toCaller } = await custom(
+ list,
+ request.body,
+ memberId,
+ roles
+ )
+ let toReturn = toCaller
+
+ if (toDatabase !== undefined) {
+ const element: Element = await sheet.add(toDatabase)
+ toCaller.id = element.id
+ if (!toCaller) {
+ toReturn = element
+ }
+ }
+ if (toReturn !== undefined) {
+ response.status(200).json(toReturn)
+ } else {
+ response.status(200)
+ }
}
} catch (e: any) {
response.status(200).json({ error: e.message })
diff --git a/src/server/gsheets/localDb.ts b/src/server/gsheets/localDb.ts
index 6e59cf9..a685084 100644
--- a/src/server/gsheets/localDb.ts
+++ b/src/server/gsheets/localDb.ts
@@ -3,7 +3,7 @@ import path from "path"
import _ from "lodash"
import { promises as fs } from "fs"
import { Volunteer } from "../../services/volunteers"
-import { PreVolunteer } from "../../services/preVolunteers"
+import { Postulant } from "../../services/postulants"
const DB_PATH = path.resolve(process.cwd(), "access/db.json")
const DB_TO_LOAD_PATH = path.resolve(process.cwd(), "access/dbToLoad.json")
@@ -14,7 +14,7 @@ export class SheetNames {
Games = "Jeux"
- PreVolunteers = "PreMembres"
+ Postulants = "Postulants"
Teams = "Equipes"
@@ -263,8 +263,8 @@ function anonimizedDb(_s: States): States {
anonimizedNotifs(v)
})
}
- if (s.PreVolunteers) {
- ;(s.PreVolunteers as PreVolunteer[]).forEach((v) => {
+ if (s.Postulants) {
+ ;(s.Postulants as Postulant[]).forEach((v) => {
anonimizedNameEmailMobile(v)
v.comment = v.id % 3 === 0 ? "Bonjour, j'adore l'initiative!" : ""
})
@@ -272,11 +272,11 @@ function anonimizedDb(_s: States): States {
return s
}
-function idADev(v: Volunteer | PreVolunteer): boolean {
+function idADev(v: Volunteer | Postulant): boolean {
return ((v as Volunteer)?.roles || []).includes("dev")
}
-function anonimizedNameEmailMobile(v: Volunteer | PreVolunteer): void {
+function anonimizedNameEmailMobile(v: Volunteer | Postulant): void {
if (idADev(v)) {
return
}
diff --git a/src/server/gsheets/postulants.ts b/src/server/gsheets/postulants.ts
new file mode 100644
index 0000000..15aa53c
--- /dev/null
+++ b/src/server/gsheets/postulants.ts
@@ -0,0 +1,44 @@
+import _ from "lodash"
+import ExpressAccessors from "./expressAccessors"
+import { Postulant, PostulantWithoutId, translationPostulant } from "../../services/postulants"
+import { canonicalEmail, canonicalMobile, trim, validMobile } from "../../utils/standardization"
+
+const expressAccessor = new ExpressAccessors(
+ "Postulants",
+ new Postulant(),
+ translationPostulant
+)
+
+export const postulantListGet = expressAccessor.listGet()
+export const postulantGet = expressAccessor.get()
+export const postulantAdd = expressAccessor.add(async (list, body) => {
+ const params = body
+ const postulant = getByEmail(list, params.email)
+ if (postulant) {
+ throw Error("Il y a déjà quelqu'un avec cet email")
+ }
+ if (!validMobile(params.mobile)) {
+ throw Error("Numéro de téléphone invalide, contacter pierre.scelles@gmail.com")
+ }
+
+ const newPostulant = _.omit(new Postulant(), "id")
+
+ _.assign(newPostulant, {
+ lastname: trim(params.lastname),
+ firstname: trim(params.firstname),
+ email: trim(params.email),
+ mobile: canonicalMobile(params.mobile),
+ })
+
+ return {
+ toDatabase: newPostulant,
+ toCaller: {},
+ }
+})
+export const postulantSet = expressAccessor.set()
+
+function getByEmail(list: T[], rawEmail: string): T | undefined {
+ const email = canonicalEmail(rawEmail || "")
+ const volunteer = list.find((v) => canonicalEmail(v.email) === email)
+ return volunteer
+}
diff --git a/src/server/gsheets/preVolunteers.ts b/src/server/gsheets/preVolunteers.ts
deleted file mode 100644
index 553f6a5..0000000
--- a/src/server/gsheets/preVolunteers.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import ExpressAccessors from "./expressAccessors"
-import {
- PreVolunteer,
- PreVolunteerWithoutId,
- translationPreVolunteer,
-} from "../../services/preVolunteers"
-
-const expressAccessor = new ExpressAccessors(
- "PreVolunteers",
- new PreVolunteer(),
- translationPreVolunteer
-)
-
-export const preVolunteerListGet = expressAccessor.listGet()
-export const preVolunteerGet = expressAccessor.get()
-export const preVolunteerAdd = expressAccessor.add()
-export const preVolunteerSet = expressAccessor.set()
-
-export const preVolunteerCountGet = expressAccessor.get((list) => list?.length || 0)
diff --git a/src/server/gsheets/volunteers.ts b/src/server/gsheets/volunteers.ts
index 1e0b96b..d0d2a4f 100644
--- a/src/server/gsheets/volunteers.ts
+++ b/src/server/gsheets/volunteers.ts
@@ -12,8 +12,9 @@ import {
translationVolunteer,
VolunteerDayWishes,
VolunteerParticipationDetails,
+ VolunteerPartialAddReturn,
} from "../../services/volunteers"
-import { canonicalEmail } from "../../utils/standardization"
+import { canonicalEmail, canonicalMobile, trim, validMobile } from "../../utils/standardization"
import { getJwt } from "../secure"
const expressAccessor = new ExpressAccessors(
@@ -23,9 +24,41 @@ const expressAccessor = new ExpressAccessors(
)
export const volunteerListGet = expressAccessor.listGet()
-export const volunteerAdd = expressAccessor.add()
+// export const volunteerAdd = expressAccessor.add()
export const volunteerSet = expressAccessor.set()
+export const volunteerPartialAdd = expressAccessor.add(async (list, body) => {
+ const params = body[0]
+ const volunteer = getByEmail(list, params.email)
+ if (volunteer) {
+ throw Error("Il y a déjà un bénévole avec cet email")
+ }
+ if (!validMobile(params.mobile)) {
+ throw Error("Numéro de téléphone invalide, contacter pierre.scelles@gmail.com")
+ }
+
+ const password = generatePassword()
+ const passwordHash = await bcrypt.hash(password, 10)
+
+ const newVolunteer = _.omit(new Volunteer(), "id")
+
+ _.assign(newVolunteer, {
+ lastname: trim(params.lastname),
+ firstname: trim(params.firstname),
+ email: trim(params.email),
+ mobile: canonicalMobile(params.mobile),
+ password1: passwordHash,
+ password2: passwordHash,
+ })
+
+ return {
+ toDatabase: newVolunteer,
+ toCaller: {
+ password,
+ } as VolunteerPartialAddReturn,
+ }
+})
+
export const volunteerLogin = expressAccessor.get(async (list, bodyArray) => {
const [body] = bodyArray
const volunteer = getByEmail(list, body.email)
diff --git a/src/server/index.ts b/src/server/index.ts
index bd5a953..67062d5 100755
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -19,16 +19,17 @@ import certbotRouter from "../routes/certbot"
import { hasSecret, secure } from "./secure"
import { announcementListGet } from "./gsheets/announcements"
import { gameListGet } from "./gsheets/games"
-import { preVolunteerAdd, preVolunteerCountGet } from "./gsheets/preVolunteers"
+import { postulantAdd } from "./gsheets/postulants"
import { teamListGet } from "./gsheets/teams"
import {
- volunteerSet,
- volunteerLogin,
- volunteerForgot,
- volunteerAsksSet,
- volunteerParticipationDetailsSet,
- volunteerTeamWishesSet,
volunteerDayWishesSet,
+ volunteerForgot,
+ volunteerLogin,
+ volunteerAsksSet,
+ volunteerPartialAdd,
+ volunteerParticipationDetailsSet,
+ volunteerSet,
+ volunteerTeamWishesSet,
} from "./gsheets/volunteers"
import { wishListGet, wishAdd } from "./gsheets/wishes"
import config from "../config"
@@ -82,8 +83,8 @@ app.get(
app.get("/GameListGet", gameListGet)
app.get("/WishListGet", wishListGet)
app.post("/WishAdd", wishAdd)
-app.post("/PreVolunteerAdd", preVolunteerAdd)
-app.get("/PreVolunteerCountGet", preVolunteerCountGet)
+app.post("/PostulantAdd", postulantAdd)
+app.post("/VolunteerPartialAdd", volunteerPartialAdd)
app.post("/VolunteerLogin", volunteerLogin)
app.post("/VolunteerForgot", volunteerForgot)
diff --git a/src/services/preVolunteers.ts b/src/services/postulants.ts
similarity index 60%
rename from src/services/preVolunteers.ts
rename to src/services/postulants.ts
index 55e4e3b..c609812 100644
--- a/src/services/preVolunteers.ts
+++ b/src/services/postulants.ts
@@ -1,4 +1,4 @@
-export class PreVolunteer {
+export class Postulant {
id = 0
firstname = ""
@@ -9,25 +9,25 @@ export class PreVolunteer {
mobile = ""
- alreadyVolunteer = false
+ potential = false
comment = ""
}
-export const translationPreVolunteer: { [k in keyof PreVolunteer]: string } = {
+export const translationPostulant: { [k in keyof Postulant]: string } = {
id: "id",
firstname: "prenom",
lastname: "nom",
email: "email",
mobile: "telephone",
- alreadyVolunteer: "dejaBenevole",
+ potential: "potentiel",
comment: "commentaire",
}
-export const elementName = "PreVolunteer"
+export const elementName = "Postulant"
export const emailRegexp =
/^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i
export const passwordMinLength = 4
-export type PreVolunteerWithoutId = Omit
+export type PostulantWithoutId = Omit
diff --git a/src/services/postulantsAccessors.ts b/src/services/postulantsAccessors.ts
new file mode 100644
index 0000000..7a25e93
--- /dev/null
+++ b/src/services/postulantsAccessors.ts
@@ -0,0 +1,9 @@
+import ServiceAccessors from "./accessors"
+import { elementName, Postulant, PostulantWithoutId } from "./postulants"
+
+const serviceAccessors = new ServiceAccessors(elementName)
+
+export const postulantListGet = serviceAccessors.listGet()
+export const postulantGet = serviceAccessors.get()
+export const postulantAdd = serviceAccessors.add()
+export const postulantSet = serviceAccessors.set()
diff --git a/src/services/preVolunteersAccessors.ts b/src/services/preVolunteersAccessors.ts
deleted file mode 100644
index 3c04c11..0000000
--- a/src/services/preVolunteersAccessors.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import ServiceAccessors from "./accessors"
-import { elementName, PreVolunteer, PreVolunteerWithoutId } from "./preVolunteers"
-
-const serviceAccessors = new ServiceAccessors(elementName)
-
-export const preVolunteerListGet = serviceAccessors.listGet()
-export const preVolunteerGet = serviceAccessors.get()
-export const preVolunteerAdd = serviceAccessors.add()
-export const preVolunteerSet = serviceAccessors.set()
-export const preVolunteerCountGet = serviceAccessors.countGet()
diff --git a/src/services/volunteers.ts b/src/services/volunteers.ts
index 372c704..7492e79 100644
--- a/src/services/volunteers.ts
+++ b/src/services/volunteers.ts
@@ -1,4 +1,5 @@
-export class Volunteer {
+/* eslint-disable max-classes-per-file */
+export class Volunteer implements VolunteerPartial {
id = 0
lastname = ""
@@ -9,7 +10,7 @@ export class Volunteer {
mobile = ""
- photo = ""
+ photo = "anonyme.png"
adult = 1
@@ -27,7 +28,7 @@ export class Volunteer {
tshirtSize = ""
- food = ""
+ food = "Aucune"
teamWishes: number[] = []
@@ -72,6 +73,22 @@ export const translationVolunteer: { [k in keyof Volunteer]: string } = {
acceptsNotifs: "accepteLesNotifs",
}
+export class VolunteerPartial {
+ lastname = ""
+
+ firstname = ""
+
+ email = ""
+
+ mobile = ""
+}
+
+export class VolunteerPartialAddReturn {
+ id = 0
+
+ password = ""
+}
+
export const elementName = "Volunteer"
export const volunteerExample: Volunteer = {
diff --git a/src/services/volunteersAccessors.ts b/src/services/volunteersAccessors.ts
index e7ec52d..0d526b0 100644
--- a/src/services/volunteersAccessors.ts
+++ b/src/services/volunteersAccessors.ts
@@ -13,7 +13,7 @@ const serviceAccessors = new ServiceAccessors(ele
export const volunteerListGet = serviceAccessors.listGet()
export const volunteerGet = serviceAccessors.get()
-export const volunteerAdd = serviceAccessors.add()
+export const volunteerPartialAdd = serviceAccessors.customPost<[Partial]>("PartialAdd")
export const volunteerSet = serviceAccessors.set()
export const volunteerLogin =
diff --git a/src/store/postulantAdd.ts b/src/store/postulantAdd.ts
new file mode 100644
index 0000000..64399fa
--- /dev/null
+++ b/src/store/postulantAdd.ts
@@ -0,0 +1,39 @@
+import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
+
+import { StateRequest, elementAddFetch } from "./utils"
+import { Postulant } from "../services/postulants"
+import { postulantAdd } from "../services/postulantsAccessors"
+
+const postulantAdapter = createEntityAdapter()
+
+const postulantAddSlice = createSlice({
+ name: "addPostulant",
+ initialState: postulantAdapter.getInitialState({
+ readyStatus: "idle",
+ } as StateRequest),
+ reducers: {
+ getRequesting: (state) => {
+ state.readyStatus = "request"
+ },
+ getSuccess: (state, { payload }: PayloadAction) => {
+ state.readyStatus = "success"
+ postulantAdapter.addOne(state, payload)
+ },
+ getFailure: (state, { payload }: PayloadAction) => {
+ state.readyStatus = "failure"
+ state.error = payload
+ },
+ },
+})
+
+export default postulantAddSlice.reducer
+export const { getRequesting, getSuccess, getFailure } = postulantAddSlice.actions
+
+export const fetchPostulantAdd = elementAddFetch(
+ postulantAdd,
+ getRequesting,
+ getSuccess,
+ getFailure,
+ () => null,
+ () => null
+)
diff --git a/src/store/preVolunteerAdd.ts b/src/store/preVolunteerAdd.ts
deleted file mode 100644
index 09149ba..0000000
--- a/src/store/preVolunteerAdd.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
-
-import { StateRequest, elementAddFetch } from "./utils"
-import { PreVolunteer } from "../services/preVolunteers"
-import { preVolunteerAdd } from "../services/preVolunteersAccessors"
-
-const preVolunteerAdapter = createEntityAdapter()
-
-const preVolunteerAddSlice = createSlice({
- name: "addPreVolunteer",
- initialState: preVolunteerAdapter.getInitialState({
- readyStatus: "idle",
- } as StateRequest),
- reducers: {
- getRequesting: (state) => {
- state.readyStatus = "request"
- },
- getSuccess: (state, { payload }: PayloadAction) => {
- state.readyStatus = "success"
- preVolunteerAdapter.addOne(state, payload)
- },
- getFailure: (state, { payload }: PayloadAction) => {
- state.readyStatus = "failure"
- state.error = payload
- },
- },
-})
-
-export default preVolunteerAddSlice.reducer
-export const { getRequesting, getSuccess, getFailure } = preVolunteerAddSlice.actions
-
-export const fetchPreVolunteerAdd = elementAddFetch(
- preVolunteerAdd,
- getRequesting,
- getSuccess,
- getFailure,
- () => null,
- () => null
-)
diff --git a/src/store/preVolunteerCount.ts b/src/store/preVolunteerCount.ts
deleted file mode 100644
index 50cdcd8..0000000
--- a/src/store/preVolunteerCount.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import { PayloadAction, createSlice } from "@reduxjs/toolkit"
-
-import { StateRequest, toastError, elementValueFetch } from "./utils"
-import { preVolunteerCountGet } from "../services/preVolunteersAccessors"
-import { AppThunk, AppState } from "."
-
-export const initialState: StateRequest & { value?: number } = { readyStatus: "idle" }
-
-const preVolunteerCount = createSlice({
- name: "preVolunteerCount",
- initialState,
- reducers: {
- getRequesting: (state) => {
- state.readyStatus = "request"
- },
- getSuccess: (state, { payload }: PayloadAction) => {
- state.readyStatus = "success"
- state.value = payload
- },
- getFailure: (state, { payload }: PayloadAction) => {
- state.readyStatus = "failure"
- state.error = payload
- },
- },
-})
-
-export default preVolunteerCount.reducer
-export const { getRequesting, getSuccess, getFailure } = preVolunteerCount.actions
-
-export const fetchPreVolunteerCount = elementValueFetch(
- preVolunteerCountGet,
- getRequesting,
- getSuccess,
- getFailure,
- (error: Error) =>
- toastError(`Erreur lors du chargement des bénévoles potentiels: ${error.message}`)
-)
-
-const shouldFetchPreVolunteerCount = (state: AppState) =>
- state.preVolunteerCount.readyStatus !== "success"
-
-export const fetchPreVolunteerCountIfNeed = (): AppThunk => (dispatch, getState) => {
- if (shouldFetchPreVolunteerCount(getState())) return dispatch(fetchPreVolunteerCount())
-
- return null
-}
diff --git a/src/store/rootReducer.ts b/src/store/rootReducer.ts
index 2b6cbf7..49a5a98 100644
--- a/src/store/rootReducer.ts
+++ b/src/store/rootReducer.ts
@@ -4,12 +4,11 @@ import { connectRouter } from "connected-react-router"
import auth from "./auth"
import gameList from "./gameList"
import announcementList from "./announcementList"
-import preVolunteerAdd from "./preVolunteerAdd"
-import preVolunteerCount from "./preVolunteerCount"
+import postulantAdd from "./postulantAdd"
import teamList from "./teamList"
import ui from "./ui"
import volunteer from "./volunteer"
-import volunteerAdd from "./volunteerAdd"
+import volunteerAdd from "./volunteerPartialAdd"
import volunteerList from "./volunteerList"
import volunteerSet from "./volunteerSet"
import volunteerLogin from "./volunteerLogin"
@@ -27,8 +26,7 @@ export default (history: History) => ({
auth,
gameList,
announcementList,
- preVolunteerAdd,
- preVolunteerCount,
+ postulantAdd,
teamList,
ui,
volunteer,
diff --git a/src/store/utils.ts b/src/store/utils.ts
index 8649df8..cf1ad83 100644
--- a/src/store/utils.ts
+++ b/src/store/utils.ts
@@ -65,7 +65,7 @@ export function elementFetch>(
}
export function elementAddFetch(
- elementAddService: (volunteerWithoutId: Omit) => Promise<{
+ elementAddService: (elementWithoutId: Omit) => Promise<{
data?: Element | undefined
error?: Error | undefined
}>,
@@ -74,12 +74,12 @@ export function elementAddFetch(
getFailure: ActionCreatorWithPayload,
errorMessage?: (error: Error) => void,
successMessage?: () => void
-): (volunteerWithoutId: Omit) => AppThunk {
- return (volunteerWithoutId: Omit): AppThunk =>
+): (elementWithoutId: Omit) => AppThunk {
+ return (elementWithoutId: Omit): AppThunk =>
async (dispatch) => {
dispatch(getRequesting())
- const { error, data } = await elementAddService(volunteerWithoutId)
+ const { error, data } = await elementAddService(elementWithoutId)
if (error) {
dispatch(getFailure(error.message))
@@ -119,7 +119,7 @@ export function elementListFetch>(
}
export function elementSet(
- elementSetService: (volunteer: Element) => Promise<{
+ elementSetService: (element: Element) => Promise<{
data?: Element | undefined
error?: Error | undefined
}>,
diff --git a/src/store/volunteerAdd.ts b/src/store/volunteerPartialAdd.ts
similarity index 66%
rename from src/store/volunteerAdd.ts
rename to src/store/volunteerPartialAdd.ts
index 24803e3..d11e935 100644
--- a/src/store/volunteerAdd.ts
+++ b/src/store/volunteerPartialAdd.ts
@@ -1,12 +1,12 @@
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
-import { StateRequest, toastError, toastSuccess, elementAddFetch } from "./utils"
+import { StateRequest, elementAddFetch } from "./utils"
import { Volunteer } from "../services/volunteers"
-import { volunteerAdd } from "../services/volunteersAccessors"
+import { volunteerPartialAdd } from "../services/volunteersAccessors"
const volunteerAdapter = createEntityAdapter()
-const volunteerAddSlice = createSlice({
+const volunteerPartialAddSlice = createSlice({
name: "addVolunteer",
initialState: volunteerAdapter.getInitialState({
readyStatus: "idle",
@@ -26,14 +26,14 @@ const volunteerAddSlice = createSlice({
},
})
-export default volunteerAddSlice.reducer
-export const { getRequesting, getSuccess, getFailure } = volunteerAddSlice.actions
+export default volunteerPartialAddSlice.reducer
+export const { getRequesting, getSuccess, getFailure } = volunteerPartialAddSlice.actions
-export const fetchVolunteerAdd = elementAddFetch(
- volunteerAdd,
+export const fetchVolunteerPartialAdd = elementAddFetch(
+ volunteerPartialAdd,
getRequesting,
getSuccess,
getFailure,
- (error: Error) => toastError(`Erreur lors de l'ajout d'un bénévole: ${error.message}`),
- () => toastSuccess("Volunteer ajoutée !")
+ () => null,
+ () => null
)
From 1936cd34a36ff33aef482c2dc52b5e54f0ed8918 Mon Sep 17 00:00:00 2001
From: pikiou
Date: Fri, 8 Apr 2022 16:17:35 +0200
Subject: [PATCH 2/5] Improve registration form
---
src/app/img/bene2019.jpg | Bin 0 -> 108321 bytes
src/app/img/pel2016.jpg | Bin 0 -> 115485 bytes
src/app/img/pel2017.jpg | Bin 0 -> 104838 bytes
src/app/img/plan2019.jpg | Bin 0 -> 309341 bytes
src/components/Form/FormButton/FormButton.tsx | 25 +-
src/components/RegisterForm/index.tsx | 815 +++++++++++++-----
.../RegisterForm/styles.module.scss | 150 +++-
src/server/gsheets/postulants.ts | 6 +
src/server/gsheets/volunteers.ts | 2 +
src/services/postulants.ts | 12 +
src/services/volunteers.ts | 8 +
11 files changed, 780 insertions(+), 238 deletions(-)
create mode 100644 src/app/img/bene2019.jpg
create mode 100644 src/app/img/pel2016.jpg
create mode 100644 src/app/img/pel2017.jpg
create mode 100644 src/app/img/plan2019.jpg
diff --git a/src/app/img/bene2019.jpg b/src/app/img/bene2019.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..a7df81899afd6bcc284b17b4e76125fd50d3a53d
GIT binary patch
literal 108321
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
zⅆ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