diff --git a/src/actions/user/reducer.actions.js b/src/actions/user/reducer.actions.js
new file mode 100644
index 0000000..ed4316b
--- /dev/null
+++ b/src/actions/user/reducer.actions.js
@@ -0,0 +1,50 @@
+import {
+ IS_SENDING_USER_REQUEST,
+ SET_USER_REQUEST_ERROR,
+ CLEAR_USER_REQUEST_ERROR,
+ SET_USER_REQUEST_SUCCESS,
+ CLEAR_USER_REQUEST_SUCCESS,
+ SET_SELF_USER
+} from "../../constants/user.constants";
+import { parseError } from "../common.actions";
+
+export function isSendingUserRequest(sendingRequest) {
+ return {
+ type: IS_SENDING_USER_REQUEST,
+ data: sendingRequest
+ };
+}
+
+export function setUserRequestError(exception) {
+ let error = parseError(exception);
+ return {
+ type: SET_USER_REQUEST_ERROR,
+ data: error
+ };
+}
+
+export function clearUserRequestError() {
+ return {
+ type: CLEAR_USER_REQUEST_ERROR
+ };
+}
+
+export function setUserRequestSuccess(response) {
+ return {
+ type: SET_USER_REQUEST_SUCCESS,
+ data: response.detail || response
+ };
+}
+
+export function clearUserRequestSuccess() {
+ return {
+ type: CLEAR_USER_REQUEST_SUCCESS
+ };
+}
+
+export function setSelfUser(selfUser) {
+ return {
+ type: SET_SELF_USER,
+ data: selfUser
+ };
+}
diff --git a/src/actions/user/saga.actions.js b/src/actions/user/saga.actions.js
new file mode 100644
index 0000000..b7a0c81
--- /dev/null
+++ b/src/actions/user/saga.actions.js
@@ -0,0 +1,7 @@
+import { SEND_GET_SELF_USER_REQUEST } from "../../constants/user.constants";
+
+export function sendGetSelfUserRequest() {
+ return {
+ type: SEND_GET_SELF_USER_REQUEST
+ };
+}
diff --git a/src/api/user.api.js b/src/api/user.api.js
new file mode 100644
index 0000000..bcd396c
--- /dev/null
+++ b/src/api/user.api.js
@@ -0,0 +1,5 @@
+import { get } from "./baseApi";
+
+export function getSelfUser() {
+ return get("/user/").then(resp => Promise.resolve(resp));
+}
diff --git a/src/components/App.jsx b/src/components/App.jsx
index 40fbc8f..2130649 100644
--- a/src/components/App.jsx
+++ b/src/components/App.jsx
@@ -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 Profile from "./User/Profile";
import PrivateRoute from "./Shared/PrivateRoute";
import About from "./Static/About";
import Footer from "./Static/Footer";
@@ -15,10 +16,6 @@ import NoMatch from "./Static/NoMatch";
import Navbar from "./Navbar";
class App extends Component {
- componentDidMount() {
-
- }
-
render() {
const footSmash = {
display: "flex",
@@ -39,13 +36,14 @@ class App extends Component {
path="/auth/verify-email/:emailKey"
component={VerifyEmail}
/>
-
+
-
+
+
diff --git a/src/components/Auth/Login.jsx b/src/components/Auth/Login.jsx
index 3d819c8..b842d79 100644
--- a/src/components/Auth/Login.jsx
+++ b/src/components/Auth/Login.jsx
@@ -41,7 +41,7 @@ class Login extends Component {
password,
userToken
} = this.props;
- if (userToken) return ;
+ if (userToken) return ;
return (
;
return (
(
+
+ My Profile
+
Settings
+
Logout
diff --git a/src/components/Shared/PrivateRoute.jsx b/src/components/Shared/PrivateRoute.jsx
index d2487bd..1665d43 100644
--- a/src/components/Shared/PrivateRoute.jsx
+++ b/src/components/Shared/PrivateRoute.jsx
@@ -1,30 +1,66 @@
import PropTypes from "prop-types";
-import React from "react";
+import React, { Component } from "react";
import { connect } from "react-redux";
import { Redirect, Route } from "react-router-dom";
+import { Loader } from "semantic-ui-react";
+
+import { sendGetSelfUserRequest } from "../../actions/user/saga.actions";
const propTypes = {
- path: PropTypes.string.isRequired,
userToken: PropTypes.string.isRequired,
- component: PropTypes.oneOfType([PropTypes.element, PropTypes.func]).isRequired
+ selfUser: PropTypes.object.isRequired,
+ isSendingUserRequest: PropTypes.bool.isRequired,
+ path: PropTypes.string.isRequired,
+ component: PropTypes.oneOfType([PropTypes.element, PropTypes.func])
+ .isRequired,
+ dispatch: PropTypes.func.isRequired
};
-const PrivateRoute = ({ userToken, component, ...rest }) => {
- return (
- {
- if (!!userToken) return React.createElement(component, props);
- return ;
- }}
- />
- );
-};
+class PrivateRoute 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());
+ }
+ }
+
+ render() {
+ const {
+ userToken,
+ selfUser,
+ isSendingUserRequest,
+ component,
+ ...rest
+ } = this.props;
+ // 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)
+ ) {
+ return ;
+ }
+ return (
+ {
+ if (!!userToken) return React.createElement(component, props);
+ return ;
+ }}
+ />
+ );
+ }
+}
PrivateRoute.propTypes = propTypes;
const mapStateToProps = state => ({
- userToken: state.auth.userToken
+ userToken: state.auth.userToken,
+ selfUser: state.user.selfUser,
+ isSendingUserRequest: state.user.isSendingUserRequest
});
export default connect(mapStateToProps)(PrivateRoute);
diff --git a/src/components/User/Profile.jsx b/src/components/User/Profile.jsx
new file mode 100644
index 0000000..ba3ed08
--- /dev/null
+++ b/src/components/User/Profile.jsx
@@ -0,0 +1,47 @@
+import React, { Component } from "react";
+import { connect } from "react-redux";
+import { Card, Container, Header, Label, List } from "semantic-ui-react";
+
+class Profile extends Component {
+ render() {
+ const { selfUser } = this.props;
+ return ;
+ }
+}
+
+function mapStateToProps(state) {
+ return { ...state.user };
+}
+
+const ProfileView = ({ user }) => (
+
+
+
+
+ {user.username || "No username!"}
+ {user.email || "No email!"}
+
+
+ {user.client && "Client"}{user.provider && "Provider"}
+ {!user.client && !user.provider && "User Registration Not Completed"}
+
+ {user.first_name} {user.last_name}
+ {user.userinfo &&
+ {Object.keys(user.userinfo).map(function(key) {
+ return (
+ {user.userinfo[key]}
+ )
+ })}
+
}
+
+
+
+
+
+
+
+);
+
+export default connect(mapStateToProps)(Profile);
diff --git a/src/constants/user.constants.js b/src/constants/user.constants.js
new file mode 100644
index 0000000..54ee206
--- /dev/null
+++ b/src/constants/user.constants.js
@@ -0,0 +1,10 @@
+// Reducer User Action Constants
+export const IS_SENDING_USER_REQUEST = "IS_SENDING_USER_REQUEST";
+export const SET_USER_REQUEST_ERROR = "SET_USER_REQUEST_ERROR";
+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";
+
+// Saga User Action Constants
+export const SEND_GET_SELF_USER_REQUEST = "SEND_GET_SELF_USER_REQUEST";
diff --git a/src/reducers/index.js b/src/reducers/index.js
index c5a7d5a..0bc72b0 100644
--- a/src/reducers/index.js
+++ b/src/reducers/index.js
@@ -1,8 +1,10 @@
import { combineReducers } from "redux";
import authReducer from "./authReducer";
+import userReducer from "./userReducer";
const reducer = combineReducers({
- auth: authReducer
+ auth: authReducer,
+ user: userReducer
});
export default reducer;
diff --git a/src/reducers/userReducer.js b/src/reducers/userReducer.js
new file mode 100644
index 0000000..23c7df5
--- /dev/null
+++ b/src/reducers/userReducer.js
@@ -0,0 +1,54 @@
+import {
+ IS_SENDING_USER_REQUEST,
+ SET_USER_REQUEST_ERROR,
+ CLEAR_USER_REQUEST_ERROR,
+ SET_USER_REQUEST_SUCCESS,
+ CLEAR_USER_REQUEST_SUCCESS,
+ SET_SELF_USER
+} from "../constants/user.constants";
+
+const initialState = {
+ isSendingUserRequest: false,
+ userRequestError: "",
+ userRequestSuccess: "",
+ selfUser: {}
+};
+
+function userReducer(state = initialState, action) {
+ switch (action.type) {
+ case IS_SENDING_USER_REQUEST:
+ return {
+ ...state,
+ isSendingUserRequest: action.data
+ };
+ case SET_USER_REQUEST_ERROR:
+ return {
+ ...state,
+ userRequestError: action.data
+ };
+ case CLEAR_USER_REQUEST_ERROR:
+ return {
+ ...state,
+ userRequestError: ""
+ };
+ case SET_USER_REQUEST_SUCCESS:
+ return {
+ ...state,
+ userRequestSuccess: action.data
+ };
+ case CLEAR_USER_REQUEST_SUCCESS:
+ return {
+ ...state,
+ userRequestSuccess: ""
+ };
+ case SET_SELF_USER:
+ return {
+ ...state,
+ selfUser: action.data
+ };
+ default:
+ return state;
+ }
+}
+
+export default userReducer;
diff --git a/src/sagas/auth.sagas.js b/src/sagas/auth.sagas.js
index b27a609..ecb2d23 100644
--- a/src/sagas/auth.sagas.js
+++ b/src/sagas/auth.sagas.js
@@ -11,6 +11,7 @@ import {
setFormPasswordConfirmation,
setFormOldPassword
} from "../actions/auth/reducer.actions";
+import { setSelfUser } from "../actions/user/reducer.actions";
import {
registerUser,
verifyEmail,
@@ -156,6 +157,7 @@ export function* logoutUserFlow(request) {
yield effects.put(clearAuthRequestError());
yield effects.call(logoutUserCall);
yield effects.put(setSelfUserToken(""));
+ yield effects.put(setSelfUser({}));
}
export function* changePasswordFlow(request) {
diff --git a/src/sagas/index.js b/src/sagas/index.js
index 73f6d25..c51270f 100644
--- a/src/sagas/index.js
+++ b/src/sagas/index.js
@@ -17,6 +17,12 @@ import {
forgotPasswordFlow,
resetPasswordFlow,
} from "./auth.sagas";
+import {
+ SEND_GET_SELF_USER_REQUEST
+} from "../constants/user.constants";
+import {
+ getSelfUserFlow
+} from "./user.sagas";
export default function* rootSaga() {
yield takeLatest(SEND_REGISTER_REQUEST, registerUserFlow);
@@ -26,4 +32,5 @@ export default function* rootSaga() {
yield takeLatest(SEND_CHANGE_PASSWORD_REQUEST, changePasswordFlow);
yield takeLatest(SEND_FORGOT_PASSWORD_REQUEST, forgotPasswordFlow);
yield takeLatest(SEND_RESET_PASSWORD_REQUEST, resetPasswordFlow);
+ yield takeLatest(SEND_GET_SELF_USER_REQUEST, getSelfUserFlow);
}
diff --git a/src/sagas/user.sagas.js b/src/sagas/user.sagas.js
new file mode 100644
index 0000000..e27d612
--- /dev/null
+++ b/src/sagas/user.sagas.js
@@ -0,0 +1,43 @@
+import { effects } from "redux-saga";
+import { setSelfUserToken } from "../actions/auth/reducer.actions";
+import {
+ isSendingUserRequest,
+ setUserRequestError,
+ setUserRequestSuccess,
+ clearUserRequestError,
+ clearUserRequestSuccess,
+ setSelfUser
+} from "../actions/user/reducer.actions";
+import { getSelfUser } from "../api/user.api";
+
+function* getSelfUserCall() {
+ yield effects.put(isSendingUserRequest(true));
+ try {
+ const wasSuccessful = yield effects.call(getSelfUser);
+ yield effects.put(setUserRequestSuccess(wasSuccessful));
+ yield effects.put(clearUserRequestError());
+ // Check if the user exists, if yes set the user, otherwise force logout
+ if (wasSuccessful.results && wasSuccessful.results.length) {
+ yield effects.put(setSelfUser(wasSuccessful.results[0]));
+ } else {
+ yield effects.put(setSelfUserToken(""));
+ yield effects.put(setSelfUser({}));
+ }
+ return wasSuccessful;
+ } catch (exception) {
+ yield effects.put(setUserRequestError(exception));
+ return false;
+ } finally {
+ yield effects.put(isSendingUserRequest(false));
+ }
+}
+
+export function* getSelfUserFlow(request) {
+ yield effects.put(clearUserRequestSuccess());
+ yield effects.put(clearUserRequestError());
+ const wasSuccessful = yield effects.call(getSelfUserCall);
+ if (!wasSuccessful) {
+ yield effects.put(setSelfUserToken(""));
+ yield effects.put(setSelfUser({}));
+ }
+}