From 33b9796efbe65a0e46ea1c09c6314f5b51d1e28c Mon Sep 17 00:00:00 2001 From: ruddi Date: Tue, 9 Mar 2021 19:08:22 +0530 Subject: [PATCH] fix: Fix profile edit form on submission --- package-lock.json | 13 ++ package.json | 1 + src/PrivateRoute.js | 41 ++-- src/actions/info.js | 142 +++++++------ src/components/App.js | 17 +- src/components/Dashboard.js | 121 +++++------ src/components/Profile.js | 386 ++++++++++++++++++++---------------- 7 files changed, 392 insertions(+), 329 deletions(-) diff --git a/package-lock.json b/package-lock.json index 65b435c..ca4c1cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3771,6 +3771,11 @@ "shallow-clone": "^0.1.2" } }, + "clsx": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", + "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -10914,6 +10919,14 @@ } } }, + "react-toastify": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-7.0.3.tgz", + "integrity": "sha512-cxZ5rfurC8LzcZQMTYc8RHIkQTs+BFur18Pzk6Loz6uS8OXUWm6nXVlH/wqglz4Z7UAE8xxcF5mRjfE13487uQ==", + "requires": { + "clsx": "^1.1.1" + } + }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", diff --git a/package.json b/package.json index b6ef66a..87edd3f 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "react-router-dom": "^5.2.0", "react-router-redux": "^4.0.8", "react-scripts": "3.4.1", + "react-toastify": "^7.0.3", "redux": "^4.0.5", "redux-api-middleware": "^3.2.1", "redux-persist": "^6.0.0", diff --git a/src/PrivateRoute.js b/src/PrivateRoute.js index 1d5a022..8c31f76 100644 --- a/src/PrivateRoute.js +++ b/src/PrivateRoute.js @@ -1,22 +1,27 @@ -import React, { Component } from 'react' -import { Route, Redirect } from 'react-router-dom' -import Menubar from './components/Menubar' -import Navbar from './components/Navbar' -import { login } from './urls' +import React, { Component } from "react"; +import { Route, Redirect } from "react-router-dom"; +import Menubar from "./components/Menubar"; +import Navbar from "./components/Navbar"; +import { login } from "./urls"; +import { ToastContainer } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; export const PrivateRoute = ({ component: Component, ...rest }) => ( - <> - - ( - localStorage.getItem('token') - ? - ( - <> - + <> + + + + localStorage.getItem("token") ? ( + <> + - + + ) : ( + ) - : - )} /> - -) + } + /> + +); diff --git a/src/actions/info.js b/src/actions/info.js index e0b348f..cfec866 100644 --- a/src/actions/info.js +++ b/src/actions/info.js @@ -1,80 +1,74 @@ -import axios from 'axios' +import axios from "axios"; +import { urlInfo, urlPatchInfo } from "../urls"; import { - urlInfo, - urlPatchInfo -} from '../urls' -import { - GET_USER_INFO, - POST_USER_INFO, - UPDATE_USER_INFO, - USER_INFO_ERRORS -} from './types' + GET_USER_INFO, + POST_USER_INFO, + UPDATE_USER_INFO, + USER_INFO_ERRORS, +} from "./types"; -export const getInfo = () => async dispatch => { - try { - const config = { - headers: { - Authorization: `Bearer ${localStorage.token}`, - } - } - const res = await axios.get(urlInfo(), config); - dispatch({ - type: GET_USER_INFO, - payload: res.data - }); - } - catch (err) { - dispatch({ - type: USER_INFO_ERRORS, - payload: err.response.data - }) - } -} +export const getInfo = () => async (dispatch) => { + try { + const config = { + headers: { + Authorization: `Bearer ${localStorage.token}`, + }, + }; + const res = await axios.get(urlInfo(), config); + dispatch({ + type: GET_USER_INFO, + payload: res.data, + }); + } catch (err) { + dispatch({ + type: USER_INFO_ERRORS, + payload: err.response.data, + }); + } +}; -export const postInfo = (data, callback) => async dispatch => { - try { - const config = { - headers: { - 'content-type': 'application/json', - Authorization: `Bearer ${localStorage.token}`, - } - } - const res = await axios.post(urlInfo(), data, config); - dispatch({ - type: POST_USER_INFO, - payload: res.data - }); - callback() - } - catch (err) { - dispatch({ - type: USER_INFO_ERRORS, - payload: err.response.data - }); - callback() - } +export const postInfo = (data, callback, success) => async (dispatch) => { + try { + const config = { + headers: { + "content-type": "application/json", + Authorization: `Bearer ${localStorage.token}`, + }, + }; + const res = await axios.post(urlInfo(), data, config); + dispatch({ + type: POST_USER_INFO, + payload: res.data, + }); + success(); + } catch (err) { + dispatch({ + type: USER_INFO_ERRORS, + payload: err.response.data, + }); + callback(); + } }; -export const patchInfo = (id, data, callback) => async dispatch => { - try { - const config = { - headers: { - 'content-type': 'application/json', - Authorization: `Bearer ${localStorage.token}`, - } - } - const res = await axios.patch(urlPatchInfo(id), data, config); - dispatch({ - type: UPDATE_USER_INFO, - payload: res.data - }); - callback() - } - catch (err) { - dispatch({ - type: USER_INFO_ERRORS, - payload: err.response.data - }); - callback() - } +export const patchInfo = (id, data, callback, success) => async (dispatch) => { + try { + const config = { + headers: { + "content-type": "application/json", + Authorization: `Bearer ${localStorage.token}`, + }, + }; + const res = await axios.patch(urlPatchInfo(id), data, config); + dispatch({ + type: UPDATE_USER_INFO, + payload: res.data, + }); + success(); + } catch (err) { + dispatch({ + type: USER_INFO_ERRORS, + payload: err.response.data, + }); + callback(); + } }; diff --git a/src/components/App.js b/src/components/App.js index 500b2c2..e5e63f4 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -1,22 +1,19 @@ -import React, { Component } from 'react' -import { Route, Switch, Router } from 'react-router-dom' -import Routes from '../Routes' -import { history } from '../store' -import '../styles/App.css' +import React, { Component } from "react"; +import { Route, Switch, Router } from "react-router-dom"; +import Routes from "../Routes"; +import { history } from "../store"; +import "../styles/App.css"; export default class App extends Component { render() { return ( -
+
-
- ) + ); } } - - diff --git a/src/components/Dashboard.js b/src/components/Dashboard.js index 69f59b6..6ab4be0 100644 --- a/src/components/Dashboard.js +++ b/src/components/Dashboard.js @@ -1,62 +1,69 @@ -import React, { Component } from 'react' -import '../styles/Dashboard.css' -import { Item, Card, Header, Divider, Icon } from 'semantic-ui-react' -import Profile from './Profile' -import Zulip from './Zulip' +import React, { Component } from "react"; +import "../styles/Dashboard.css"; +import { Item, Card, Header, Divider, Icon } from "semantic-ui-react"; +import Profile from "./Profile"; +import Zulip from "./Zulip"; export default class Dashboard extends Component { - constructor(props) { - super(props) - this.state = { - edit: false - } - } + constructor(props) { + super(props); + this.state = { + edit: false, + }; + } - handleEdit = () => { - this.setState({ - edit: !this.state.edit - }) - } + handleEdit = () => { + this.setState({ + edit: !this.state.edit, + }); + }; - render() { - return ( -
-
- {/* render profile details and list of forms filled by user */} - - - - -
- Profile - -
-
- - - -
-
- - - -
Forms Filled
-
-
-
-
-
- {/* render components for Zulip and Github stats */} - - - - - - - - -
-
- ) - } + render() { + return ( +
+
+ {/* render profile details and list of forms filled by user */} + + + + +
+ Profile + +
+
+ + + +
+
+ + + +
Forms Filled
+
+
+
+
+
+ {/* render components for Zulip and Github stats */} + + + + + + + + +
+
+ ); + } } diff --git a/src/components/Profile.js b/src/components/Profile.js index 2f52cff..a7105e5 100644 --- a/src/components/Profile.js +++ b/src/components/Profile.js @@ -1,187 +1,233 @@ -import React, { Component } from 'react' -import { connect } from 'react-redux' -import { getInfo, postInfo, patchInfo } from '../actions/info' -import PropTypes from 'prop-types' -import { Form, Message } from 'semantic-ui-react' -import '../styles/Profile.css' +import React, { Component } from "react"; +import { connect } from "react-redux"; +import { getInfo, postInfo, patchInfo } from "../actions/info"; +import PropTypes from "prop-types"; +import { toast } from "react-toastify"; +import { Form, Message } from "semantic-ui-react"; +import "../styles/Profile.css"; class Profile extends Component { - constructor(props) { - super(props) - this.state = { - name: '', - zulip_id: null, - update: false, - error: null, - submitted: false - } - } + constructor(props) { + super(props); + this.state = { + name: "", + zulip_id: null, + update: false, + error: null, + submitted: false, + }; + } - componentDidMount() { - this.props.getInfo() - } + componentDidMount() { + this.props.getInfo(); + } - submitInfo = () => { - if(!this.state.update) { - const data = { - name: this.state.name, - zulip_id: this.state.zulip_id - } - this.props.postInfo(data, this.callback) - this.setState({ - update: true - }) - } - else { - const data = { - name: this.state.name - } - this.props.patchInfo(this.props.userinfoid, data, this.callback) - } + submitInfo = () => { + if (!this.state.update) { + const data = { + name: this.state.name, + zulip_id: this.state.zulip_id, + }; + this.props.postInfo(data, this.callback, this.success); + this.setState({ + update: true, + }); + } else { + const data = { + name: this.state.name, + }; + this.props.patchInfo( + this.props.userinfoid, + data, + this.callback, + this.success + ); } + }; - callback = () => { - this.setState({ - error: this.props.userinfoerror?true:false, - submitted: true - }) - setTimeout(() => { - this.setState({ - error: null, - submitted: false - }) - }, 5000) - } + callback = () => { + this.setState({ + error: this.props.userinfoerror ? true : false, + submitted: true, + }); + toast.error("Unsuccessful"); + setTimeout(() => { + this.setState({ + error: null, + submitted: false, + }); + }, 5000); + }; + success = () => { + this.props.handleEdit(); + toast.success("Succesful"); + }; - onChange = (e) => { - this.setState({ [e.target.name]: e.target.value}); - } + onChange = (e) => { + this.setState({ [e.target.name]: e.target.value }); + }; - render() { - const { userinfo } = this.props - { - userinfo && userinfo.length === 1 ? this.state.update = true : this.state.update = false - } - return ( - <> - { - userinfo && userinfo.length === 1 ? - userinfo.map(userinfo => -
- { - this.props.edit === true ? -
- - - - - SUBMIT - - - : -
- Name: {userinfo.name}
- Email: {userinfo.user.email}
- Role: {userinfo.user_type}
- Zulip ID: {userinfo.zulip_id} -
+ render() { + const { userinfo } = this.props; + { + userinfo && userinfo.length === 1 + ? (this.state.update = true) + : (this.state.update = false); + } + return ( + <> + {userinfo && userinfo.length === 1 ? ( + userinfo.map((userinfo) => ( +
+ {this.props.edit === true ? ( +
+ - ) - : - <> - { - this.props.edit === true ? - <> + onChange={this.onChange} + label="Name" + placeholder="Enter your name..." + fluid + /> + + + {this.state.error && ( - - - - - - - SUBMIT - - - - : You have not filled in your basic information till now. - } - - } - - ) - } + )} + + SUBMIT + + + ) : ( +
+ + Name: + {userinfo.name} + +
+ + Email: + {userinfo.user.email} + +
+ + Role: + {userinfo.user_type} + +
+ + Zulip ID: + {userinfo.zulip_id} + +
+ )} +
+ )) + ) : ( + <> + {this.props.edit === true ? ( + <> + +
+ + + + + {this.state.error && ( + + )} + + SUBMIT + + + + ) : ( + + You have not filled in your basic information till now. + + )} + + )} + + ); + } } Profile.propTypes = { - postInfo: PropTypes.func.isRequired, - patchInfo: PropTypes.func.isRequired + postInfo: PropTypes.func.isRequired, + patchInfo: PropTypes.func.isRequired, }; -const mapStateToProps = state => ({ - userinfo: state.info.userinfo, - userinfoerror: state.info.userinfoerror, - userinfoid: state.info.userinfoid, -}) +const mapStateToProps = (state) => ({ + userinfo: state.info.userinfo, + userinfoerror: state.info.userinfoerror, + userinfoid: state.info.userinfoid, +}); -export default connect( - mapStateToProps, - { getInfo, postInfo, patchInfo } -)(Profile) +export default connect(mapStateToProps, { getInfo, postInfo, patchInfo })( + Profile +);