Added Complete Registration stepper component, all stepper logic
This commit is contained in:
parent
e69773ac8e
commit
561664a701
21
README.md
21
README.md
|
@ -15,10 +15,23 @@ Now you can visit `localhost:3000` from your browser.
|
||||||
|
|
||||||
The environment variables are embedded during the build time. For more information, please refer to the [docs](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-custom-environment-variables).
|
The environment variables are embedded during the build time. For more information, please refer to the [docs](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-custom-environment-variables).
|
||||||
|
|
||||||
| Environment Variable | Default Value | Description |
|
| Environment Variable | Default Value | Description |
|
||||||
| ------------------------- |:-------------------------:| -------------------:|
|
| ------------------------- |:-------------------------:| -------------------------------:|
|
||||||
| `REACT_APP_API_ENDPOINT` | `"http://localhost:8000"` | Server API endpoint |
|
| `REACT_APP_API_ENDPOINT` | `"http://localhost:8000"` | Server API endpoint |
|
||||||
| `REACT_APP_REDUX_LOGGING` | ` ` | Set for Redux Log |
|
| `REACT_APP_REDUX_LOGGING` | ` ` | Set any value for Redux logging |
|
||||||
|
|
||||||
|
|
||||||
|
## Production
|
||||||
|
|
||||||
|
To build the production instance of this application, run the following:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export REACT_APP_API_ENDPOINT="http://dev.tannercollin.com:8000/" && yarn build
|
||||||
|
|
||||||
|
# then, to serve the production site locally
|
||||||
|
yarn global add serve
|
||||||
|
serve -s build --port 3000
|
||||||
|
```
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,12 @@ import {
|
||||||
CLEAR_USER_REQUEST_ERROR,
|
CLEAR_USER_REQUEST_ERROR,
|
||||||
SET_USER_REQUEST_SUCCESS,
|
SET_USER_REQUEST_SUCCESS,
|
||||||
CLEAR_USER_REQUEST_SUCCESS,
|
CLEAR_USER_REQUEST_SUCCESS,
|
||||||
SET_SELF_USER
|
SET_SELF_USER,
|
||||||
|
SET_COMPLETE_REGISTRATION_STEP,
|
||||||
|
SET_COMPLETE_REGISTRATION_CLIENT_OR_PROVIDER,
|
||||||
|
SET_FORM_PHONE_NUMBER,
|
||||||
|
SET_FORM_BUSINESS_NUMBER,
|
||||||
|
SET_FORM_SOCIAL_INSURANCE_NUMBER
|
||||||
} from "../../constants/user.constants";
|
} from "../../constants/user.constants";
|
||||||
import { parseError } from "../common.actions";
|
import { parseError } from "../common.actions";
|
||||||
|
|
||||||
|
@ -48,3 +53,38 @@ export function setSelfUser(selfUser) {
|
||||||
data: selfUser
|
data: selfUser
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setCompleteRegistrationStep(step) {
|
||||||
|
return {
|
||||||
|
type: SET_COMPLETE_REGISTRATION_STEP,
|
||||||
|
data: step
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setCompleteRegistrationClientOrProvider(clientOrProvider) {
|
||||||
|
return {
|
||||||
|
type: SET_COMPLETE_REGISTRATION_CLIENT_OR_PROVIDER,
|
||||||
|
data: clientOrProvider
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setFormPhoneNumber(phoneNumber) {
|
||||||
|
return {
|
||||||
|
type: SET_FORM_PHONE_NUMBER,
|
||||||
|
data: phoneNumber
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setFormBusinessNumber(businessNumber) {
|
||||||
|
return {
|
||||||
|
type: SET_FORM_BUSINESS_NUMBER,
|
||||||
|
data: businessNumber
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setFormSocialInsuranceNumber(socialInsuranceNumber) {
|
||||||
|
return {
|
||||||
|
type: SET_FORM_SOCIAL_INSURANCE_NUMBER,
|
||||||
|
data: socialInsuranceNumber
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import Register from "./Auth/Register";
|
||||||
import ResetPassword from "./Auth/ResetPassword";
|
import ResetPassword from "./Auth/ResetPassword";
|
||||||
import Settings from "./Auth/Settings";
|
import Settings from "./Auth/Settings";
|
||||||
import VerifyEmail from "./Auth/VerifyEmail";
|
import VerifyEmail from "./Auth/VerifyEmail";
|
||||||
|
import CompleteRegistration from "./User/CompleteRegistration";
|
||||||
import Profile from "./User/Profile";
|
import Profile from "./User/Profile";
|
||||||
import PrivateRoute from "./Shared/PrivateRoute";
|
import PrivateRoute from "./Shared/PrivateRoute";
|
||||||
import About from "./Static/About";
|
import About from "./Static/About";
|
||||||
|
@ -17,15 +18,16 @@ import Navbar from "./Navbar";
|
||||||
|
|
||||||
class App extends Component {
|
class App extends Component {
|
||||||
render() {
|
render() {
|
||||||
const footSmash = {
|
|
||||||
display: "flex",
|
|
||||||
minHeight: "calc(100vh - 1px)",
|
|
||||||
flexDirection: "column"
|
|
||||||
};
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Navbar />
|
<Navbar />
|
||||||
<div style={footSmash}>
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
minHeight: "calc(100vh - 1px)",
|
||||||
|
flexDirection: "column"
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div style={{ flex: "1" }}>
|
<div style={{ flex: "1" }}>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path="/" component={Home} />
|
<Route exact path="/" component={Home} />
|
||||||
|
@ -44,8 +46,10 @@ class App extends Component {
|
||||||
component={ResetPassword}
|
component={ResetPassword}
|
||||||
/>
|
/>
|
||||||
<PrivateRoute path="/user/profile" component={Profile} />
|
<PrivateRoute path="/user/profile" component={Profile} />
|
||||||
|
<Route path='/user/complete-registration' component={Profile} />
|
||||||
<Route component={NoMatch} />
|
<Route component={NoMatch} />
|
||||||
</Switch>
|
</Switch>
|
||||||
|
<Route path='/user/complete-registration' component={CompleteRegistration} />
|
||||||
</div>
|
</div>
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,9 +3,18 @@ import { connect } from "react-redux";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { Dropdown, Menu } from "semantic-ui-react";
|
import { Dropdown, Menu } from "semantic-ui-react";
|
||||||
|
|
||||||
|
import { sendGetSelfUserRequest } from "../actions/user/saga.actions";
|
||||||
import { sendLogoutRequest } from "../actions/auth/saga.actions";
|
import { sendLogoutRequest } from "../actions/auth/saga.actions";
|
||||||
|
|
||||||
class Navbar extends Component {
|
class Navbar extends Component {
|
||||||
|
componentWillMount() {
|
||||||
|
const { dispatch, userToken, selfUser } = this.props;
|
||||||
|
// If the user token exists and the self user object isn't loaded, dispatch
|
||||||
|
if (userToken && Object.keys(selfUser).length === 0) {
|
||||||
|
dispatch(sendGetSelfUserRequest());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dispatchLogoutRequest = () => {
|
dispatchLogoutRequest = () => {
|
||||||
this.props.dispatch(sendLogoutRequest());
|
this.props.dispatch(sendLogoutRequest());
|
||||||
};
|
};
|
||||||
|
@ -22,7 +31,10 @@ class Navbar extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state) {
|
||||||
return { ...state.auth };
|
return {
|
||||||
|
userToken: state.auth.userToken,
|
||||||
|
selfUser: state.user.selfUser
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const NavbarView = ({ isAuthenticated, dispatchLogoutRequest }) => (
|
const NavbarView = ({ isAuthenticated, dispatchLogoutRequest }) => (
|
||||||
|
|
|
@ -33,16 +33,23 @@ class PrivateRoute extends Component {
|
||||||
component,
|
component,
|
||||||
...rest
|
...rest
|
||||||
} = this.props;
|
} = this.props;
|
||||||
// If the user token exists and
|
// If the user token exists and
|
||||||
// * self user object isn't loaded yet or
|
// * self user object isn't loaded yet or
|
||||||
// * we are still sending user request
|
// * we are still sending user request
|
||||||
// show loading spinner
|
// show loading spinner
|
||||||
if (
|
if (
|
||||||
!!userToken &&
|
userToken && (Object.keys(selfUser).length === 0 || isSendingUserRequest)
|
||||||
(Object.keys(selfUser).length === 0 || isSendingUserRequest)
|
|
||||||
) {
|
) {
|
||||||
return <Loader active />;
|
return <Loader active />;
|
||||||
}
|
}
|
||||||
|
// If the user exists but they aren't a client or provider yet, confirm-registration
|
||||||
|
if (
|
||||||
|
userToken &&
|
||||||
|
Object.keys(selfUser).length &&
|
||||||
|
(!selfUser.client || !selfUser.provider)
|
||||||
|
) {
|
||||||
|
return <Redirect to="/user/complete-registration" />;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<Route
|
<Route
|
||||||
{...rest}
|
{...rest}
|
||||||
|
|
102
src/components/User/CompleteRegistration.jsx
Normal file
102
src/components/User/CompleteRegistration.jsx
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
import React, { Component } from "react";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { Redirect } from "react-router-dom";
|
||||||
|
import { Grid, Modal, Step } from "semantic-ui-react";
|
||||||
|
|
||||||
|
import {
|
||||||
|
setCompleteRegistrationStep
|
||||||
|
} from "../../actions/user/reducer.actions";
|
||||||
|
import {
|
||||||
|
USER_INFO_STEP,
|
||||||
|
CLIENT_OR_PROVIDER_STEP,
|
||||||
|
COMPLETE_INFORMATION_STEP
|
||||||
|
} from "../../constants/user.constants";
|
||||||
|
|
||||||
|
class CompleteRegistration extends Component {
|
||||||
|
onChangeStep = (event, data) => {
|
||||||
|
event.preventDefault();
|
||||||
|
this.props.dispatch(setCompleteRegistrationStep(data.step));
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
userToken,
|
||||||
|
completeRegistrationCurrentStep,
|
||||||
|
completeRegistrationMaxStep,
|
||||||
|
completeRegistrationClientOrProvider
|
||||||
|
} = this.props;
|
||||||
|
if (!userToken) return <Redirect to="/auth/login" />;
|
||||||
|
return (
|
||||||
|
<CompleteRegistrationView
|
||||||
|
currentStep={completeRegistrationCurrentStep}
|
||||||
|
maxStep={completeRegistrationMaxStep}
|
||||||
|
completeRegistrationClientOrProvider={
|
||||||
|
completeRegistrationClientOrProvider
|
||||||
|
}
|
||||||
|
onChangeStep={this.onChangeStep}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
return {
|
||||||
|
...state.user,
|
||||||
|
userToken: state.auth.userToken
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const CompleteRegistrationView = ({
|
||||||
|
currentStep,
|
||||||
|
maxStep,
|
||||||
|
completeRegistrationClientOrProvider,
|
||||||
|
onChangeStep
|
||||||
|
}) => (
|
||||||
|
<Modal defaultOpen={true} closeOnDimmerClick={false} size="large">
|
||||||
|
<Modal.Header>Complete Registration</Modal.Header>
|
||||||
|
<Modal.Content>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Row>
|
||||||
|
<Grid.Column stretched={true}>
|
||||||
|
<Step.Group stackable="tablet" ordered>
|
||||||
|
<Step
|
||||||
|
completed={maxStep > USER_INFO_STEP}
|
||||||
|
active={currentStep === USER_INFO_STEP}
|
||||||
|
title="Basic User Info"
|
||||||
|
description="Fill out your user information"
|
||||||
|
onClick={onChangeStep}
|
||||||
|
disabled={maxStep < USER_INFO_STEP}
|
||||||
|
step={USER_INFO_STEP}
|
||||||
|
/>
|
||||||
|
<Step
|
||||||
|
completed={maxStep > CLIENT_OR_PROVIDER_STEP}
|
||||||
|
active={currentStep === CLIENT_OR_PROVIDER_STEP}
|
||||||
|
title="Client or Provider"
|
||||||
|
description="Choose to be a Client or a Provider"
|
||||||
|
onClick={onChangeStep}
|
||||||
|
disabled={maxStep < CLIENT_OR_PROVIDER_STEP}
|
||||||
|
step={CLIENT_OR_PROVIDER_STEP}
|
||||||
|
/>
|
||||||
|
<Step
|
||||||
|
completed={maxStep > COMPLETE_INFORMATION_STEP}
|
||||||
|
active={currentStep === COMPLETE_INFORMATION_STEP}
|
||||||
|
title="Complete Information"
|
||||||
|
description="Fill out the client or provider information"
|
||||||
|
onClick={onChangeStep}
|
||||||
|
disabled={maxStep < COMPLETE_INFORMATION_STEP}
|
||||||
|
step={COMPLETE_INFORMATION_STEP}
|
||||||
|
/>
|
||||||
|
</Step.Group>
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid.Row>
|
||||||
|
<Grid.Row>
|
||||||
|
{currentStep === USER_INFO_STEP && <p>User Info</p>}
|
||||||
|
{currentStep === CLIENT_OR_PROVIDER_STEP && <p>Client or Provider</p>}
|
||||||
|
{currentStep === COMPLETE_INFORMATION_STEP && <p>Complete Info</p>}
|
||||||
|
</Grid.Row>
|
||||||
|
</Grid>
|
||||||
|
</Modal.Content>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default connect(mapStateToProps)(CompleteRegistration);
|
|
@ -29,7 +29,7 @@ const ProfileView = ({ user }) => (
|
||||||
{user.userinfo && <List>
|
{user.userinfo && <List>
|
||||||
{Object.keys(user.userinfo).map(function(key) {
|
{Object.keys(user.userinfo).map(function(key) {
|
||||||
return (<List.Item key={key}>
|
return (<List.Item key={key}>
|
||||||
{user.userinfo[key]}
|
{key}: {user.userinfo[key]}
|
||||||
</List.Item>)
|
</List.Item>)
|
||||||
})}
|
})}
|
||||||
</List>}
|
</List>}
|
||||||
|
|
|
@ -5,6 +5,20 @@ export const CLEAR_USER_REQUEST_ERROR = "CLEAR_USER_REQUEST_ERROR";
|
||||||
export const SET_USER_REQUEST_SUCCESS = "SET_USER_REQUEST_SUCCESS";
|
export const SET_USER_REQUEST_SUCCESS = "SET_USER_REQUEST_SUCCESS";
|
||||||
export const CLEAR_USER_REQUEST_SUCCESS = "CLEAR_USER_REQUEST_SUCCESS";
|
export const CLEAR_USER_REQUEST_SUCCESS = "CLEAR_USER_REQUEST_SUCCESS";
|
||||||
export const SET_SELF_USER = "SET_SELF_USER";
|
export const SET_SELF_USER = "SET_SELF_USER";
|
||||||
|
export const SET_COMPLETE_REGISTRATION_STEP = "SET_COMPLETE_REGISTRATION_STEP";
|
||||||
|
export const SET_COMPLETE_REGISTRATION_CLIENT_OR_PROVIDER =
|
||||||
|
"SET_COMPLETE_REGISTRATION_CLIENT_OR_PROVIDER";
|
||||||
|
export const SET_FORM_PHONE_NUMBER = "SET_FORM_PHONE_NUMBER";
|
||||||
|
export const SET_FORM_BUSINESS_NUMBER = "SET_FORM_BUSINESS_NUMBER";
|
||||||
|
export const SET_FORM_SOCIAL_INSURANCE_NUMBER =
|
||||||
|
"SET_FORM_SOCIAL_INSURANCE_NUMBER";
|
||||||
|
|
||||||
// Saga User Action Constants
|
// Saga User Action Constants
|
||||||
export const SEND_GET_SELF_USER_REQUEST = "SEND_GET_SELF_USER_REQUEST";
|
export const SEND_GET_SELF_USER_REQUEST = "SEND_GET_SELF_USER_REQUEST";
|
||||||
|
|
||||||
|
// Misc. User Constants (int so we can mark prior as completed)
|
||||||
|
export const USER_INFO_STEP = 1;
|
||||||
|
export const CLIENT_OR_PROVIDER_STEP = 2;
|
||||||
|
export const COMPLETE_INFORMATION_STEP = 3;
|
||||||
|
export const CLIENT = "CLIENT";
|
||||||
|
export const PROVIDER = "PROVIDER";
|
||||||
|
|
|
@ -4,14 +4,26 @@ import {
|
||||||
CLEAR_USER_REQUEST_ERROR,
|
CLEAR_USER_REQUEST_ERROR,
|
||||||
SET_USER_REQUEST_SUCCESS,
|
SET_USER_REQUEST_SUCCESS,
|
||||||
CLEAR_USER_REQUEST_SUCCESS,
|
CLEAR_USER_REQUEST_SUCCESS,
|
||||||
SET_SELF_USER
|
SET_SELF_USER,
|
||||||
|
SET_COMPLETE_REGISTRATION_STEP,
|
||||||
|
SET_COMPLETE_REGISTRATION_CLIENT_OR_PROVIDER,
|
||||||
|
SET_FORM_PHONE_NUMBER,
|
||||||
|
SET_FORM_BUSINESS_NUMBER,
|
||||||
|
SET_FORM_SOCIAL_INSURANCE_NUMBER,
|
||||||
|
USER_INFO_STEP
|
||||||
} from "../constants/user.constants";
|
} from "../constants/user.constants";
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
isSendingUserRequest: false,
|
isSendingUserRequest: false,
|
||||||
userRequestError: "",
|
userRequestError: "",
|
||||||
userRequestSuccess: "",
|
userRequestSuccess: "",
|
||||||
selfUser: {}
|
selfUser: {},
|
||||||
|
completeRegistrationCurrentStep: USER_INFO_STEP,
|
||||||
|
completeRegistrationMaxStep: USER_INFO_STEP,
|
||||||
|
completeRegistrationClientOrProvider: "",
|
||||||
|
phoneNumber: "",
|
||||||
|
businessNumber: "",
|
||||||
|
socialInsuranceNumber: ""
|
||||||
};
|
};
|
||||||
|
|
||||||
function userReducer(state = initialState, action) {
|
function userReducer(state = initialState, action) {
|
||||||
|
@ -46,6 +58,35 @@ function userReducer(state = initialState, action) {
|
||||||
...state,
|
...state,
|
||||||
selfUser: action.data
|
selfUser: action.data
|
||||||
};
|
};
|
||||||
|
case SET_COMPLETE_REGISTRATION_STEP:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
completeRegistrationCurrentStep: action.data,
|
||||||
|
completeRegistrationMaxStep: Math.max(
|
||||||
|
action.data,
|
||||||
|
state.completeRegistrationMaxStep
|
||||||
|
)
|
||||||
|
};
|
||||||
|
case SET_COMPLETE_REGISTRATION_CLIENT_OR_PROVIDER:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
completeRegistrationClientOrProvider: action.data
|
||||||
|
};
|
||||||
|
case SET_FORM_PHONE_NUMBER:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
phoneNumber: action.data
|
||||||
|
};
|
||||||
|
case SET_FORM_BUSINESS_NUMBER:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
businessNumber: action.data
|
||||||
|
};
|
||||||
|
case SET_FORM_SOCIAL_INSURANCE_NUMBER:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
socialInsuranceNumber: action.data
|
||||||
|
};
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user