diff --git a/src/App.js b/src/App.js index 496f951..edbceb2 100644 --- a/src/App.js +++ b/src/App.js @@ -39,6 +39,7 @@ function App() { const PageCandidatureConseiller = lazy(() => import('./views/candidature-conseiller/PageCandidatureConseiller')); const PageCandidatureStructure = lazy(() => import('./views/candidature-structure/PageCandidatureStructure')); const PageCandidatureCoordinateur = lazy(() => import('./views/candidature-coordinateur/PageCandidatureCoordinateur')); + const PageCandidatureValidee = lazy(() => import('./views/candidature-validee/PageCandidatureValidee')); return (
@@ -49,6 +50,7 @@ function App() { }/> }/> }/> + }/> }/> }/> }/> diff --git a/src/components/commun/Alert.jsx b/src/components/commun/Alert.jsx new file mode 100644 index 0000000..017e7c1 --- /dev/null +++ b/src/components/commun/Alert.jsx @@ -0,0 +1,17 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +export default function Alert({ children, titre }) { + return ( +
+

{titre}

+

{children}

+
+ ); +} + +Alert.propTypes = { + children: PropTypes.node, + titre: PropTypes.string, +}; + diff --git a/src/components/commun/BoutonRadio.jsx b/src/components/commun/BoutonRadio.jsx index e8f0894..d6d4a10 100644 --- a/src/components/commun/BoutonRadio.jsx +++ b/src/components/commun/BoutonRadio.jsx @@ -5,7 +5,7 @@ export default function BoutonRadio({ children, id, nomGroupe }) { return (
- + diff --git a/src/components/commun/Datepicker.jsx b/src/components/commun/Datepicker.jsx index 3858950..58542bd 100644 --- a/src/components/commun/Datepicker.jsx +++ b/src/components/commun/Datepicker.jsx @@ -7,7 +7,7 @@ export default function Datepicker({ children, id, isRequired = true, onChange, - +
); } diff --git a/src/components/commun/Input.jsx b/src/components/commun/Input.jsx index 2b3badd..a69a445 100644 --- a/src/components/commun/Input.jsx +++ b/src/components/commun/Input.jsx @@ -6,7 +6,17 @@ export default function Input({ children, id, isRequired = true, type = 'text',
- +
); diff --git a/src/views/candidature-conseiller/CandidatureConseiller.jsx b/src/views/candidature-conseiller/CandidatureConseiller.jsx index 32ff2ad..8483cf7 100644 --- a/src/views/candidature-conseiller/CandidatureConseiller.jsx +++ b/src/views/candidature-conseiller/CandidatureConseiller.jsx @@ -6,6 +6,7 @@ import Disponibilite from './Disponibilite'; import Motivation from './Motivation'; import EnResume from './EnResume'; import { useScrollToSection } from '../../hooks/useScrollToSection'; +import { useNavigate } from 'react-router-dom'; import '@gouvfr/dsfr/dist/component/form/form.min.css'; import '@gouvfr/dsfr/dist/component/input/input.min.css'; @@ -14,27 +15,45 @@ import '@gouvfr/dsfr/dist/component/radio/radio.min.css'; import '@gouvfr/dsfr/dist/component/badge/badge.min.css'; import '@gouvfr/dsfr/dist/component/notice/notice.min.css'; import '@gouvfr/dsfr/dist/component/sidemenu/sidemenu.min.css'; +import '@gouvfr/dsfr/dist/component/alert/alert.min.css'; import './CandidatureConseiller.css'; import { useApiAdmin } from './useApiAdmin'; +import Alert from '../../components/commun/Alert'; export default function CandidatureConseiller() { const [dateDisponibilite, setDateDisponibilite] = useState(''); const [isSituationValid, setIsSituationValid] = useState(true); - const { creerCandidatureConseiller } = useApiAdmin(); + const [validationError, setValidationError] = useState(); + const { buildConseillerData, creerCandidatureConseiller } = useApiAdmin(); + const navigate = useNavigate(); useScrollToSection(); - const validerLaCandidature = event => { + const estSituationRemplie = formData => { + const demandeurEmploi = formData.get('demandeurEmploi'); + const enEmploi = formData.get('enEmploi'); + const enFormation = formData.get('enFormation'); + const diplome = formData.get('diplome'); + + return demandeurEmploi || enEmploi || enFormation || diplome; + }; + + const validerLaCandidature = async event => { event.preventDefault(); const formData = new FormData(event.currentTarget); - const situations = formData.get('situations'); - if (situations === null) { + if (!estSituationRemplie(formData)) { setIsSituationValid(false); document.getElementById('situation-et-experience').scrollIntoView(); } else { - event.currentTarget.submit(); - creerCandidatureConseiller(); + const conseillerData = buildConseillerData(formData); + const resultatCreation = await creerCandidatureConseiller(conseillerData); + if (resultatCreation.status >= 400) { + const error = await resultatCreation.json(); + setValidationError(error.message); + } else { + navigate('/candidature-validee'); + } } }; @@ -47,6 +66,9 @@ export default function CandidatureConseiller() {

Je veux devenir conseiller numérique

Les champs avec * sont obligatoires.

+ {validationError && + {validationError} + }
({ useLocation: () => ({ hash: '' }), + useNavigate: () => { } })); describe('candidature conseiller', () => { diff --git a/src/views/candidature-conseiller/Disponibilite.jsx b/src/views/candidature-conseiller/Disponibilite.jsx index 1ef67d5..7fcb1e9 100644 --- a/src/views/candidature-conseiller/Disponibilite.jsx +++ b/src/views/candidature-conseiller/Disponibilite.jsx @@ -16,7 +16,7 @@ export default function Disponibilite({ setDateDisponibilite }) {

Accompagnement de personnes vers l’autonomie dans leurs usages de technologies, services et médias numériques.

- setDateDisponibilite(event.target.value)} min={dateDuJour}> + setDateDisponibilite(event.target.value)} min={dateDuJour}> Choisir une date
diff --git a/src/views/candidature-conseiller/SituationEtExperience.jsx b/src/views/candidature-conseiller/SituationEtExperience.jsx index 4b22f1e..82e6bcb 100644 --- a/src/views/candidature-conseiller/SituationEtExperience.jsx +++ b/src/views/candidature-conseiller/SituationEtExperience.jsx @@ -20,7 +20,7 @@ export default function SituationEtExperience({ isSituationValid }) { Êtes-vous actuellement dans l’une des situations suivantes ? *

{situations.map(({ id, libelle }) => - + {libelle} )} diff --git a/src/views/candidature-conseiller/useApiAdmin.js b/src/views/candidature-conseiller/useApiAdmin.js index d24b47f..25d885d 100644 --- a/src/views/candidature-conseiller/useApiAdmin.js +++ b/src/views/candidature-conseiller/useApiAdmin.js @@ -1,18 +1,34 @@ export const useApiAdmin = () => { - const creerCandidatureConseiller = async () => { + const creerCandidatureConseiller = async conseillerData => { const baseUrl = import.meta.env.VITE_APP_API_URL; const requestOptions = { method: 'POST', - headers: { 'Content-Type': 'application/json' } + headers: { 'Content-Type': 'application/json' }, + body: conseillerData }; try { - const result = fetch(`${baseUrl}/candidature-conseiller`, requestOptions); - console.log('===================', result); + return await fetch(`${baseUrl}/candidature-conseiller`, requestOptions); } catch (error) { - console.error(error); + return error; } }; - return { creerCandidatureConseiller }; + const convertStringToBoolean = (conseillerData, key) => { + if (conseillerData[key] === 'on') { + conseillerData[key] = true; + } + }; + + const buildConseillerData = formData => { + const conseillerData = JSON.stringify(Object.fromEntries(formData)); + convertStringToBoolean(conseillerData, 'demandeurEmploi'); + convertStringToBoolean(conseillerData, 'enEmploi'); + convertStringToBoolean(conseillerData, 'enFormation'); + convertStringToBoolean(conseillerData, 'diplome'); + + return conseillerData; + }; + + return { buildConseillerData, creerCandidatureConseiller }; }; diff --git a/src/views/candidature-validee/CandidatureValidee.css b/src/views/candidature-validee/CandidatureValidee.css new file mode 100644 index 0000000..b9fde8f --- /dev/null +++ b/src/views/candidature-validee/CandidatureValidee.css @@ -0,0 +1,10 @@ +.cv-contenu { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; +} + +.cv-titre { + color: var(--blue-france-sun-113-625); +} diff --git a/src/views/candidature-validee/CandidatureValidee.jsx b/src/views/candidature-validee/CandidatureValidee.jsx new file mode 100644 index 0000000..58482c0 --- /dev/null +++ b/src/views/candidature-validee/CandidatureValidee.jsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { useNavigate } from 'react-router-dom'; + +import './CandidatureValidee.css'; + + +export default function CandidatureValidee() { + const navigate = useNavigate(); + + const goToHome = () => { + navigate('/'); + }; + + return ( +
+

👏

+

Merci, votre demande a été envoyée.

+

+ Pour confirmer votre inscription et recevoir des propositions de candidats, veuillez{' '} + consulter l’email qui vient de vous être envoyé. Si vous ne recevez pas cet email dans les prochaines minutes,{' '} + pensez à vérifier votre dossier de spams. +

+ +
+ ); +} diff --git a/src/views/candidature-validee/PageCandidatureValidee.jsx b/src/views/candidature-validee/PageCandidatureValidee.jsx new file mode 100644 index 0000000..9ce714e --- /dev/null +++ b/src/views/candidature-validee/PageCandidatureValidee.jsx @@ -0,0 +1,12 @@ +import React from 'react'; +import Header from '../../components/Header'; +import CandidatureValidee from './CandidatureValidee'; + +export default function PageCandidatureValidee() { + return ( + <> +
+ + + ); +}