diff --git a/package-lock.json b/package-lock.json
index 86bc6073..9a35f959 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10502,6 +10502,27 @@
"integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==",
"dev": true
},
+ "formik": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/formik/-/formik-2.2.6.tgz",
+ "integrity": "sha512-Kxk2zQRafy56zhLmrzcbryUpMBvT0tal5IvcifK5+4YNGelKsnrODFJ0sZQRMQboblWNym4lAW3bt+tf2vApSA==",
+ "requires": {
+ "deepmerge": "^2.1.1",
+ "hoist-non-react-statics": "^3.3.0",
+ "lodash": "^4.17.14",
+ "lodash-es": "^4.17.14",
+ "react-fast-compare": "^2.0.1",
+ "tiny-warning": "^1.0.2",
+ "tslib": "^1.10.0"
+ },
+ "dependencies": {
+ "deepmerge": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz",
+ "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA=="
+ }
+ }
+ },
"forwarded": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
@@ -18468,6 +18489,11 @@
"integrity": "sha512-HvPuUQnLp5H7TouGq3kzBeioJmXms1wHy9EGjz2OURWBp4qZO6AfGEcnxts1D/CbwPLRAgTMPCEgYhA3sEM4vw==",
"dev": true
},
+ "react-fast-compare": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz",
+ "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw=="
+ },
"react-focus-lock": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.5.0.tgz",
diff --git a/package.json b/package.json
index 72e5cfff..46bd3de2 100644
--- a/package.json
+++ b/package.json
@@ -47,6 +47,7 @@
"classnames": "^2.2.6",
"extract-react-intl-messages": "^4.1.1",
"form-urlencoded": "^4.2.1",
+ "formik": "^2.2.6",
"lodash.camelcase": "^4.3.0",
"lodash.snakecase": "^4.1.1",
"prop-types": "15.7.2",
diff --git a/src/forgot-password/ForgotPasswordPage.jsx b/src/forgot-password/ForgotPasswordPage.jsx
index 7b4d3980..165fd6e2 100644
--- a/src/forgot-password/ForgotPasswordPage.jsx
+++ b/src/forgot-password/ForgotPasswordPage.jsx
@@ -1,10 +1,16 @@
-import React, { useState } from 'react';
+import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Redirect } from 'react-router-dom';
-import { Input, StatefulButton, ValidationFormGroup } from '@edx/paragon';
+import {
+ Form,
+ Input,
+ StatefulButton,
+ ValidationFormGroup,
+} from '@edx/paragon';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
+import { Formik } from 'formik';
import messages from './messages';
import { forgotPassword } from './data/actions';
import { forgotPasswordResultSelector } from './data/selectors';
@@ -12,87 +18,89 @@ import RequestInProgressAlert from './RequestInProgressAlert';
import { LOGIN_PAGE } from '../data/constants';
import LoginHelpLinks from '../logistration/LoginHelpLinks';
+const validateEmail = (e, values, setFieldValue) => {
+ const inputEmail = e.target.value;
+ const isEmailValid = inputEmail.match(/^([\w.%+-]+)@([\w-]+\.)+([\w]{2,})$/i);
+ setFieldValue('email', inputEmail);
+ setFieldValue('isEmailValid', isEmailValid !== null);
+};
+
const ForgotPasswordPage = (props) => {
const { intl, status } = props;
- const [emailInput, setEmailValue] = useState('');
- const [emailValid, setEmailValidValue] = useState(true);
-
- const validateEmail = (email) => {
- const isEmailValid = email.match(/^([\w.%+-]+)@([\w-]+\.)+([\w]{2,})$/i);
- setEmailValidValue(isEmailValid !== null);
- };
-
- const handleOnChange = (e) => {
- const emailValue = e.target.value;
- setEmailValue(emailValue);
- validateEmail(emailValue);
- };
-
- const handleSubmit = (e) => {
- e.preventDefault();
- if (emailInput === '') {
- setEmailValidValue(false);
- }
- if (emailValid && emailInput !== '') {
- props.forgotPassword(emailInput);
- }
- };
return (
- <>
- {status === 'complete' ?