Skip to content

Commit

Permalink
gestion conseiller & candidat update infos (#150)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ornella452 authored Nov 7, 2024
1 parent 1f9d0dc commit 1d5928c
Show file tree
Hide file tree
Showing 9 changed files with 249 additions and 43 deletions.
2 changes: 2 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -26,6 +27,7 @@ function App() {
<Route path="/login" element={<Login />} />
<Route path="/inscription/:token" element={<ChoosePassword />} />
<Route path="/candidat/confirmation-email/:token" element={<EmailConfirmer />} />
<Route path="/conseillers/confirmation-email/:token" element={<ConfirmationEmailPro />} />
<Route path="/mot-de-passe-oublie" element={<ForgottenPassword />} />
<Route path="/renouveler-mot-de-passe/:token" element={<ForgottenPassword />} />
<Route path="/candidature-supprimee" element={<CandidatureSupprimee />} />
Expand Down
56 changes: 51 additions & 5 deletions src/actions/user.actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,27 @@ export const userActions = {
inviteAccountsPrefet,
forgottenPassword,
updateInfosCandidat,
updateInfosConseiller,
confirmUserEmail,
confirmUserEmailPro,
verifyCode,
};

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 => {
Expand Down Expand Up @@ -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());
Expand All @@ -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());
Expand Down
50 changes: 50 additions & 0 deletions src/components/anonymous/ConfirmationEmailPro.js
Original file line number Diff line number Diff line change
@@ -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 (
<div>
<Header/>
<div className="">
<div className="fr-grid-row fr-grid-row--center fr-mt-8w">
<div style={{ width: '50%', textAlign: 'center' }}>
{tokenVerifiedOK &&
<div>
<p className="fr-label flashBag" style={{ fontSize: '16px' }}>
La confirmation de votre e-mail a été effectuée avec succès
&nbsp;
<i className="ri-check-line ri-xl" style={{ verticalAlign: 'middle' }}></i>
</p>
<h4>Nous allons vous rediriger vers votre espace candidat....</h4>
</div>
}
{tokenVerifiedError &&
<p className="fr-label flashBag labelError" style={{ fontSize: '16px' }}>
La confirmation de votre e-mail a échoué, <br/>
veuillez réessayer plus tard
</p>
}
</div>
</div>
</div>
</div>
);
}

export default ConfirmationEmailPro;
2 changes: 1 addition & 1 deletion src/components/anonymous/ForgottenPassword.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ function ForgottenPassword() {
<span>Désolé mais le lien est invalide ou a déjà été utilisé.</span>
}

{ tokenVerified && !passwordChoosen && resultVerifyToken?.role === 'candidat' &&
{ tokenVerified && !passwordChoosen && ['candidat', 'conseiller'].includes(resultVerifyToken?.role) &&
<div>
<div>
{errorPassword && <span>{errorPassword.error ? errorPassword.error : 'Une erreur s’est produite'}</span>}
Expand Down
4 changes: 2 additions & 2 deletions src/components/connected/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ function Home() {

return (
<>
{user?.role === 'candidat' && (!candidat || candidat?.sexe !== undefined) &&
{['candidat', 'conseiller'].includes(user?.role) && (!candidat || candidat?.sexe !== undefined) &&
<Connected />
}
{user?.role === 'candidat' && candidat && candidat?.sexe === undefined &&
{['candidat', 'conseiller'].includes(user?.role) && candidat && candidat?.sexe === undefined &&
<FormulaireSexeAge />
}
</>
Expand Down
119 changes: 87 additions & 32 deletions src/components/connected/Informations.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};

Expand All @@ -45,6 +66,8 @@ function Informations({ infos, setInfos, conseiller }) {
<p className="info-candidat">Nom&nbsp;: <strong>{ conseiller?.nom }</strong></p>
<p className="info-candidat">Prénom&nbsp;: { conseiller?.prenom }</p>
<p className="info-candidat">Email&nbsp;: { conseiller?.email }</p>
{conseiller?.statut === 'RECRUTE' &&
<p className="info-candidat">Email&nbsp; professionnel: { conseiller?.emailPro ?? '-'}</p>}
<p>Téléphone&nbsp;: { conseiller?.telephone }</p>
<p>Disponible à partir du&nbsp;: { dayjs(conseiller?.dateDisponibilite).format('DD/MM/YYYY') }</p>
<button className="fr-btn fr-mt-6w fr-mb-1w" onClick={activeFormulaire}>
Expand All @@ -55,25 +78,55 @@ function Informations({ infos, setInfos, conseiller }) {
<div className="fr-container--fluid">
<div className="fr-grid-row">
<form className="fr-my-3w fr-col-10 fr-col-lg-8">
<label className="fr-label">Nom</label>
<input className="fr-input" type="text" id="text-input-nom" name="nom" value={infos?.nom} onChange={handleForm}/>
<label className="fr-label">Prénom</label>
<input className="fr-input" type="text" id="text-input-prenom" name="prenom" value={infos?.prenom} onChange={handleForm}/>
<label className="fr-label">E-mail</label>
<input className="fr-input" type="text" id="text-input-email" name="email" value={infos?.email} onChange={handleForm}/>
<label className="fr-label">Téléphone</label>
<input className="fr-input" type="text" id="text-input-telephone" maxLength="20" name="telephone" value={infos?.telephone} onChange={handleForm}/>
<label className="fr-label">Disponible à partir du</label>
<DatePicker
name="dateDisponibilite"
className="fr-input fr-my-2w"
dateFormat="dd/MM/yyyy"
locale="fr"
selected={infos?.dateDisponibilite ?? ''}
onChange={date => setInfos({ ...infos, dateDisponibilite: date })}
minDate={new Date()}
onKeyDown={e => e.preventDefault()}
/>
{conseiller?.statut === 'RECRUTE' && <>
<label className="fr-label">Nom</label>
<input className="fr-input" disabled type="text" id="text-input-nom" name="nom" value={conseiller.nom} />
<label className="fr-label">Prénom</label>
<input className="fr-input" disabled type="text" id="text-input-prenom" name="prenom" value={conseiller.prenom} />
<label className="fr-label">E-mail</label>
<input className="fr-input" type="text" id="text-input-email" name="email" value={infosConseiller?.email} onChange={handleForm} />
<label className="fr-label">E-mail professionnel</label>
<input className="fr-input" type="text" id="text-input-email" name="emailPro" value={infosConseiller?.emailPro} onChange={handleForm} />
<label className="fr-label">Téléphone</label>
<input className="fr-input" type="text" id="text-input-telephone"
maxLength="20" name="telephone" value={infosConseiller?.telephone} onChange={handleForm} />
<label className="fr-label">Disponible à partir du</label>
<DatePicker
name="dateDisponibilite"
className="fr-input fr-my-2w"
dateFormat="dd/MM/yyyy"
locale="fr"
selected={infosConseiller?.dateDisponibilite ?? ''}
onChange={date => setInfosConseiller({ ...infosConseiller, dateDisponibilite: date })}
minDate={new Date()}
onKeyDown={e => e.preventDefault()}
/>
</>
}

{conseiller.statut !== 'RECRUTE' && <>
<label className="fr-label">Nom</label>
<input className="fr-input" type="text" id="text-input-nom" name="nom" value={infos?.nom} onChange={handleForm} />
<label className="fr-label">Prénom</label>
<input className="fr-input" type="text" id="text-input-prenom" name="prenom" value={infos?.prenom} onChange={handleForm} />
<label className="fr-label">E-mail</label>
<input className="fr-input" type="text" id="text-input-email" name="email" value={infos?.email} onChange={handleForm} />
<label className="fr-label">Téléphone</label>
<input className="fr-input" type="text" id="text-input-telephone"
maxLength="20" name="telephone" value={infos?.telephone} onChange={handleForm} />
<label className="fr-label">Disponible à partir du</label>
<DatePicker
name="dateDisponibilite"
className="fr-input fr-my-2w"
dateFormat="dd/MM/yyyy"
locale="fr"
selected={infos?.dateDisponibilite ?? ''}
onChange={date => setInfos({ ...infos, dateDisponibilite: date })}
minDate={new Date()}
onKeyDown={e => e.preventDefault()}
/>
</>
}
</form>
<div className="fr-col-5">
<button onClick={() => setForm(false)} className="fr-btn red-btn info-btn fr-mb-1w">Annuler</button>
Expand All @@ -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;
17 changes: 14 additions & 3 deletions src/components/connected/MonEspace.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [{
Expand Down Expand Up @@ -177,9 +186,11 @@ function MonEspace() {
<div className="fr-grid-row">
<div className="fr-col-12 fr-col-lg-6">
<h2 className="fr-mb-7w">Mes informations</h2>
<Informations infos={infos} setInfos={setInfos} conseiller={conseiller} />
<Informations infosConseiller={infosConseiller} setInfosConseiller={setInfosConseiller} infos={infos} setInfos={setInfos} conseiller={conseiller} />
<UpdateDisponibilite conseiller={conseiller} />
<SupprimerCandidature conseiller={conseiller} />
{conseiller && conseiller?.statut !== 'RECRUTE' &&
<SupprimerCandidature conseiller={conseiller} />
}
</div>
<div className="fr-col-12 fr-col-lg-6" >
<h2 className="fr-mb-7w">Mon Curriculum vit&aelig;</h2>
Expand Down
18 changes: 18 additions & 0 deletions src/reducers/userReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Loading

0 comments on commit 1d5928c

Please sign in to comment.