Skip to content

Commit

Permalink
feat: Integrate facebook social login and get response
Browse files Browse the repository at this point in the history
see: #8
  • Loading branch information
sujinleeme committed Jul 11, 2018
1 parent cfb85cd commit 5ed3a84
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/sign-up/actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { SIGNUP_REQUESTING } from "./constants"

export const signupRequest = ({response, channel}) => {
console.log("called")
return {
type: SIGNUP_REQUESTING,
response,
channel
}
}
3 changes: 3 additions & 0 deletions src/sign-up/constants.js
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"
69 changes: 69 additions & 0 deletions src/sign-up/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React from "react"
import PropTypes from "prop-types"
import { connect } from "react-redux"
import { Button } from "@material-ui/core"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
import { signupRequest } from "./actions"
import FacebookLogin from "react-facebook-login/dist/facebook-login-render-props"
import config from "../social-config.json"

// Signin.propTypes = {
// classes: PropTypes.object.isRequired,
// view: PropTypes.string.isRequired,
// modalRequest: PropTypes.func.isRequired
// }
//

const SocialSignInButton = ({buttonCSSClass, iconCSSClass, textButton, onClick, channel}) => {

const FONTAWESOME_ICONS = {
facebook: ["fab", "facebook"],
google: ["fab", "google"]
}

return (
<Button variant="outlined" className={ buttonCSSClass }
onClick={ onClick }
>
<FontAwesomeIcon
icon={ FONTAWESOME_ICONS[channel] }
className={ iconCSSClass }/>
{ textButton[channel] }
</Button>
)
}

const Signup = (props) => {

const {classes, signupRequest, textButton} = props

return (
<div className={ `${classes.container} ${classes.buttonGroup}` }>
<FacebookLogin
appId={ config.FACEBOOK_APP_ID }
autoLoad
callback={ (response) => console.log(response) }
render={ renderProps => (
<SocialSignInButton
channel="facebook"
buttonCSSClass={ classes.social }
iconCSSClass={ classes.icon }
onClick={ renderProps.onClick }
textButton={ textButton }
/>
) }
/>


<SocialSignInButton
channel="google"
buttonCSSClass={ classes.social }
iconCSSClass={ classes.icon }
textButton={ textButton }
/>
</div>
)
}

export default connect(null, {signupRequest})(Signup)

58 changes: 58 additions & 0 deletions src/sign-up/reducer.js
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
62 changes: 62 additions & 0 deletions src/sign-up/sagas.js
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 sign-up 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

0 comments on commit 5ed3a84

Please sign in to comment.