Skip to content

Commit

Permalink
feat: add sign in, register component
Browse files Browse the repository at this point in the history
  • Loading branch information
pyphilia committed Nov 19, 2020
1 parent d6b2ed3 commit e9f9170
Show file tree
Hide file tree
Showing 10 changed files with 380 additions and 18 deletions.
12 changes: 8 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,23 @@
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"js-cookie": "2.2.1",
"node-fetch": "2.6.1",
"prop-types": "15.7.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router": "5.2.0",
"react-router-dom": "5.2.0",
"react-scripts": "3.4.3"
},
"scripts": {
"start": "react-scripts start",
"start": "env-cmd -f ./.env.local react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"test": "env-cmd -f ./.env.test react-scripts test",
"eject": "react-scripts eject",
"lint": "eslint .",
"prettier:check": "prettier --check 'src/**/*.js'",
"prettier:write": "prettier --write 'src/**/*.js'",
"prettier:check": "prettier --check src/**/*.js",
"prettier:write": "prettier --write src/**/*.js",
"hooks:uninstall": "node node_modules/husky/husky.js uninstall",
"hooks:install": "node node_modules/husky/husky.js install"
},
Expand All @@ -44,6 +47,7 @@
"devDependencies": {
"@commitlint/cli": "11.0.0",
"@commitlint/config-conventional": "11.0.0",
"env-cmd": "10.1.0",
"eslint-config-airbnb": "18.2.0",
"eslint-config-prettier": "6.11.0",
"eslint-plugin-import": "2.22.0",
Expand Down
42 changes: 42 additions & 0 deletions src/api/authentication.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { API_HOST } from '../config/constants';

// payload = {email}
export const getOwnItems = async () => {
const req = await fetch(`${API_HOST}/own`, {
method: 'GET',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
});
console.log(req)
};

// payload = {email}
export const createItem = async () => {
const req = await fetch(`${API_HOST}/items`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify({name:'myitem'}),
headers: { 'Content-Type': 'application/json' },
});
console.log(await req.json())
};

// payload = {email}
export const signIn = async (payload) => {
const req = await fetch(`${API_HOST}/login`, {
method: 'POST',
body: JSON.stringify(payload),
headers: { 'Content-Type': 'application/json' },
});
return req.status === 204;
};

// payload = {name, mail}
export const register = async (payload) => {
const req = await fetch(`${API_HOST}/register`, {
method: 'POST',
body: JSON.stringify(payload),
headers: { 'Content-Type': 'application/json' },
});
return req.status === 204;
};
19 changes: 18 additions & 1 deletion src/components/App.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import React from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import {
BrowserRouter as Router,
Switch,
Route,
Redirect,
} from 'react-router-dom';
import { makeStyles } from '@material-ui/core/styles';
import Header from './layout/Header';
import Items from './main/Items';
import items from '../data/sample';
import Register from './Register';
import { REGISTER_PATH, SIGN_IN_PATH } from '../config/paths';
import SignIn from './SignIn';

const useStyles = makeStyles((theme) => ({
root: {
Expand All @@ -25,6 +33,15 @@ function App() {
<Route path="/items/:itemId">
<Items items={items} />
</Route>
<Route path={SIGN_IN_PATH} exact>
<SignIn />
</Route>
<Route path={REGISTER_PATH} exact>
<Register />
</Route>
<Route path="/" exact>
<Redirect to="/items" />
</Route>
</Switch>
</main>
</div>
Expand Down
142 changes: 142 additions & 0 deletions src/components/Register.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router';
import { withStyles } from '@material-ui/core/styles';
import TextField from '@material-ui/core/TextField';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
import Divider from '@material-ui/core/Divider';
import Grid from '@material-ui/core/Grid';
import { Alert } from '@material-ui/lab';
import { SIGN_IN_PATH } from '../config/paths';
import { register } from '../api/authentication';

const styles = (theme) => ({
fullScreen: {
margin: 'auto',
textAlign: 'center',
},
input: {
margin: theme.spacing(1),
},
form: {
width: '50%',
minWidth: '200px',
margin: 'auto',
},
divider: {
margin: theme.spacing(2),
},
});

class Register extends Component {
static propTypes = {
classes: PropTypes.shape({
fullScreen: PropTypes.string.isRequired,
divider: PropTypes.string.isRequired,
form: PropTypes.string.isRequired,
input: PropTypes.string.isRequired,
}).isRequired,
history: PropTypes.shape({
push: PropTypes.func.isRequired,
replace: PropTypes.func.isRequired,
}).isRequired,
};

state = {
email: '',
name: '',
isSuccess: null,
};

handleOnSignIn = () => {
const {
history: { push },
} = this.props;
push(SIGN_IN_PATH);
};

handleemailOnChange = (e) => {
this.setState({ email: e.target.value });
};

handleNameOnChange = (e) => {
this.setState({ name: e.target.value });
};

register = async () => {
const { email, name } = this.state;
const isSuccess = await register({ name, email });
this.setState({ isSuccess });
};

renderMessage = () => {
const { isSuccess } = this.state;
if (isSuccess) {
return (
<Alert severity="success">
An email was sent with the register link!
</Alert>
);
}
// is not triggered for null (initial case)
if (isSuccess === false) {
return <Alert severity="error">An error occured.</Alert>;
}
return null;
};

render() {
const { classes } = this.props;
const { email, name, isRequestSent } = this.state;

if (isRequestSent) {
return <div>You will receive a email with your cookie!</div>;
}

return (
<div className={classes.fullScreen}>
{this.renderMessage()}
<Typography variant="h2" component="h2">
Register
</Typography>
<Grid container className={classes.form}>
<Grid item xs={12}>
<TextField
className={classes.input}
required
label="Name"
variant="outlined"
value={name}
onChange={this.handleNameOnChange}
/>
</Grid>
<Grid item xs={12}>
<TextField
className={classes.input}
required
label="email"
variant="outlined"
value={email}
onChange={this.handleemailOnChange}
/>
</Grid>
<Grid item xs={12}>
<Button variant="contained" color="primary" onClick={this.register}>
Register
</Button>
</Grid>
</Grid>

<Divider variant="middle" className={classes.divider} />
<Button variant="text" color="primary" onClick={this.handleOnSignIn}>
Already have an account? Click here to sign in
</Button>
</div>
);
}
}

const StyledComponent = withStyles(styles, { withTheme: true })(Register);

export default withRouter(StyledComponent);
135 changes: 135 additions & 0 deletions src/components/SignIn.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Cookies from 'js-cookie'
import { withRouter } from 'react-router';
import { withStyles } from '@material-ui/core/styles';
import TextField from '@material-ui/core/TextField';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
import Divider from '@material-ui/core/Divider';
import FormControl from '@material-ui/core/FormControl';
import { Alert } from '@material-ui/lab';
import { REGISTER_PATH } from '../config/paths';
import { createItem, getOwnItems, signIn } from '../api/authentication';

const styles = (theme) => ({
fullScreen: {
margin: 'auto',
textAlign: 'center',
},
input: {
margin: theme.spacing(1),
},
form: {
width: '50%',
minWidth: '200px',
margin: 'auto',
},
divider: {
margin: theme.spacing(2),
},
});

class SignIn extends Component {
static propTypes = {
classes: PropTypes.shape({
fullScreen: PropTypes.string.isRequired,
divider: PropTypes.string.isRequired,
form: PropTypes.string.isRequired,
input: PropTypes.string.isRequired,
}).isRequired,
history: PropTypes.shape({
push: PropTypes.func.isRequired,
replace: PropTypes.func.isRequired,
}).isRequired,
};

state = {
isSuccess: null,
email: '',
};

componentDidUpdate() {
//this.isSignedIn()
}

async componentDidMount() {
this.isSignedIn()
console.log(await createItem())
}

async isSignedIn() {
await fetch("http://ielsrv7.epfl.ch/auth?t=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI4N2M0OTQwZS1mNzY0LTRkODYtODExNC0xZWRkOWVmZjJlZTAiLCJpYXQiOjE2MDU3NzYxMTEsImV4cCI6MTYwNTc3NzkxMX0.g9Kb2hauJyv25nX-Y-vtFHwsCglKXueo_Y-C4IvoG-M", {
credentials: "include",

})
// getOwnItems()
}

handleOnRegister = () => {
const {
history: { push },
} = this.props;
push(REGISTER_PATH);
};

signIn = async () => {
const { email } = this.state;
const isSuccess = await signIn({ email });
this.setState({ isSuccess });
};

handleOnChange = (e) => {
this.setState({ email: e.target.value });
};

renderMessage = () => {
const { isSuccess } = this.state;
if (isSuccess) {
return (
<Alert severity="success">An email was sent with the login link!</Alert>
);
}
// is not triggered for null (initial case)
if (isSuccess === false) {
return <Alert severity="error">An error occured.</Alert>;
}
return null;
};

render() {
const { classes } = this.props;
const { email } = this.state;

return (
<div className={classes.fullScreen}>
{this.renderMessage()}
<Typography variant="h2" component="h2">
Sign In
</Typography>
<FormControl>
<TextField
className={classes.input}
required
label="email"
variant="outlined"
value={email}
onChange={this.handleOnChange}
/>
<Button variant="contained" color="primary" onClick={this.signIn}>
Sign In
</Button>
</FormControl>

<Divider variant="middle" className={classes.divider} />
<Button variant="text" color="primary" onClick={this.handleOnRegister}>
Not registered? Click here to register
</Button>
</div>
);
}
}

const StyledComponent = withStyles(styles, { withTheme: true })(SignIn);

export default withRouter(StyledComponent);
Loading

0 comments on commit e9f9170

Please sign in to comment.