From ca718632cd5f006faf23948791df7f52d176a86a Mon Sep 17 00:00:00 2001 From: Hardik Choudhary Date: Sat, 18 Nov 2023 00:12:43 +0530 Subject: [PATCH 1/2] Converted Form into functional component --- .../components/onboarding/form.jsx | 255 +++++++++++------- 1 file changed, 161 insertions(+), 94 deletions(-) diff --git a/app/assets/javascripts/components/onboarding/form.jsx b/app/assets/javascripts/components/onboarding/form.jsx index 7434c3b58c..41be0012df 100644 --- a/app/assets/javascripts/components/onboarding/form.jsx +++ b/app/assets/javascripts/components/onboarding/form.jsx @@ -1,119 +1,186 @@ -import React from 'react'; -import createReactClass from 'create-react-class'; +import React, { useEffect, useRef, useState } from 'react'; import PropTypes from 'prop-types'; import withRouter from '../util/withRouter'; import { connect } from 'react-redux'; - +import { useNavigate } from 'react-router-dom'; import OnboardAPI from '../../utils/onboarding_utils.js'; -import { addNotification } from '../../actions/notification_actions.js'; +import { addNotification as notify } from '../../actions/notification_actions.js'; const isEnrollUrl = (returnToParam) => { - if (returnToParam.includes('/enroll')) { return true; } - if (returnToParam.includes('%2Fenroll')) { return true; } + if (returnToParam.includes('/enroll')) { + return true; + } + if (returnToParam.includes('%2Fenroll')) { + return true; + } return false; }; -const Form = createReactClass({ - propTypes: { - currentUser: PropTypes.object, - returnToParam: PropTypes.string, - addNotification: PropTypes.func - }, - - getInitialState() { - const user = this.props.currentUser; - return { - started: false, - user, - name: user.real_name, - email: user.email, - instructor: (user.permissions !== null) ? String(user.permission === 2) : null - }; - }, +const Form = ({ currentUser, returnToParam, addNotification }) => { + const [state, setState] = useState({ + started: false, + user: currentUser, + name: currentUser.real_name, + email: currentUser.email, + instructor: + currentUser.permissions !== null + ? String(currentUser.permission === 2) + : null, + sending: false, + }); + + const [instructorFormClass, setInstructorFormClass] = useState(''); + + const [submitText, setSubmitText] = useState('Submit'); + const [disabled, setDisabled] = useState(false); + + const navigate = useNavigate(); // Update state when input fields change - _handleFieldChange(field, e) { - const obj = {}; - obj[field] = e.target.value; - return this.setState(obj); - }, + const handleFieldChange = (field, e) => { + setState(prevState => ({ + ...prevState, + [field]: e.target.value, + })); + }; - _handleSubmit(e) { + const formRef = useRef(); + + const handleSubmit = async (e) => { e.preventDefault(); - this.setState({ sending: true }); - this.state.user.instructor = this.state.instructor === 'true'; - return OnboardAPI.onboard({ - real_name: this.state.name, - email: this.state.email, - instructor: this.state.instructor === 'true' - }) - .then(() => { - const destination = this.state.instructor === 'true' ? 'supplementary' : 'permissions'; - return this.props.router.navigate(`/onboarding/${destination}?return_to=${decodeURIComponent(this.props.returnToParam)}`); - } - ) - .catch(() => { - this.props.addNotification({ + setState(prevState => ({ ...prevState, sending: true })); + state.user.instructor = state.instructor === 'true'; + try { + await OnboardAPI.onboard({ + real_name: state.name, + email: state.email, + instructor: state.instructor === 'true', + }); + + const destination = state.instructor === 'true' ? 'supplementary' : 'permissions'; + + navigate( + `/onboarding/${destination}?return_to=${decodeURIComponent( + returnToParam + )}` + ); + } catch (err) { + addNotification({ message: I18n.t('error_500.explanation'), closable: true, - type: 'error' + type: 'error', }); - this.setState({ sending: false }); - }); - }, + setState(prevState => ({ ...prevState, sending: false })); + } + }; - render() { - const submitText = this.state.sending ? 'Sending' : 'Submit'; - const disabled = this.state.sending; + useEffect(() => { + setSubmitText(state.sending ? 'Sending' : 'Submit'); + setDisabled(state.sending); + }, [state]); + useEffect(() => { // Hide the 'are you an instructor' question if user is returning to an enrollment URL. // That means they are trying to join a course as a student, so assume that they are one. - const instructorFormClass = isEnrollUrl(this.props.returnToParam) ? 'form-group hidden' : 'form-group'; - - return ( -
-

Let’s get some business out of the way.

-
-
- - -

- Your real name is not public. It is only seen by you, your instructor, and Wiki Education admins. -

-
-
- - -

- Your email is only used for notifications and will not be shared. -

-
-
- -
-
- -
-
- -
+ setInstructorFormClass( + isEnrollUrl(returnToParam) ? 'form-group hidden' : 'form-group' + ); + }, [returnToParam]); + + return ( +
+

Let's get some business out of the way.

+ handleSubmit(e)} ref={formRef}> +
+ + handleFieldChange('name', e)} + /> +

+ Your real name is not public. It is only seen by you, your + instructor, and Wiki Education admins. +

+
+
+ + handleFieldChange('email', e)} + /> +

+ Your email is only used for notifications and will not be shared. +

+
+
+ +
+
+ +
+
+
- - -
- ); - } -}); +
+ + +
+ ); +}; + +Form.propTypes = { + currentUser: PropTypes.object, + returnToParam: PropTypes.string, + addNotification: PropTypes.func, +}; -const mapDispatchToProps = { addNotification }; +const mapDispatchToProps = { notify }; export default withRouter(connect(null, mapDispatchToProps)(Form)); From 4d5dd89737c0e0ced66f2cd0f5b9d3f0651db085 Mon Sep 17 00:00:00 2001 From: Hardik Choudhary Date: Sat, 18 Nov 2023 00:58:42 +0530 Subject: [PATCH 2/2] Using props object instead of destructuring individual props --- .../components/onboarding/form.jsx | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/app/assets/javascripts/components/onboarding/form.jsx b/app/assets/javascripts/components/onboarding/form.jsx index 41be0012df..83871d2d5f 100644 --- a/app/assets/javascripts/components/onboarding/form.jsx +++ b/app/assets/javascripts/components/onboarding/form.jsx @@ -4,7 +4,7 @@ import withRouter from '../util/withRouter'; import { connect } from 'react-redux'; import { useNavigate } from 'react-router-dom'; import OnboardAPI from '../../utils/onboarding_utils.js'; -import { addNotification as notify } from '../../actions/notification_actions.js'; +import { addNotification } from '../../actions/notification_actions.js'; const isEnrollUrl = (returnToParam) => { if (returnToParam.includes('/enroll')) { @@ -16,15 +16,15 @@ const isEnrollUrl = (returnToParam) => { return false; }; -const Form = ({ currentUser, returnToParam, addNotification }) => { +const Form = (props) => { const [state, setState] = useState({ started: false, - user: currentUser, - name: currentUser.real_name, - email: currentUser.email, + user: props.currentUser, + name: props.currentUser.real_name, + email: props.currentUser.email, instructor: - currentUser.permissions !== null - ? String(currentUser.permission === 2) + props.currentUser.permissions !== null + ? String(props.currentUser.permission === 2) : null, sending: false, }); @@ -61,11 +61,11 @@ const Form = ({ currentUser, returnToParam, addNotification }) => { navigate( `/onboarding/${destination}?return_to=${decodeURIComponent( - returnToParam + props.returnToParam )}` ); } catch (err) { - addNotification({ + props.addNotification({ message: I18n.t('error_500.explanation'), closable: true, type: 'error', @@ -83,9 +83,9 @@ const Form = ({ currentUser, returnToParam, addNotification }) => { // Hide the 'are you an instructor' question if user is returning to an enrollment URL. // That means they are trying to join a course as a student, so assume that they are one. setInstructorFormClass( - isEnrollUrl(returnToParam) ? 'form-group hidden' : 'form-group' + isEnrollUrl(props.returnToParam) ? 'form-group hidden' : 'form-group' ); - }, [returnToParam]); + }, [props.returnToParam]); return (
@@ -181,6 +181,6 @@ Form.propTypes = { addNotification: PropTypes.func, }; -const mapDispatchToProps = { notify }; +const mapDispatchToProps = { addNotification }; export default withRouter(connect(null, mapDispatchToProps)(Form));