Add email and error message when duplicate email at registration

This commit is contained in:
pikiou 2022-04-12 17:31:53 +02:00
parent dc4fdda658
commit ebefcb247c
9 changed files with 123 additions and 79 deletions

View File

@ -76,7 +76,19 @@ const RegisterForm = ({ dispatch }: Props): JSX.Element => {
toastError("Cet email est invalid ><") toastError("Cet email est invalid ><")
return return
} }
if (firstname && lastname && email && mobile && !sending) { if (!firstname || !lastname || !email || !mobile || sending) {
toast.warning("Il faut remplir les quelques infos sur toi ><", {
position: "top-center",
autoClose: 6000,
hideProgressBar: true,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
})
return
}
if (potentialVolunteer) { if (potentialVolunteer) {
dispatch( dispatch(
fetchPostulantAdd({ fetchPostulantAdd({
@ -121,43 +133,48 @@ const RegisterForm = ({ dispatch }: Props): JSX.Element => {
} }
setSending(true) setSending(true)
} else {
toast.warning("Il faut remplir les queques infos sur toi ><", {
position: "top-center",
autoClose: 6000,
hideProgressBar: true,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
})
}
} }
const { error, entities: postulant } = useSelector( const { error: postulantError, entities: postulant } = useSelector(
(state: AppState) => state.postulantAdd, (state: AppState) => state.postulantAdd,
shallowEqual shallowEqual
) )
const { error: volunteerError, entities: volunteer } = useSelector(
(state: AppState) => state.volunteerAdd,
shallowEqual
)
let sendSuccess let sendSuccess
if (!_.isEmpty(postulant)) { let sendError
let sendingElement
if (
!postulantError &&
!_.isEmpty(postulant) &&
(potentialVolunteer || (!volunteerError && !_.isEmpty(volunteer)))
) {
if (sending) { if (sending) {
setSending(false) setSending(false)
} }
sendSuccess = <span className={styles.success}>Formulaire envoyé !</span> sendSuccess = <span className={styles.success}>Formulaire envoyé !</span>
} } else if (postulantError && _.isEmpty(postulant)) {
let sendError
if (error && _.isEmpty(postulant)) {
if (sending) { if (sending) {
setSending(false) setSending(false)
} }
sendError = <span className={styles.error}>{error}</span> sendError = <span className={styles.error}>{postulantError}</span>
} } else if (volunteerError && _.isEmpty(volunteer)) {
let sendingElement
if (sending) { if (sending) {
sendingElement = <span className={styles.sending}>Envoi en cours...</span> setSending(false)
}
sendError = <span className={styles.error}>{volunteerError}</span>
} else if (sending) {
sendingElement = (
<span className={styles.sending}>
Envoi en cours...
<br />
En cas de problème, écrire à contact@parisestludique.fr
</span>
)
} }
const intro = ( const intro = (

View File

@ -604,7 +604,7 @@ async function tryNTimes<T>(
return await func() return await func()
} catch (e: any) { } catch (e: any) {
console.error(e?.error || e?.message || e) console.error(e?.error || e?.message || e)
console.error(`${repeatCount} attemps left every ${delayBetweenAttempts}`) console.error(`${repeatCount} attempts left every ${delayBetweenAttempts}`)
await new Promise<void>((resolve) => { await new Promise<void>((resolve) => {
setTimeout(() => resolve(), delayBetweenAttempts) setTimeout(() => resolve(), delayBetweenAttempts)
}) })

View File

@ -12,7 +12,6 @@ import {
translationVolunteer, translationVolunteer,
VolunteerDayWishes, VolunteerDayWishes,
VolunteerParticipationDetails, VolunteerParticipationDetails,
VolunteerPartialAddReturn,
} from "../../services/volunteers" } from "../../services/volunteers"
import { canonicalEmail, canonicalMobile, trim, validMobile } from "../../utils/standardization" import { canonicalEmail, canonicalMobile, trim, validMobile } from "../../utils/standardization"
import { getJwt } from "../secure" import { getJwt } from "../secure"
@ -31,7 +30,9 @@ export const volunteerPartialAdd = expressAccessor.add(async (list, body) => {
const params = body[0] const params = body[0]
const volunteer = getByEmail(list, params.email) const volunteer = getByEmail(list, params.email)
if (volunteer) { 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)) { if (!validMobile(params.mobile)) {
throw Error("Numéro de téléphone invalide, contacter pierre.scelles@gmail.com") 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, password2: passwordHash,
}) })
await sendSignUpEmail(newVolunteer.email, password)
return { return {
toDatabase: newVolunteer, toDatabase: newVolunteer,
toCaller: { toCaller: {},
password,
} as VolunteerPartialAddReturn,
} }
}) })
async function sendSignUpEmail(email: string, password: string): Promise<void> {
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 ! :)<br />Voici ton mot de passe pour accéder au <a href="https://fo.parisestludique.fr/">site des bénévoles</a> : <strong>${password}</strong><br />Tu y trouveras notamment comment on communique entre bénévoles.<br />Bonne journée !<br />Pierre`,
}
await sgMail.send(msg)
}
}
export const volunteerLogin = expressAccessor.get<VolunteerLogin>(async (list, bodyArray) => { export const volunteerLogin = expressAccessor.get<VolunteerLogin>(async (list, bodyArray) => {
const [body] = bodyArray const [body] = bodyArray
const volunteer = getByEmail(list, body.email) const volunteer = getByEmail(list, body.email)

View File

@ -30,6 +30,9 @@ export default class ServiceAccessors<
...axiosConfig, ...axiosConfig,
params: { id }, params: { id },
}) })
if (data.error) {
throw Error(data.error)
}
return { data } return { data }
} catch (error) { } catch (error) {
return { error: error as Error } return { error: error as Error }
@ -51,6 +54,9 @@ export default class ServiceAccessors<
`${config.API_URL}/${this.elementName}ListGet`, `${config.API_URL}/${this.elementName}ListGet`,
axiosConfig axiosConfig
) )
if (data.error) {
throw Error(data.error)
}
return { data } return { data }
} catch (error) { } catch (error) {
return { error: error as Error } return { error: error as Error }
@ -100,6 +106,9 @@ export default class ServiceAccessors<
volunteerWithoutId, volunteerWithoutId,
axiosConfig axiosConfig
) )
if (data.error) {
throw Error(data.error)
}
return { data } return { data }
} catch (error) { } catch (error) {
return { error: error as Error } return { error: error as Error }
@ -122,6 +131,9 @@ export default class ServiceAccessors<
volunteer, volunteer,
axiosConfig axiosConfig
) )
if (data.error) {
throw Error(data.error)
}
return { data } return { data }
} catch (error) { } catch (error) {
return { error: error as Error } return { error: error as Error }
@ -143,6 +155,9 @@ export default class ServiceAccessors<
`${config.API_URL}/${this.elementName}CountGet`, `${config.API_URL}/${this.elementName}CountGet`,
axiosConfig axiosConfig
) )
if (data.error) {
throw Error(data.error)
}
return { data } return { data }
} catch (error) { } catch (error) {
return { error: error as Error } return { error: error as Error }

View File

@ -24,7 +24,7 @@ export class Volunteer implements VolunteerPartial {
dayWishesComment = "" dayWishesComment = ""
tshirtCount = "" tshirtCount = 0
tshirtSize = "" tshirtSize = ""
@ -92,12 +92,6 @@ export class VolunteerPartial {
mobile = "" mobile = ""
} }
export class VolunteerPartialAddReturn {
id = 0
password = ""
}
export const elementName = "Volunteer" export const elementName = "Volunteer"
export const volunteerExample: Volunteer = { export const volunteerExample: Volunteer = {
@ -113,7 +107,7 @@ export const volunteerExample: Volunteer = {
discordId: "", discordId: "",
dayWishes: [], dayWishes: [],
dayWishesComment: "", dayWishesComment: "",
tshirtCount: "1", tshirtCount: 1,
tshirtSize: "Femme M", tshirtSize: "Femme M",
food: "Végétarien", food: "Végétarien",
teamWishes: [], teamWishes: [],

View File

@ -7,7 +7,7 @@ import { postulantAdd } from "../services/postulantsAccessors"
const postulantAdapter = createEntityAdapter<Postulant>() const postulantAdapter = createEntityAdapter<Postulant>()
const postulantAddSlice = createSlice({ const postulantAddSlice = createSlice({
name: "addPostulant", name: "postulantAdd",
initialState: postulantAdapter.getInitialState({ initialState: postulantAdapter.getInitialState({
readyStatus: "idle", readyStatus: "idle",
} as StateRequest), } as StateRequest),
@ -17,7 +17,7 @@ const postulantAddSlice = createSlice({
}, },
getSuccess: (state, { payload }: PayloadAction<Postulant>) => { getSuccess: (state, { payload }: PayloadAction<Postulant>) => {
state.readyStatus = "success" state.readyStatus = "success"
postulantAdapter.addOne(state, payload) postulantAdapter.setOne(state, payload)
}, },
getFailure: (state, { payload }: PayloadAction<string>) => { getFailure: (state, { payload }: PayloadAction<string>) => {
state.readyStatus = "failure" state.readyStatus = "failure"

View File

@ -7,7 +7,7 @@ import { volunteerPartialAdd } from "../services/volunteersAccessors"
const volunteerAdapter = createEntityAdapter<Volunteer>() const volunteerAdapter = createEntityAdapter<Volunteer>()
const volunteerPartialAddSlice = createSlice({ const volunteerPartialAddSlice = createSlice({
name: "addVolunteer", name: "volunteerAdd",
initialState: volunteerAdapter.getInitialState({ initialState: volunteerAdapter.getInitialState({
readyStatus: "idle", readyStatus: "idle",
} as StateRequest), } as StateRequest),
@ -17,7 +17,7 @@ const volunteerPartialAddSlice = createSlice({
}, },
getSuccess: (state, { payload }: PayloadAction<Volunteer>) => { getSuccess: (state, { payload }: PayloadAction<Volunteer>) => {
state.readyStatus = "success" state.readyStatus = "success"
volunteerAdapter.addOne(state, payload) volunteerAdapter.setOne(state, payload)
}, },
getFailure: (state, { payload }: PayloadAction<string>) => { getFailure: (state, { payload }: PayloadAction<string>) => {
state.readyStatus = "failure" state.readyStatus = "failure"

View File

@ -7,7 +7,7 @@ import { wishAdd } from "../services/wishesAccessors"
const wishAdapter = createEntityAdapter<Wish>() const wishAdapter = createEntityAdapter<Wish>()
const wishAddSlice = createSlice({ const wishAddSlice = createSlice({
name: "addWish", name: "wishAdd",
initialState: wishAdapter.getInitialState({ initialState: wishAdapter.getInitialState({
readyStatus: "idle", readyStatus: "idle",
} as StateRequest), } as StateRequest),

View File

@ -8,7 +8,7 @@ import { wishListGet } from "../services/wishesAccessors"
const wishAdapter = createEntityAdapter<Wish>() const wishAdapter = createEntityAdapter<Wish>()
const wishList = createSlice({ const wishList = createSlice({
name: "getWishList", name: "wishList",
initialState: wishAdapter.getInitialState({ initialState: wishAdapter.getInitialState({
readyStatus: "idle", readyStatus: "idle",
} as StateRequest), } as StateRequest),