From ebefcb247ca0723304cfa22ab1717866006ba97b Mon Sep 17 00:00:00 2001 From: pikiou Date: Tue, 12 Apr 2022 17:31:53 +0200 Subject: [PATCH] Add email and error message when duplicate email at registration --- src/components/RegisterForm/index.tsx | 135 +++++++++++++++----------- src/server/gsheets/accessors.ts | 2 +- src/server/gsheets/volunteers.ts | 28 +++++- src/services/accessors.ts | 15 +++ src/services/volunteers.ts | 10 +- src/store/postulantAdd.ts | 4 +- src/store/volunteerPartialAdd.ts | 4 +- src/store/wishAdd.ts | 2 +- src/store/wishList.ts | 2 +- 9 files changed, 123 insertions(+), 79 deletions(-) diff --git a/src/components/RegisterForm/index.tsx b/src/components/RegisterForm/index.tsx index ea1c606..54223d0 100644 --- a/src/components/RegisterForm/index.tsx +++ b/src/components/RegisterForm/index.tsx @@ -76,53 +76,8 @@ const RegisterForm = ({ dispatch }: Props): JSX.Element => { toastError("Cet email est invalid ><") return } - if (firstname && lastname && email && mobile && !sending) { - if (potentialVolunteer) { - dispatch( - fetchPostulantAdd({ - potential: true, - firstname, - lastname, - email, - mobile, - howToContact, - alreadyCame, - firstMeeting, - commentFirstMeeting: firstMeeting ? "" : commentFirstMeeting, - comment, - }) - ) - } else { - dispatch( - fetchVolunteerPartialAdd({ - firstname, - lastname, - email, - mobile, - howToContact, - canHelpBefore, - pelMember, - }) - ) - dispatch( - fetchPostulantAdd({ - potential: false, - firstname, - lastname, - email, - mobile, - howToContact, - alreadyCame, - firstMeeting, - commentFirstMeeting: firstMeeting ? "" : commentFirstMeeting, - comment, - }) - ) - } - - setSending(true) - } else { - toast.warning("Il faut remplir les queques infos sur toi ><", { + if (!firstname || !lastname || !email || !mobile || sending) { + toast.warning("Il faut remplir les quelques infos sur toi ><", { position: "top-center", autoClose: 6000, hideProgressBar: true, @@ -131,33 +86,95 @@ const RegisterForm = ({ dispatch }: Props): JSX.Element => { draggable: true, progress: undefined, }) + return } + + if (potentialVolunteer) { + dispatch( + fetchPostulantAdd({ + potential: true, + firstname, + lastname, + email, + mobile, + howToContact, + alreadyCame, + firstMeeting, + commentFirstMeeting: firstMeeting ? "" : commentFirstMeeting, + comment, + }) + ) + } else { + dispatch( + fetchVolunteerPartialAdd({ + firstname, + lastname, + email, + mobile, + howToContact, + canHelpBefore, + pelMember, + }) + ) + dispatch( + fetchPostulantAdd({ + potential: false, + firstname, + lastname, + email, + mobile, + howToContact, + alreadyCame, + firstMeeting, + commentFirstMeeting: firstMeeting ? "" : commentFirstMeeting, + comment, + }) + ) + } + + setSending(true) } - const { error, entities: postulant } = useSelector( + const { error: postulantError, entities: postulant } = useSelector( (state: AppState) => state.postulantAdd, shallowEqual ) + const { error: volunteerError, entities: volunteer } = useSelector( + (state: AppState) => state.volunteerAdd, + shallowEqual + ) + let sendSuccess - if (!_.isEmpty(postulant)) { + let sendError + let sendingElement + if ( + !postulantError && + !_.isEmpty(postulant) && + (potentialVolunteer || (!volunteerError && !_.isEmpty(volunteer))) + ) { if (sending) { setSending(false) } sendSuccess = Formulaire envoyé ! - } - - let sendError - if (error && _.isEmpty(postulant)) { + } else if (postulantError && _.isEmpty(postulant)) { if (sending) { setSending(false) } - sendError = {error} - } - - let sendingElement - if (sending) { - sendingElement = Envoi en cours... + sendError = {postulantError} + } else if (volunteerError && _.isEmpty(volunteer)) { + if (sending) { + setSending(false) + } + sendError = {volunteerError} + } else if (sending) { + sendingElement = ( + + Envoi en cours... +
+ En cas de problème, écrire à contact@parisestludique.fr +
+ ) } const intro = ( diff --git a/src/server/gsheets/accessors.ts b/src/server/gsheets/accessors.ts index 1109c43..8b51ab2 100644 --- a/src/server/gsheets/accessors.ts +++ b/src/server/gsheets/accessors.ts @@ -604,7 +604,7 @@ async function tryNTimes( return await func() } catch (e: any) { console.error(e?.error || e?.message || e) - console.error(`${repeatCount} attemps left every ${delayBetweenAttempts}`) + console.error(`${repeatCount} attempts left every ${delayBetweenAttempts}`) await new Promise((resolve) => { setTimeout(() => resolve(), delayBetweenAttempts) }) diff --git a/src/server/gsheets/volunteers.ts b/src/server/gsheets/volunteers.ts index 171bfa5..e31ef76 100644 --- a/src/server/gsheets/volunteers.ts +++ b/src/server/gsheets/volunteers.ts @@ -12,7 +12,6 @@ import { translationVolunteer, VolunteerDayWishes, VolunteerParticipationDetails, - VolunteerPartialAddReturn, } from "../../services/volunteers" import { canonicalEmail, canonicalMobile, trim, validMobile } from "../../utils/standardization" import { getJwt } from "../secure" @@ -31,7 +30,9 @@ 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") + throw Error( + "Il y a déjà un bénévole avec cet email. Mieux vaut redemander un mot de passe si tu l'as oublié." + ) } if (!validMobile(params.mobile)) { throw Error("Numéro de téléphone invalide, contacter pierre.scelles@gmail.com") @@ -54,14 +55,31 @@ export const volunteerPartialAdd = expressAccessor.add(async (list, body) => { password2: passwordHash, }) + await sendSignUpEmail(newVolunteer.email, password) + return { toDatabase: newVolunteer, - toCaller: { - password, - } as VolunteerPartialAddReturn, + toCaller: {}, } }) +async function sendSignUpEmail(email: string, password: string): Promise { + const apiKey = process.env.SENDGRID_API_KEY || "" + if (__DEV__ || apiKey === "") { + console.error(`Fake sending signup email to ${email} with password ${password}`) + } else { + sgMail.setApiKey(apiKey) + const msg = { + to: email, + from: "contact@parisestludique.fr", + subject: "Accès au site des bénévoles de Paris est Ludique", + text: `Ton inscription est bien enregistrée, l'aventure PeL peut commencer ! :)\nVoici ton mot de passe pour accéder au site des bénévoles où tu t'es inscrit.e : ${password}\nTu y trouveras notamment comment on communique entre bénévoles.\nBonne journée !\nPierre`, + html: `Ton inscription est bien enregistrée, l'aventure PeL peut commencer ! :)
Voici ton mot de passe pour accéder au site des bénévoles : ${password}
Tu y trouveras notamment comment on communique entre bénévoles.
Bonne journée !
Pierre`, + } + await sgMail.send(msg) + } +} + export const volunteerLogin = expressAccessor.get(async (list, bodyArray) => { const [body] = bodyArray const volunteer = getByEmail(list, body.email) diff --git a/src/services/accessors.ts b/src/services/accessors.ts index d256ae7..e11579b 100644 --- a/src/services/accessors.ts +++ b/src/services/accessors.ts @@ -30,6 +30,9 @@ export default class ServiceAccessors< ...axiosConfig, params: { id }, }) + if (data.error) { + throw Error(data.error) + } return { data } } catch (error) { return { error: error as Error } @@ -51,6 +54,9 @@ export default class ServiceAccessors< `${config.API_URL}/${this.elementName}ListGet`, axiosConfig ) + if (data.error) { + throw Error(data.error) + } return { data } } catch (error) { return { error: error as Error } @@ -100,6 +106,9 @@ export default class ServiceAccessors< volunteerWithoutId, axiosConfig ) + if (data.error) { + throw Error(data.error) + } return { data } } catch (error) { return { error: error as Error } @@ -122,6 +131,9 @@ export default class ServiceAccessors< volunteer, axiosConfig ) + if (data.error) { + throw Error(data.error) + } return { data } } catch (error) { return { error: error as Error } @@ -143,6 +155,9 @@ export default class ServiceAccessors< `${config.API_URL}/${this.elementName}CountGet`, axiosConfig ) + if (data.error) { + throw Error(data.error) + } return { data } } catch (error) { return { error: error as Error } diff --git a/src/services/volunteers.ts b/src/services/volunteers.ts index 83b97c1..332f8df 100644 --- a/src/services/volunteers.ts +++ b/src/services/volunteers.ts @@ -24,7 +24,7 @@ export class Volunteer implements VolunteerPartial { dayWishesComment = "" - tshirtCount = "" + tshirtCount = 0 tshirtSize = "" @@ -92,12 +92,6 @@ export class VolunteerPartial { mobile = "" } -export class VolunteerPartialAddReturn { - id = 0 - - password = "" -} - export const elementName = "Volunteer" export const volunteerExample: Volunteer = { @@ -113,7 +107,7 @@ export const volunteerExample: Volunteer = { discordId: "", dayWishes: [], dayWishesComment: "", - tshirtCount: "1", + tshirtCount: 1, tshirtSize: "Femme M", food: "Végétarien", teamWishes: [], diff --git a/src/store/postulantAdd.ts b/src/store/postulantAdd.ts index 64399fa..f576a5c 100644 --- a/src/store/postulantAdd.ts +++ b/src/store/postulantAdd.ts @@ -7,7 +7,7 @@ import { postulantAdd } from "../services/postulantsAccessors" const postulantAdapter = createEntityAdapter() const postulantAddSlice = createSlice({ - name: "addPostulant", + name: "postulantAdd", initialState: postulantAdapter.getInitialState({ readyStatus: "idle", } as StateRequest), @@ -17,7 +17,7 @@ const postulantAddSlice = createSlice({ }, getSuccess: (state, { payload }: PayloadAction) => { state.readyStatus = "success" - postulantAdapter.addOne(state, payload) + postulantAdapter.setOne(state, payload) }, getFailure: (state, { payload }: PayloadAction) => { state.readyStatus = "failure" diff --git a/src/store/volunteerPartialAdd.ts b/src/store/volunteerPartialAdd.ts index d11e935..a26ef63 100644 --- a/src/store/volunteerPartialAdd.ts +++ b/src/store/volunteerPartialAdd.ts @@ -7,7 +7,7 @@ import { volunteerPartialAdd } from "../services/volunteersAccessors" const volunteerAdapter = createEntityAdapter() const volunteerPartialAddSlice = createSlice({ - name: "addVolunteer", + name: "volunteerAdd", initialState: volunteerAdapter.getInitialState({ readyStatus: "idle", } as StateRequest), @@ -17,7 +17,7 @@ const volunteerPartialAddSlice = createSlice({ }, getSuccess: (state, { payload }: PayloadAction) => { state.readyStatus = "success" - volunteerAdapter.addOne(state, payload) + volunteerAdapter.setOne(state, payload) }, getFailure: (state, { payload }: PayloadAction) => { state.readyStatus = "failure" diff --git a/src/store/wishAdd.ts b/src/store/wishAdd.ts index d8440e8..6845d7f 100644 --- a/src/store/wishAdd.ts +++ b/src/store/wishAdd.ts @@ -7,7 +7,7 @@ import { wishAdd } from "../services/wishesAccessors" const wishAdapter = createEntityAdapter() const wishAddSlice = createSlice({ - name: "addWish", + name: "wishAdd", initialState: wishAdapter.getInitialState({ readyStatus: "idle", } as StateRequest), diff --git a/src/store/wishList.ts b/src/store/wishList.ts index 23ce147..fbb42ae 100644 --- a/src/store/wishList.ts +++ b/src/store/wishList.ts @@ -8,7 +8,7 @@ import { wishListGet } from "../services/wishesAccessors" const wishAdapter = createEntityAdapter() const wishList = createSlice({ - name: "getWishList", + name: "wishList", initialState: wishAdapter.getInitialState({ readyStatus: "idle", } as StateRequest),