Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#6474848: Add user sign up #2

Merged
merged 1 commit into from Jun 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion .babelrc
@@ -1 +1,5 @@
{ "presets": ["@babel/preset-env", "@babel/preset-react"] }
{
"presets": ["@babel/preset-env", "@babel/preset-react"],
"plugins": ["transform-class-properties"]

}
13 changes: 12 additions & 1 deletion package.json
Expand Up @@ -20,15 +20,26 @@
},
"homepage": "https://github.com/KabohaJeanMark/ireporter-react-frontend#readme",
"dependencies": {
"axios": "^0.19.0",
"css": "^2.2.4",
"loader": "^2.1.1",
"node-sass": "^4.12.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-router-dom": "^5.0.1"
"react-redux": "^7.1.0",
"react-router-dom": "^5.0.1",
"react-toastify": "^5.3.1",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0",
"sass": "^1.22.0",
"sass-loader": "^7.1.0"
},
"devDependencies": {
"@babel/core": "^7.4.5",
"@babel/preset-env": "^7.4.5",
"@babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.6",
"babel-plugin-transform-class-properties": "^6.24.1",
"css-loader": "^3.0.0",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
Expand Down
12 changes: 11 additions & 1 deletion src/components/Apps/Apps.js
@@ -1,15 +1,25 @@
import React, { Component } from 'react';
import { BrowserRouter as Router, Route} from 'react-router-dom';

import {Provider} from 'react-redux';
import store from '../../redux/store';
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import Home from '../Home/Home';
import SignUp from '../../containers/Signup';

class App extends Component {

render(){
return(
<Provider store={store}>
<ToastContainer />
<Router>
<Route exact path="/" component={Home}/>
<Route exact path="/signup" component={SignUp}/>
</Router>

</Provider>

);
}
};
Expand Down
3 changes: 3 additions & 0 deletions src/components/Home/Home.js
@@ -1,9 +1,12 @@
import React, {Component} from 'react';
//import components
import Navbar from '../Navbar';

class Home extends Component {
render(){
return(
<div>
<Navbar />
<h1>Welcome to Ireporter</h1>
</div>
);
Expand Down
91 changes: 91 additions & 0 deletions src/components/Navbar/Navbar.scss
@@ -0,0 +1,91 @@
* {
padding: 0;
margin: 0;

}

$primary_color: orange;

.Navbar{
color: blue;
width: 100%;
height: 7rem;
background: grey;
border-bottom: 4px $primary_color solid;
}

.Navbar ul{
padding-top: 45px;


}

.Navbar ul li{
display: inline;

}


.Navbar ul li a{
text-decoration: none;
padding: 0 10px;
color: white;
text-shadow: 0 2px 4px black;
}

.Navbar ul li a:hover{
color: $primary_color;
}

.Navbar ul li a:active{
opacity: 0.8;
}

.create-signup {

}

.card{
width: 30%;
margin-top: 30px;
}

.card input{
width: 100%;
min-width: 300px;
border: 1px grey solid;
height: 35px;
border-radius: 8px;
padding: 0 5px 2px 5px;
margin: 10px 0;
font-size: 17px;
outline: none;


}

.card input:hover, .card input:focus{
border: 1px $primary_color solid;
}

.card button {
padding: 10px 20px;
font-size: 17px;
border-radius: 8px;
cursor: pointer;
outline:none;
background: white;
border: 1px $primary_color solid;
color: $primary_color;
}

.card button:hover {

background: $primary_color;
color: white;
border: 1px $primary_color solid;
}

.card button:active {
opacity: 0.8;
}
19 changes: 19 additions & 0 deletions src/components/Navbar/index.js
@@ -0,0 +1,19 @@
import React, { Component } from 'react';
import '../Navbar/Navbar.scss';

class Navbar extends Component {
render(){
return(
<div className="Navbar" align="right">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/signup">Signup</a></li>
<li><a href="/login">Login</a></li>
</ul>
</div>
);
}
}


export default Navbar;
83 changes: 83 additions & 0 deletions src/components/SignupComponent.js
@@ -0,0 +1,83 @@
import React from 'react';
import Navbar from './Navbar';

const SignUpPresentationComponent = ({ handleSubmit, handleChange}) => {
return (
<>
<Navbar />
<div className="create-signup" align="center">
<div className="card">
<form onSubmit={handleSubmit}>
<div className="form-group">
<input
type="text"
name="first_name"
id="firstname-input"
placeholder="first name"
required
onChange={(e) => handleChange(e)}/>
</div>
<div className="form-group">
<input
type="text"
name="last_name"
id="lastname-input"
placeholder="last name"
required
onChange={(e) => handleChange(e)}/>
</div>
<div className="form-group">
<input

type="text"
name="othernames"
id="othername-input"
placeholder="other name"
required
onChange={e => handleChange(e)}/>
</div>
<div className="form-group">
<input
type="text"
name="email"
id="email-input"
placeholder="email"
required
onChange={e => handleChange(e)}/>
</div>
<div className="form-group">
<input
type="text"
name="username"
id="username-input"
placeholder="username"
required
onChange={e => handleChange(e)}/>
</div>
<div className="form-group">
<input
type="text"
name="phone_number"
id="phonenumber-input"
placeholder="phone number"
required
onChange={e => handleChange(e)}/>
</div>
<div className="form-group">
<input
type="text"
name="password"
id="password-input"
placeholder="password"
required
onChange={e => handleChange(e)}/>
</div>
<button type="submit" className="btn postarticle-btn btn-outline-primary">Sign up</button>
</form>
</div>
</div>
</>
);
};

export default SignUpPresentationComponent;
72 changes: 72 additions & 0 deletions src/containers/Signup.js
@@ -0,0 +1,72 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { toast } from 'react-toastify';
import SignUpPresentationComponent from '../components/SignupComponent';
import PropTypes from 'prop-types';
import {signupUrl} from '../utils';
import {postSignup} from '../redux/actions/SignupActions';


export class SignUp extends Component {
constructor(props){
super(props);
const state = {
first_name:"",
last_name:"",
othernames:"",
username:"",
phone_number:"",
email:"",
password:""
};
}
checkBlank = () => {
const { first_name, last_name, othernames, username, phone_number,email, password } = this.state;
if (first_name === '' || last_name === '' || othernames === ''||username === '' || phone_number === '' || email === ''|| password ==='') {
toast.dismiss();
toast.error("All fields must be filled", {
hideProgressBar: false,
autoClose: 3000
});
}
};

handleChange = (event) => {
this.setState({
[event.target.name]: event.target.value
});
};
handleSubmit = (event) => {
event.preventDefault();
const { first_name, last_name, othernames, username, phone_number,email, password } = this.state;
const signupDetails = { first_name, last_name, othernames, username, phone_number,email, password };
this.checkBlank();
this.props.postSignup(signupUrl, signupDetails, this.props);
};

render () {
return (
<div>
<SignUpPresentationComponent
handleSubmit={this.handleSubmit}
handleChange={this.handleChange}/>
</div>

);
}
}

SignUp.propTypes = {
handleSubmit: PropTypes.func,
handleChange: PropTypes.func,
first_name: PropTypes.string,
last_name: PropTypes.string,
username: PropTypes.string,
othernames: PropTypes.string,
phone_number:PropTypes.string,
email:PropTypes.string,
password:PropTypes.string,
postSignup: PropTypes.func
};

export default connect(null, {postSignup})(SignUp);
26 changes: 26 additions & 0 deletions src/redux/actions/SignupActions.js
@@ -0,0 +1,26 @@
import axios from 'axios';
import { toast } from 'react-toastify';
import { signupType } from './types';

export const postSignup = (signupUrl, signupDetails, props) => dispatch =>
axios.post(signupUrl, signupDetails).then(response => {
const { status } = response;
if (status === 201) {
dispatch({ type: signupType.SIGNUP_SUCCESS, payload: response.data });
toast.dismiss();
toast.success("You have signed up successfully", {
hideProgressBar: false, autoClose: 3000
});
document.location.href = '/';
}
})
.catch((error) => {
if (error.response.status === 400) {
dispatch({ type: signupType.SIGNUP_ERROR, payload: error.response.data });
toast.dismiss();
toast.error("This email, username and password cannot be used to sign up", {
hideProgressBar: false, autoClose: 3000
});
}
}
);
4 changes: 4 additions & 0 deletions src/redux/actions/types.js
@@ -0,0 +1,4 @@
export const signupType = {
SIGNUP_SUCCESS: "SIGNUP_SUCCESS",
SIGNUP_ERROR: "SIGNUP_ERROR"
};