diff --git a/client/actions/api.js b/client/actions/api.js index 173d4eb..7c2b843 100644 --- a/client/actions/api.js +++ b/client/actions/api.js @@ -1,7 +1,7 @@ let api = '/api/v1'; if (process.env.NODE_ENV === 'development') { - api = 'http://localhost:5000/api/v1'; + api = 'http://localhost:4000/api/v1'; } /** diff --git a/client/components/App.jsx b/client/components/App.jsx index 024d944..4e9e241 100644 --- a/client/components/App.jsx +++ b/client/components/App.jsx @@ -13,8 +13,7 @@ import BookDetail from './library/BookDetail'; import Dashboard from './dashboard/Dashboard'; import Logout from './auth/Logout'; // import ForgotPassword from './forgotPassword'; -// -// import UpdateProfile from './dashboard/UpdateProfile'; +import UpdateProfile from './dashboard/UpdateProfile'; import mock from './mock'; @@ -28,7 +27,7 @@ import mock from './mock'; class App extends Component { /** * Creates an instance of App. - * @param {Object} props + * @param {Object} props * @memberof App */ constructor(props) { @@ -38,7 +37,7 @@ class App extends Component { } /** * renders app to DOM - * + * * @returns {JSX} JSX representation of component * @memberof App */ @@ -49,7 +48,7 @@ class App extends Component { - {/* */} + diff --git a/client/components/auth/Login.js b/client/components/auth/Login.js new file mode 100644 index 0000000..e3a489c --- /dev/null +++ b/client/components/auth/Login.js @@ -0,0 +1,179 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { Link, Redirect } from 'react-router-dom'; +import { connect } from 'react-redux'; +import { Row } from 'react-materialize'; +import GoogleLogin from 'react-google-login'; +import FaGoogle from 'react-icons/lib/fa/google'; + +import Header from '../header/Header'; +import { login } from '../../actions/login'; +import Loading from '../Loading'; + + +const Materialize = window.Materialize; + +/* + eslint-disable + */ +class Login extends Component { + constructor(props) { + super(props); + this.state = { + username: '', + password: '', + }; + this.handleLogin = this.handleLogin.bind(this); + this.handleChange = this.handleChange.bind(this); + this.responseGoogle = this.responseGoogle.bind(this); + } + + responseGoogle(response) { + // const loginProfile = response.getBasicProfile(); + console.log(response); + } + + handleLogin(event) { + event.preventDefault(); + this.setState({ isLoading: true }); + this.props.login(this.state) + .then( + (data) => { + Materialize.toast( + `Welcome Back, ${data.firstName || 'Reader'}`, + 2500, + 'teal darken-4' + ); + }, + (error) => { + Materialize.toast(error.response.data.message, 2500, 'red darken-4'); + this.setState({ isLoading: false }); + } + ) + .catch((err) => { + Materialize.toast( + `Ouch! Something went awry. It's probably our fault`, + 2500, + 'red darken-4' + ); + this.setState({ isLoading: false }); + }); + } + + handleChange(event) { + event.preventDefault(); + const formField = event.target.name; + const user = Object.assign({}, this.state); + if (!!event.target.value.trim()) { + user[formField] = event.target.value.trim(); + } + this.setState(() => user); + } + + render() { + const loadingState = this.state.isLoading ? + : null + return ( + this.props.isLoggedIn === true ? + : +
+
+
+
+ +
+
+
+

Hello Reader

+
Welcome home avid reader
+
+
+
+
+
Login
+
+
+
+
+ +
+
+ +
+ {loadingState} +
+ +
+
+ {/* + + Login with Google + */} +
+
+

Don't have an account? + Sign up +

+
+
+

Forgot password?     + Click here +

+
+
+
+
+
+
+
+
+
+
+
+ ); + } +} + +Login.propTypes = { + login: PropTypes.func.isRequired, +}; + +const mapStateToProps = ({ authReducer }) => ( + { isLoggedIn: authReducer.isLoggedIn } +); + + +export default connect(mapStateToProps, { login })(Login); diff --git a/client/components/dashboard/ProfileInfo.jsx b/client/components/dashboard/ProfileInfo.jsx index 21f89fa..24dac3d 100644 --- a/client/components/dashboard/ProfileInfo.jsx +++ b/client/components/dashboard/ProfileInfo.jsx @@ -1,5 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; +import { Link } from 'react-router-dom'; import { Col, Icon } from 'react-materialize'; import imageFallback from '../../static/profile_image.png'; @@ -20,13 +21,12 @@ const ProfileInfo = props => ( - edit Edit Profile - + ); diff --git a/client/components/dashboard/UpdateProfile.js b/client/components/dashboard/UpdateProfile.js new file mode 100644 index 0000000..4a4a1e9 --- /dev/null +++ b/client/components/dashboard/UpdateProfile.js @@ -0,0 +1,109 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import { Col, Row } from 'react-materialize'; + +import Header from '../header/Header'; + +/** + * Component to update user profile + * @type {Object} + */ +class UpdateProfile extends Component { + /** + * constructs instance of Component + * @return {Object} JSX component + */ + constructor() { + super(); + this.handleSubmit = this.handleSubmit.bind(this); + } + /** + * handles form submission + * @param {Object} event DOM onSubmit event + * @return {mixed} sends a network request + */ + handleSubmit(event) { + event.preventDefault(); + } + + /** + * class method that renders a component to the DOM + * @return {Object} JSX element + */ + render() { + return ( +
+
+
+ + +
+
+
+ Update your profile information +
+
+ +
+
First Name:
+ +
+
+
Last Name:
+ +
+
+ Leave the password fields empty unless you actually want + to change your password +
+
+
Current Password:
+ +
+
+
New Password:
+ +
+
+ +
+
+ +
+
+
+ ); + } +} + +UpdateProfile.propTypes = { + user: PropTypes.object.isRequired, +}; + +const mapStateToProps = ({ authReducer }) => ({ + user: authReducer.user, +}); + +export default connect(mapStateToProps)(UpdateProfile); diff --git a/server/bin/www.js b/server/bin/www.js index c7eb7a1..e936be2 100644 --- a/server/bin/www.js +++ b/server/bin/www.js @@ -2,7 +2,7 @@ import http from 'http'; import app from '../app'; -const port = parseInt(process.env.PORT, 10) || 5000; +const port = parseInt(process.env.PORT, 10) || 4000; const server = http.createServer(app); diff --git a/server/middleware/authentication.js b/server/middleware/authentication.js index 37e50a2..aaf6079 100644 --- a/server/middleware/authentication.js +++ b/server/middleware/authentication.js @@ -11,7 +11,7 @@ dotenv.config(); */ const getToken = (req) => { const token = req.body.token || req.headers['x-access-token'] || - req.headers.Authorization.slice(7); + (req.headers.Authorization && req.headers.Authorization.slice(7)); return token; }; diff --git a/webpack.prod.config.js b/webpack.prod.config.js index 6dddf47..0a17e21 100644 --- a/webpack.prod.config.js +++ b/webpack.prod.config.js @@ -66,12 +66,12 @@ module.exports = { warnings: false } }), - new webpack.DefinePlugin({ - 'process.env': { - NODE_ENV: JSON.stringify('production') - }, - GOOGLE_CLIENT_SECRET: JSON.stringify('VenazYqo1V-41a8pAocf7a9H'), - GOOGLE_CLIENT_ID: JSON.stringify('701806023399-vgqondt26qh10vcuei77r7nsbcd8oa8k.apps.googleusercontent.com') - }) + // new webpack.DefinePlugin({ + // 'process.env': { + // NODE_ENV: JSON.stringify('production') + // }, + // GOOGLE_CLIENT_SECRET: JSON.stringify('VenazYqo1V-41a8pAocf7a9H'), + // GOOGLE_CLIENT_ID: JSON.stringify('701806023399-vgqondt26qh10vcuei77r7nsbcd8oa8k.apps.googleusercontent.com') + // }) ], };