-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
5 changed files
with
249 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { SIGNUP_REQUESTING } from "./constants" | ||
|
||
const signupRequest = ({email, password}) => { | ||
console.log("called") | ||
return { | ||
type: SIGNUP_REQUESTING, | ||
email, | ||
password | ||
} | ||
} | ||
|
||
export default signupRequest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export const SIGNUP_REQUESTING = "SIGNUP_REQUESTING" | ||
export const SIGNUP_SUCCESS = "SIGNUP_SUCCESS" | ||
export const SIGNUP_ERROR = "SIGNUP_ERROR" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import React from "react" | ||
import PropTypes from "prop-types" | ||
import { withStyles } from "@material-ui/core/styles" | ||
import MenuItem from "@material-ui/core/MenuItem" | ||
import TextField from "@material-ui/core/TextField" | ||
import Modal from "@material-ui/core/Modal" | ||
import Button from "@material-ui/core/Button" | ||
|
||
const styles = theme => ({ | ||
container: { | ||
display: "flex", | ||
flexWrap: "wrap" | ||
}, | ||
textField: { | ||
marginLeft: theme.spacing.unit, | ||
marginRight: theme.spacing.unit, | ||
width: 200 | ||
}, | ||
menu: { | ||
width: 200 | ||
} | ||
}) | ||
|
||
const currencies = [ | ||
{ | ||
value: "USD", | ||
label: "$" | ||
}, | ||
{ | ||
value: "EUR", | ||
label: "€" | ||
}, | ||
{ | ||
value: "BTC", | ||
label: "฿" | ||
}, | ||
{ | ||
value: "JPY", | ||
label: "¥" | ||
} | ||
] | ||
|
||
class Signup extends React.Component { | ||
state = { | ||
open: false, | ||
name: "Cat in the Hat", | ||
age: "", | ||
multiline: "Controlled", | ||
currency: "EUR" | ||
} | ||
|
||
handleOpen = () => { | ||
this.setState({open: true}) | ||
} | ||
|
||
handleClose = () => { | ||
this.setState({open: false}) | ||
} | ||
|
||
handleChange = name => event => { | ||
this.setState({ | ||
[name]: event.target.value | ||
}) | ||
} | ||
|
||
render() { | ||
const {classes} = this.props | ||
|
||
return ( | ||
<Modal | ||
aria-labelledby="simple-modal-title" | ||
aria-describedby="simple-modal-description" | ||
|
||
> | ||
<form className={ classes.container } noValidate autoComplete="on"> | ||
<TextField | ||
id="textarea" | ||
label="With placeholder multiline" | ||
placeholder="Placeholder" | ||
multiline | ||
className={ classes.textField } | ||
margin="normal" | ||
/> | ||
<TextField | ||
required | ||
id="required" | ||
label="Required" | ||
defaultValue="Hello World" | ||
className={ classes.textField } | ||
margin="normal" | ||
/> | ||
<TextField | ||
id="textarea" | ||
label="With placeholder multiline" | ||
placeholder="Placeholder" | ||
multiline | ||
className={ classes.textField } | ||
margin="normal" | ||
/> | ||
</form> | ||
</Modal> | ||
) | ||
} | ||
} | ||
/* | ||
TextFields.propTypes = { | ||
classes: PropTypes.object.isRequired | ||
} | ||
*/ | ||
|
||
|
||
|
||
export default withStyles(styles)(Signup) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { | ||
SIGNUP_REQUESTING, | ||
SIGNUP_SUCCESS, | ||
SIGNUP_ERROR | ||
} from "./constants" | ||
|
||
const initialState = { | ||
requesting: false, | ||
successful: false, | ||
messages: [], | ||
errors: [] | ||
} | ||
|
||
const reducer = (state = initialState, action) => { | ||
switch (action.type) { | ||
case SIGNUP_REQUESTING: | ||
return { | ||
requesting: true, | ||
successful: false, | ||
messages: [{body: "Signing up...", time: new Date()}], | ||
errors: [] | ||
} | ||
|
||
// reset the state and add a body message of success! | ||
// remember our successful returned payload will be: | ||
// {"email": "of the new user", "id": "of the user"} | ||
case SIGNUP_SUCCESS: | ||
return { | ||
errors: [], | ||
messages: [{ | ||
body: `Successfully created account for ${action.response.email}`, | ||
time: new Date() | ||
}], | ||
requesting: false, | ||
successful: true | ||
} | ||
|
||
// reset the state but with errors! | ||
// the error payload returned is actually far | ||
// more detailed, but we'll just stick with | ||
// the base message for now | ||
case SIGNUP_ERROR: | ||
return { | ||
errors: state.errors.concat([{ | ||
body: action.error.toString(), | ||
time: new Date() | ||
}]), | ||
messages: [], | ||
requesting: false, | ||
successful: false | ||
} | ||
|
||
default: | ||
return state | ||
} | ||
} | ||
|
||
export default reducer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { call, put, takeLatest } from "redux-saga/effects" | ||
import { handleApiErrors } from "../lib/api-errors" | ||
import { | ||
SIGNUP_REQUESTING, | ||
SIGNUP_SUCCESS, | ||
SIGNUP_ERROR | ||
} from "./constants" | ||
|
||
// The url derived from our .env file | ||
const signupUrl = `${process.env.REACT_APP_API_URL}/api/Clients` | ||
|
||
function signupApi(email, password) { | ||
// call to the "fetch". this is a "native" function for browsers | ||
// that's conveniently polyfilled in create-react-app if not available | ||
return fetch(signupUrl, { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json" | ||
}, | ||
body: JSON.stringify({email, password}) | ||
}) | ||
.then(handleApiErrors) // we'll make this in a second | ||
.then(response => response.json()) | ||
.then(json => json) | ||
.catch((error) => { | ||
throw error | ||
}) | ||
} | ||
|
||
// This will be run when the SIGNUP_REQUESTING | ||
// Action is found by the watcher | ||
function* signupFlow(action) { | ||
try { | ||
const {email, password} = action | ||
// pulls "calls" to our signupApi with our email and password | ||
// from our dispatched signup action, and will PAUSE | ||
// here until the API async function, is complete! | ||
const response = yield call(signupApi, email, password) | ||
|
||
// when the above api call has completed it will "put", | ||
// or dispatch, an action of type SIGNUP_SUCCESS with | ||
// the successful response. | ||
yield put({type: SIGNUP_SUCCESS, response}) | ||
} catch (error) { | ||
// if the api call fails, it will "put" the SIGNUP_ERROR | ||
// into the dispatch along with the error. | ||
yield put({type: SIGNUP_ERROR, error}) | ||
} | ||
} | ||
|
||
// Watches for the SIGNUP_REQUESTING action type | ||
// When it gets it, it will call signupFlow() | ||
// WITH the action we dispatched | ||
function* signupWatcher() { | ||
// takeLatest() takes the LATEST call of that action and runs it | ||
// if we we're to use takeEvery, it would take every single | ||
// one of the actions and kick off a new task to handle it | ||
// CONCURRENTLY!!! | ||
yield takeLatest(SIGNUP_REQUESTING, signupFlow) | ||
} | ||
|
||
export default signupWatcher |