From 1d5928cd371dd9b04b9c13e6fb85b9b596d71b6c Mon Sep 17 00:00:00 2001 From: Ornella <68587983+Ornella452@users.noreply.github.com> Date: Thu, 7 Nov 2024 18:04:22 +0100 Subject: [PATCH] gestion conseiller & candidat update infos (#150) --- src/App.js | 2 + src/actions/user.actions.js | 56 ++++++++- .../anonymous/ConfirmationEmailPro.js | 50 ++++++++ src/components/anonymous/ForgottenPassword.js | 2 +- src/components/connected/Home.js | 4 +- src/components/connected/Informations.js | 119 +++++++++++++----- src/components/connected/MonEspace.js | 17 ++- src/reducers/userReducer.js | 18 +++ src/services/user.service.js | 24 ++++ 9 files changed, 249 insertions(+), 43 deletions(-) create mode 100644 src/components/anonymous/ConfirmationEmailPro.js diff --git a/src/App.js b/src/App.js index b99b639..7c211ae 100644 --- a/src/App.js +++ b/src/App.js @@ -6,6 +6,7 @@ import ChoosePassword from './components/anonymous/createAccount/ChoosePassword' import PrivateRoute from './components/connected/PrivateRoute'; import Footer from './components/common/Footer'; import EmailConfirmer from './components/anonymous/ConfirmationEmail'; +import ConfirmationEmailPro from './components/anonymous/ConfirmationEmailPro'; import ForgottenPassword from './components/anonymous/ForgottenPassword'; import CandidatureSupprimee from './components/anonymous/CandidatureSupprimee'; import { useSelector } from 'react-redux'; @@ -26,6 +27,7 @@ function App() { } /> } /> } /> + } /> } /> } /> } /> diff --git a/src/actions/user.actions.js b/src/actions/user.actions.js index 18be144..b1a4c66 100644 --- a/src/actions/user.actions.js +++ b/src/actions/user.actions.js @@ -10,7 +10,9 @@ export const userActions = { inviteAccountsPrefet, forgottenPassword, updateInfosCandidat, + updateInfosConseiller, confirmUserEmail, + confirmUserEmailPro, verifyCode, }; @@ -18,18 +20,17 @@ function login(username, password) { return dispatch => { dispatch(request({ username })); - userService.login(username, password) - .then( + userService.login(username, password).then( data => { data.user.role = data.user.roles[0]; delete data.user.roles; dispatch(success(data)); - if (data.user.role !== 'candidat') { - window.location.pathname = '/login'; - } else { + if (['candidat', 'conseiller'].includes(data.user.role)) { // store user details and jwt token in local storage to keep user logged in between page refreshes localStorage.setItem('user', JSON.stringify(data)); window.location.pathname = '/mon-espace'; + } else { + window.location.pathname = '/login'; } }, error => { @@ -214,6 +215,29 @@ function updateInfosCandidat({ id, infos }) { } } +function updateInfosConseiller({ id, infos }) { + return dispatch => { + dispatch(request()); + userService.updateInfosConseiller(id, infos) + .then( + user => dispatch(success(user)), + error => { + dispatch(failure(error)); + } + ); + }; + + function request() { + return { type: 'UPDATE_USER_EMAIL_REQUEST' }; + } + function success(user) { + return { type: 'UPDATE_USER_EMAIL_SUCCESS', user }; + } + function failure(error) { + return { type: 'UPDATE_USER_EMAIL_FAILURE', error }; + } +} + function confirmUserEmail(token) { return dispatch => { dispatch(request()); @@ -237,6 +261,28 @@ function confirmUserEmail(token) { } } +function confirmUserEmailPro(token) { + return dispatch => { + dispatch(request()); + userService.confirmUserEmailPro(token).then( + user => dispatch(success(user)), + error => { + dispatch(failure(error)); + } + ); + }; + + function request() { + return { type: 'CONFIRMATION_UPDATE_USER_EMAIL_PRO_REQUEST' }; + } + function success(user) { + return { type: 'CONFIRMATION_UPDATE_USER_EMAIL_PRO_SUCCESS', user }; + } + function failure(error) { + return { type: 'CONFIRMATION_UPDATE_USER_EMAIL_PRO_FAILURE', error }; + } +} + function verifyCode(code, email) { return dispatch => { dispatch(request()); diff --git a/src/components/anonymous/ConfirmationEmailPro.js b/src/components/anonymous/ConfirmationEmailPro.js new file mode 100644 index 0000000..5f10070 --- /dev/null +++ b/src/components/anonymous/ConfirmationEmailPro.js @@ -0,0 +1,50 @@ +import React, { useEffect } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { userActions } from '../../actions'; +import Header from '../common/Header'; +import { useNavigate, useParams } from 'react-router-dom'; + +function ConfirmationEmailPro() { + const navigate = useNavigate(); + const { token } = useParams(); + const dispatch = useDispatch(); + const tokenVerifiedOK = useSelector(state => state.user?.isEmailPro); + const tokenVerifiedError = useSelector(state => state.user?.patchError); + + useEffect(() => { + dispatch(userActions.confirmUserEmailPro(token)); + setTimeout(() => { + navigate('/mon-espace'); + }, 7000); + }, []); + + return ( +
+
+
+
+
+ {tokenVerifiedOK && +
+

+ La confirmation de votre e-mail a été effectuée avec succès +   + +

+

Nous allons vous rediriger vers votre espace candidat....

+
+ } + {tokenVerifiedError && +

+ La confirmation de votre e-mail a échoué,
+ veuillez réessayer plus tard +

+ } +
+
+
+
+ ); +} + +export default ConfirmationEmailPro; diff --git a/src/components/anonymous/ForgottenPassword.js b/src/components/anonymous/ForgottenPassword.js index 049d110..dfdb442 100644 --- a/src/components/anonymous/ForgottenPassword.js +++ b/src/components/anonymous/ForgottenPassword.js @@ -119,7 +119,7 @@ function ForgottenPassword() { Désolé mais le lien est invalide ou a déjà été utilisé. } - { tokenVerified && !passwordChoosen && resultVerifyToken?.role === 'candidat' && + { tokenVerified && !passwordChoosen && ['candidat', 'conseiller'].includes(resultVerifyToken?.role) &&
{errorPassword && {errorPassword.error ? errorPassword.error : 'Une erreur s’est produite'}} diff --git a/src/components/connected/Home.js b/src/components/connected/Home.js index 2917564..1526adc 100644 --- a/src/components/connected/Home.js +++ b/src/components/connected/Home.js @@ -27,10 +27,10 @@ function Home() { return ( <> - {user?.role === 'candidat' && (!candidat || candidat?.sexe !== undefined) && + {['candidat', 'conseiller'].includes(user?.role) && (!candidat || candidat?.sexe !== undefined) && } - {user?.role === 'candidat' && candidat && candidat?.sexe === undefined && + {['candidat', 'conseiller'].includes(user?.role) && candidat && candidat?.sexe === undefined && } diff --git a/src/components/connected/Informations.js b/src/components/connected/Informations.js index d17a177..e4a925c 100644 --- a/src/components/connected/Informations.js +++ b/src/components/connected/Informations.js @@ -9,32 +9,53 @@ import '@gouvfr/dsfr/dist/utility/icons/icons-design/icons-design.min.css'; import '@gouvfr/dsfr/dist/utility/icons/icons-system/icons-system.min.css'; import 'react-datepicker/dist/react-datepicker.css'; -function Informations({ infos, setInfos, conseiller }) { +function Informations({ infos, setInfos, infosConseiller, setInfosConseiller, conseiller }) { const dispatch = useDispatch(); const { _id } = useSelector(state => state.authentication.user?.user); const [form, setForm] = useState(false); const activeFormulaire = () => { setForm(true); - setInfos({ - nom: conseiller?.nom, - prenom: conseiller?.prenom, - email: conseiller?.email, - telephone: conseiller?.telephone, - dateDisponibilite: new Date(conseiller?.dateDisponibilite), - }); + if (conseiller.statut === 'RECRUTE') { + setInfosConseiller({ + email: conseiller?.email, + emailPro: conseiller?.emailPro, + telephone: conseiller?.telephone, + dateDisponibilite: new Date(conseiller?.dateDisponibilite), + }); + } else { + setInfos({ + nom: conseiller?.nom, + prenom: conseiller?.prenom, + email: conseiller?.email, + emailPro: conseiller?.emailPro, + telephone: conseiller?.telephone, + dateDisponibilite: new Date(conseiller?.dateDisponibilite), + }); + } }; const handleForm = event => { let { name, value } = event.target; - setInfos({ - ...infos, - [name]: value - }); + if (conseiller.statut === 'RECRUTE') { + setInfosConseiller({ + ...infosConseiller, + [name]: value + }); + } else { + setInfos({ + ...infos, + [name]: value + }); + } }; const updateEmail = () => { - dispatch(userActions.updateInfosCandidat({ id: _id, infos: infos })); + if (conseiller?.statut === 'RECRUTE') { + dispatch(userActions.updateInfosConseiller({ id: _id, infos: infosConseiller })); + } else { + dispatch(userActions.updateInfosCandidat({ id: _id, infos })); + } setForm(false); }; @@ -45,6 +66,8 @@ function Informations({ infos, setInfos, conseiller }) {

Nom : { conseiller?.nom }

Prénom : { conseiller?.prenom }

Email : { conseiller?.email }

+ {conseiller?.statut === 'RECRUTE' && +

Email  professionnel: { conseiller?.emailPro ?? '-'}

}

Téléphone : { conseiller?.telephone }

Disponible à partir du : { dayjs(conseiller?.dateDisponibilite).format('DD/MM/YYYY') }

@@ -91,6 +144,8 @@ function Informations({ infos, setInfos, conseiller }) { Informations.propTypes = { infos: PropTypes.object, setInfos: PropTypes.func, + infosConseiller: PropTypes.object, + setInfosConseiller: PropTypes.func, conseiller: PropTypes.object }; export default Informations; diff --git a/src/components/connected/MonEspace.js b/src/components/connected/MonEspace.js index 279dc19..2cf0e2f 100644 --- a/src/components/connected/MonEspace.js +++ b/src/components/connected/MonEspace.js @@ -34,7 +34,16 @@ function MonEspace() { nom: conseiller?.nom, prenom: conseiller?.prenom, email: conseiller?.email, - telephone: conseiller?.telephone + emailPro: conseiller?.emailPro, + telephone: conseiller?.telephone, + dateDisponibilite: conseiller?.dateDisponibilite + }); + + const [infosConseiller, setInfosConseiller] = useState({ + email: conseiller?.email, + emailPro: conseiller?.emailPro, + telephone: conseiller?.telephone, + dateDisponibilite: conseiller?.dateDisponibilite }); const errorTab = [{ @@ -177,9 +186,11 @@ function MonEspace() {

Mes informations

- + - + {conseiller && conseiller?.statut !== 'RECRUTE' && + + }

Mon Curriculum vitæ

diff --git a/src/reducers/userReducer.js b/src/reducers/userReducer.js index 2c5172c..8fd567e 100644 --- a/src/reducers/userReducer.js +++ b/src/reducers/userReducer.js @@ -38,6 +38,24 @@ export default function user(state = null, action) { patchError: action.error, loading: false }; + case 'CONFIRMATION_UPDATE_USER_EMAIL_PRO_REQUEST': + return { + ...state, + loading: true, + patchError: false + }; + case 'CONFIRMATION_UPDATE_USER_EMAIL_PRO_SUCCESS': + return { + ...state, + isEmailPro: action.user.isEmailPro, + loading: false + }; + case 'CONFIRMATION_UPDATE_USER_EMAIL_PRO_FAILURE': + return { + ...state, + patchError: action.error, + loading: false + }; default: return state; } diff --git a/src/services/user.service.js b/src/services/user.service.js index dcf0070..3565e4e 100644 --- a/src/services/user.service.js +++ b/src/services/user.service.js @@ -6,7 +6,9 @@ export const userService = { verifyToken, choosePassword, updateInfosCandidat, + updateInfosConseiller, confirmUserEmail, + confirmUserEmailPro, sendForgottenPasswordEmail, verifyCode, }; @@ -78,6 +80,18 @@ function updateInfosCandidat(id, infos) { return fetch(uri, requestOptions).then(handleResponse); } +function updateInfosConseiller(id, infos) { + const apiUrlRoot = import.meta.env.VITE_APP_API; + const requestOptions = { + method: 'PATCH', + headers: Object.assign({ 'Content-Type': 'application/json' }, authHeader()), + body: JSON.stringify(infos) + }; + + let uri = `${apiUrlRoot}/conseiller/updateInfosConseiller/${id}`; + return fetch(uri, requestOptions).then(handleResponse); +} + function confirmUserEmail(token) { const apiUrlRoot = import.meta.env.VITE_APP_API; const requestOptions = { @@ -88,6 +102,16 @@ function confirmUserEmail(token) { return fetch(uri, requestOptions).then(handleResponse); } +function confirmUserEmailPro(token) { + const apiUrlRoot = import.meta.env.VITE_APP_API; + const requestOptions = { + method: 'PATCH', + headers: authHeader(), + }; + let uri = `${apiUrlRoot}/conseillers/confirmation-email/${token}`; + return fetch(uri, requestOptions).then(handleResponse); +} + function sendForgottenPasswordEmail(username) { const apiUrlRoot = import.meta.env.VITE_APP_API;