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).
|
||||
|
||||
| Environment Variable | Default Value | Description |
|
||||
| ------------------------- |:-------------------------:| -------------------:|
|
||||
| `REACT_APP_API_ENDPOINT` | `"http://localhost:8000"` | Server API endpoint |
|
||||
| `REACT_APP_REDUX_LOGGING` | ` ` | Set for Redux Log |
|
||||
| Environment Variable | Default Value | Description |
|
||||
| ------------------------- |:-------------------------:| -------------------------------:|
|
||||
| `REACT_APP_API_ENDPOINT` | `"http://localhost:8000"` | Server API endpoint |
|
||||
| `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
|
||||
|
||||
|
|
|
@ -4,7 +4,12 @@ import {
|
|||
CLEAR_USER_REQUEST_ERROR,
|
||||
SET_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";
|
||||
import { parseError } from "../common.actions";
|
||||
|
||||
|
@ -48,3 +53,38 @@ export function setSelfUser(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 Settings from "./Auth/Settings";
|
||||
import VerifyEmail from "./Auth/VerifyEmail";
|
||||
import CompleteRegistration from "./User/CompleteRegistration";
|
||||
import Profile from "./User/Profile";
|
||||
import PrivateRoute from "./Shared/PrivateRoute";
|
||||
import About from "./Static/About";
|
||||
|
@ -17,15 +18,16 @@ import Navbar from "./Navbar";
|
|||
|
||||
class App extends Component {
|
||||
render() {
|
||||
const footSmash = {
|
||||
display: "flex",
|
||||
minHeight: "calc(100vh - 1px)",
|
||||
flexDirection: "column"
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<Navbar />
|
||||
<div style={footSmash}>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
minHeight: "calc(100vh - 1px)",
|
||||
flexDirection: "column"
|
||||
}}
|
||||
>
|
||||
<div style={{ flex: "1" }}>
|
||||
<Switch>
|
||||
<Route exact path="/" component={Home} />
|
||||
|
@ -44,8 +46,10 @@ class App extends Component {
|
|||
component={ResetPassword}
|
||||
/>
|
||||
<PrivateRoute path="/user/profile" component={Profile} />
|
||||
<Route path='/user/complete-registration' component={Profile} />
|
||||
<Route component={NoMatch} />
|
||||
</Switch>
|
||||
<Route path='/user/complete-registration' component={CompleteRegistration} />
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
|
|
|
@ -3,9 +3,18 @@ import { connect } from "react-redux";
|
|||
import { Link } from "react-router-dom";
|
||||
import { Dropdown, Menu } from "semantic-ui-react";
|
||||
|
||||
import { sendGetSelfUserRequest } from "../actions/user/saga.actions";
|
||||
import { sendLogoutRequest } from "../actions/auth/saga.actions";
|
||||
|
||||
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 = () => {
|
||||
this.props.dispatch(sendLogoutRequest());
|
||||
};
|
||||
|
@ -22,7 +31,10 @@ class Navbar extends Component {
|
|||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return { ...state.auth };
|
||||
return {
|
||||
userToken: state.auth.userToken,
|
||||
selfUser: state.user.selfUser
|
||||
};
|
||||
}
|
||||
|
||||
const NavbarView = ({ isAuthenticated, dispatchLogoutRequest }) => (
|
||||
|
|
|
@ -33,16 +33,23 @@ class PrivateRoute extends Component {
|
|||
component,
|
||||
...rest
|
||||
} = this.props;
|
||||
// If the user token exists and
|
||||
// If the user token exists and
|
||||
// * self user object isn't loaded yet or
|
||||
// * we are still sending user request
|
||||
// show loading spinner
|
||||
if (
|
||||
!!userToken &&
|
||||
(Object.keys(selfUser).length === 0 || isSendingUserRequest)
|
||||
userToken && (Object.keys(selfUser).length === 0 || isSendingUserRequest)
|
||||
) {
|
||||
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 (
|
||||
<Route
|
||||
{...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>
|
||||
{Object.keys(user.userinfo).map(function(key) {
|
||||
return (<List.Item key={key}>
|
||||
{user.userinfo[key]}
|
||||
{key}: {user.userinfo[key]}
|
||||
</List.Item>)
|
||||
})}
|
||||
</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 CLEAR_USER_REQUEST_SUCCESS = "CLEAR_USER_REQUEST_SUCCESS";
|
||||
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
|
||||
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,
|
||||
SET_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";
|
||||
|
||||
const initialState = {
|
||||
isSendingUserRequest: false,
|
||||
userRequestError: "",
|
||||
userRequestSuccess: "",
|
||||
selfUser: {}
|
||||
selfUser: {},
|
||||
completeRegistrationCurrentStep: USER_INFO_STEP,
|
||||
completeRegistrationMaxStep: USER_INFO_STEP,
|
||||
completeRegistrationClientOrProvider: "",
|
||||
phoneNumber: "",
|
||||
businessNumber: "",
|
||||
socialInsuranceNumber: ""
|
||||
};
|
||||
|
||||
function userReducer(state = initialState, action) {
|
||||
|
@ -46,6 +58,35 @@ function userReducer(state = initialState, action) {
|
|||
...state,
|
||||
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:
|
||||
return state;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user