From 9b56dd9244c28c361f9c784f5d58f3b9fbee1603 Mon Sep 17 00:00:00 2001
From: = <=>
Date: Thu, 3 Dec 2020 20:50:18 +0100
Subject: [PATCH] Add basic profile page
---
package.json | 2 +
src/containers/App/index.js | 14 ++--
src/containers/App/reducer.js | 3 +-
src/containers/Routes/index.js | 20 +++++
src/pages/Login/actions.js | 2 +-
src/pages/Login/reducer.js | 5 +-
src/pages/Login/saga.js | 4 +-
src/pages/Profile/actions.js | 90 ++++++++++++++++++++
src/pages/Profile/constants.js | 17 ++++
src/pages/Profile/index.js | 145 +++++++++++++++++++++++++++++++++
src/pages/Profile/reducer.js | 77 +++++++++++++++++
src/pages/Profile/saga.js | 111 +++++++++++++++++++++++++
src/pages/Profile/selectors.js | 44 ++++++++++
src/utils/api.js | 8 +-
src/utils/configureStore.js | 14 ++--
src/utils/routes.js | 10 +++
yarn.lock | 49 ++++++++++-
17 files changed, 590 insertions(+), 25 deletions(-)
create mode 100644 src/containers/Routes/index.js
create mode 100644 src/pages/Profile/actions.js
create mode 100644 src/pages/Profile/constants.js
create mode 100644 src/pages/Profile/index.js
create mode 100644 src/pages/Profile/reducer.js
create mode 100644 src/pages/Profile/saga.js
create mode 100644 src/pages/Profile/selectors.js
diff --git a/package.json b/package.json
index bd60e24..30ab5a3 100644
--- a/package.json
+++ b/package.json
@@ -3,8 +3,10 @@
"version": "0.1.0",
"private": true,
"dependencies": {
+ "@date-io/date-fns": "^2.10.6",
"@material-ui/core": "^4.11.1",
"@material-ui/icons": "^4.9.1",
+ "@material-ui/pickers": "^3.2.10",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
diff --git a/src/containers/App/index.js b/src/containers/App/index.js
index dfc6eda..c19c7b9 100644
--- a/src/containers/App/index.js
+++ b/src/containers/App/index.js
@@ -1,15 +1,13 @@
import React from 'react';
-import {Route, Switch} from 'react-router-dom';
import { ThemeProvider } from '@material-ui/core/styles'
import {createStructuredSelector} from "reselect";
import CssBaseline from '@material-ui/core/CssBaseline'
-import { theme, routes } from 'utils'
+import { theme } from 'utils'
import {makeSelectIsLogged} from "./selectors";
import { useSelector } from 'react-redux';
import Navbar from 'components/Navbar'
-import HomePage from 'pages/Home'
-import LoginPage from 'pages/Login'
+import Routes from 'containers/Routes'
const stateSelector = createStructuredSelector({
isLogged: makeSelectIsLogged(),
@@ -21,11 +19,9 @@ const App = () => {
return (
- {isLogged && }
-
-
-
-
+ {/*{isLogged && }*/}
+
+
);
};
diff --git a/src/containers/App/reducer.js b/src/containers/App/reducer.js
index 72e87fc..cdd758c 100644
--- a/src/containers/App/reducer.js
+++ b/src/containers/App/reducer.js
@@ -19,11 +19,10 @@ const appReducer = produce((draft, action) => {
draft.tokens = action.tokens;
draft.user = action.user;
break;
+
case LOGOUT_ERROR:
case LOGOUT_SUCCESS:
return initialState;
- default:
- return initialState;
}
}, initialState);
diff --git a/src/containers/Routes/index.js b/src/containers/Routes/index.js
new file mode 100644
index 0000000..c49e7f5
--- /dev/null
+++ b/src/containers/Routes/index.js
@@ -0,0 +1,20 @@
+import React from 'react';
+import {Route, Switch} from "react-router-dom";
+import {routes} from "utils";
+
+const Routes = () => {
+ return (
+
+ {Object.values(routes).map(({ exact, path, component }, index) => (
+
+ ))}
+
+ );
+};
+
+export default Routes;
diff --git a/src/pages/Login/actions.js b/src/pages/Login/actions.js
index 1e8db07..d3d65e8 100644
--- a/src/pages/Login/actions.js
+++ b/src/pages/Login/actions.js
@@ -10,7 +10,7 @@ export const loginAction = () => ({
type: LOGIN_REQUEST,
})
-export const loginSuccessAction = (user, tokens) => ({
+export const loginSuccessAction = ({user, tokens}) => ({
type: LOGIN_SUCCESS,
user,
tokens,
diff --git a/src/pages/Login/reducer.js b/src/pages/Login/reducer.js
index 760add0..3bb0dbc 100644
--- a/src/pages/Login/reducer.js
+++ b/src/pages/Login/reducer.js
@@ -13,18 +13,19 @@ const loginPageReducer = produce((draft, action) => {
case LOGIN_SUCCESS:
draft.loading = false;
break;
+
case LOGIN_REQUEST:
draft.loading = true;
break;
+
case LOGIN_ERROR:
draft.loading = false;
draft.error = action.error;
break;
+
case LOGIN_INPUT_CHANGE:
draft[action.name] = action.value;
break;
- default:
- return initialState;
}
}, initialState);
diff --git a/src/pages/Login/saga.js b/src/pages/Login/saga.js
index 1cfc3d6..22bc1d6 100644
--- a/src/pages/Login/saga.js
+++ b/src/pages/Login/saga.js
@@ -18,8 +18,8 @@ export function* login() {
try {
const { tokens, user } = yield call(request, requestURL, requestParameters);
- yield put(loginSuccessAction(user, tokens));
- yield put(push(routes.dashboard.path));
+ yield put(loginSuccessAction({user, tokens}));
+ yield put(push(routes.profile.path));
} catch (error) {
yield put(loginErrorAction(error.message));
}
diff --git a/src/pages/Profile/actions.js b/src/pages/Profile/actions.js
new file mode 100644
index 0000000..42bc07c
--- /dev/null
+++ b/src/pages/Profile/actions.js
@@ -0,0 +1,90 @@
+import {
+ GET_ACTIVITIES_REQUEST,
+ GET_ACTIVITIES_SUCCESS,
+ GET_ACTIVITIES_ERROR,
+ GET_GENDERS_ERROR,
+ GET_GENDERS_REQUEST,
+ GET_GENDERS_SUCCESS,
+ PROFILE_INPUT_CHANGE,
+ GET_PROFILE_REQUEST,
+ GET_PROFILE_SUCCESS,
+ GET_PROFILE_ERROR,
+ UPDATE_PROFILE_REQUEST,
+ UPDATE_PROFILE_SUCCESS,
+ UPDATE_PROFILE_ERROR
+} from './constants';
+
+export const profileInputChange = ({name, value}) => ({
+ type: PROFILE_INPUT_CHANGE,
+ name,
+ value,
+})
+
+export const getProfileAction = () => ({
+ type: GET_PROFILE_REQUEST,
+})
+
+export const getProfileSuccessAction = ({birthday, gender, height, currentWeight, goalWeight, rateOfChange, activity}) => ({
+ type: GET_PROFILE_SUCCESS,
+ birthday,
+ gender,
+ height,
+ currentWeight,
+ goalWeight,
+ rateOfChange,
+ activity
+})
+
+export const getProfileErrorAction = (error) => ({
+ type: GET_PROFILE_ERROR,
+ error,
+})
+
+
+export const updateProfileAction = () => ({
+ type: UPDATE_PROFILE_REQUEST,
+})
+
+export const updateProfileSuccessAction = ({birthday, gender, height, currentWeight, goalWeight, rateOfChange, activity}) => ({
+ type: UPDATE_PROFILE_SUCCESS,
+ birthday,
+ gender,
+ height,
+ currentWeight,
+ goalWeight,
+ rateOfChange,
+ activity
+})
+
+export const updateProfileErrorAction = (error) => ({
+ type: UPDATE_PROFILE_ERROR,
+ error,
+})
+
+export const getActivitiesAction = () => ({
+ type: GET_ACTIVITIES_REQUEST,
+})
+
+export const getActivitiesSuccessAction = ({ activities }) => ({
+ type: GET_ACTIVITIES_SUCCESS,
+ activities,
+})
+
+export const getActivitiesErrorAction = (error) => ({
+ type: GET_ACTIVITIES_ERROR,
+ error,
+})
+
+export const getGendersAction = () => ({
+ type: GET_GENDERS_REQUEST,
+})
+
+export const getGendersSuccessAction = ({ genders }) => ({
+ type: GET_GENDERS_SUCCESS,
+ genders,
+})
+
+export const getGendersErrorAction = (error) => ({
+ type: GET_GENDERS_ERROR,
+ error,
+})
diff --git a/src/pages/Profile/constants.js b/src/pages/Profile/constants.js
new file mode 100644
index 0000000..744f1ba
--- /dev/null
+++ b/src/pages/Profile/constants.js
@@ -0,0 +1,17 @@
+export const GET_PROFILE_REQUEST = 'app/ProfilePage/GET_PROFILE_REQUEST';
+export const GET_PROFILE_SUCCESS = 'app/ProfilePage/GET_PROFILE_SUCCESS';
+export const GET_PROFILE_ERROR = 'app/ProfilePage/GET_PROFILE_ERROR';
+
+export const UPDATE_PROFILE_REQUEST = 'app/ProfilePage/UPDATE_PROFILE_REQUEST';
+export const UPDATE_PROFILE_SUCCESS = 'app/ProfilePage/UPDATE_PROFILE_SUCCESS';
+export const UPDATE_PROFILE_ERROR = 'app/ProfilePage/UPDATE_PROFILE_ERROR';
+
+export const GET_GENDERS_REQUEST = 'app/ProfilePage/GET_GENDERS_REQUEST';
+export const GET_GENDERS_SUCCESS = 'app/ProfilePage/GET_GENDERS_SUCCESS';
+export const GET_GENDERS_ERROR = 'app/ProfilePage/GET_GENDERS_ERROR';
+
+export const GET_ACTIVITIES_REQUEST = 'app/ProfilePage/GET_ACTIVITIES_REQUEST';
+export const GET_ACTIVITIES_SUCCESS = 'app/ProfilePage/GET_ACTIVITIES_SUCCESS';
+export const GET_ACTIVITIES_ERROR = 'app/ProfilePage/GET_ACTIVITIES_ERROR';
+
+export const PROFILE_INPUT_CHANGE = 'app/ProfilePage/PROFILE_INPUT_CHANGE';
diff --git a/src/pages/Profile/index.js b/src/pages/Profile/index.js
new file mode 100644
index 0000000..f8a499f
--- /dev/null
+++ b/src/pages/Profile/index.js
@@ -0,0 +1,145 @@
+import React, { useEffect } from 'react';
+import { Container, Slider, Button, TextField, FormControl, MenuItem, InputLabel, Select, Grid, Typography } from '@material-ui/core'
+import {useInjectReducer, useInjectSaga} from "redux-injectors";
+import reducer from "./reducer";
+import saga from "./saga";
+import { useSelector, useDispatch } from 'react-redux';
+import {createStructuredSelector} from "reselect";
+import { profileInputChange, getProfileAction, getActivitiesAction, getGendersAction } from './actions'
+import {
+ makeSelectError,
+ makeSelectBirthday,
+ makeSelectHeight,
+ makeSelectCurrentWeight,
+ makeSelectRateOfChange,
+ makeSelectActivity,
+ makeSelectGoalWeight,
+ makeSelectGender,
+ makeSelectLoading,
+} from "./selectors";
+
+const stateSelector = createStructuredSelector({
+ loading: makeSelectLoading(),
+ error: makeSelectError(),
+ gender: makeSelectGender(),
+ birthday: makeSelectBirthday(),
+ height: makeSelectHeight(),
+ currentWeight: makeSelectCurrentWeight(),
+ goalWeight: makeSelectGoalWeight(),
+ rateOfChange: makeSelectRateOfChange(),
+ activity: makeSelectActivity(),
+});
+
+const key = 'profilePage'
+const ProfilePage = () => {
+ useInjectReducer({ key, reducer });
+ useInjectSaga({ key, saga });
+ const dispatch = useDispatch()
+ const {
+ gender,
+ birthday,
+ height,
+ currentWeight,
+ goalWeight,
+ rateOfChange,
+ activity,
+ } = useSelector(stateSelector)
+
+ const getProfile = () => dispatch(getProfileAction())
+ const getActivities = () => dispatch(getActivitiesAction())
+ const getGenders = () => dispatch(getGendersAction())
+
+ useEffect(() => {
+ getProfile()
+ getActivities()
+ getGenders()
+ }, [])
+
+const handleChange = ({ target: { name, value }}) => {
+ dispatch(profileInputChange({ name, value }))
+ }
+
+ return (
+
+
+ Profile
+
+ Gender
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The rate of weight change
+
+
+
+
+ Activity
+
+
+
+
+
+
+
+ );
+};
+
+export default ProfilePage;
diff --git a/src/pages/Profile/reducer.js b/src/pages/Profile/reducer.js
new file mode 100644
index 0000000..9ecbf93
--- /dev/null
+++ b/src/pages/Profile/reducer.js
@@ -0,0 +1,77 @@
+import produce from 'immer';
+import {
+ GET_ACTIVITIES_SUCCESS,
+ GET_GENDERS_SUCCESS,
+ GET_ACTIVITIES_ERROR,
+ GET_GENDERS_ERROR,
+ GET_ACTIVITIES_REQUEST,
+ GET_GENDERS_REQUEST,
+ PROFILE_INPUT_CHANGE,
+ GET_PROFILE_REQUEST,
+ GET_PROFILE_SUCCESS,
+ GET_PROFILE_ERROR,
+ UPDATE_PROFILE_REQUEST,
+ UPDATE_PROFILE_SUCCESS,
+ UPDATE_PROFILE_ERROR
+} from './constants';
+
+export const initialState = {
+ activities: [],
+ genders: [],
+ loading: false,
+ error: {},
+ gender: '',
+ birthday: '',
+ height: 0,
+ currentWeight: 0,
+ goalWeight: 0,
+ rateOfChange: 0,
+ activity: 0,
+};
+
+const loginPageReducer = produce((draft, action) => {
+ switch(action.type) {
+ case GET_ACTIVITIES_SUCCESS:
+ draft.activities = action.activities;
+ draft.loading = false;
+ break;
+
+ case GET_GENDERS_SUCCESS:
+ draft.genders = action.genders;
+ draft.loading = false;
+ break;
+
+ case GET_PROFILE_SUCCESS:
+ case UPDATE_PROFILE_SUCCESS:
+ draft.birthday = action.birthday;
+ draft.gender = action.gender;
+ draft.height = action.height;
+ draft.currentWeight = action.currentWeight;
+ draft.goalWeight = action.goalWeight;
+ draft.rateOfChange = action.rateOfChange;
+ draft.activity = action.activity;
+ draft.loading = false;
+ break;
+
+ case GET_ACTIVITIES_REQUEST:
+ case GET_GENDERS_REQUEST:
+ case GET_PROFILE_REQUEST:
+ case UPDATE_PROFILE_REQUEST:
+ draft.loading = true;
+ break;
+
+ case GET_ACTIVITIES_ERROR:
+ case GET_GENDERS_ERROR:
+ case GET_PROFILE_ERROR:
+ case UPDATE_PROFILE_ERROR:
+ draft.loading = false;
+ draft.error = action.error;
+ break;
+
+ case PROFILE_INPUT_CHANGE:
+ draft[action.name] = action.value;
+ break;
+ }
+}, initialState);
+
+export default loginPageReducer;
diff --git a/src/pages/Profile/saga.js b/src/pages/Profile/saga.js
new file mode 100644
index 0000000..6c700ca
--- /dev/null
+++ b/src/pages/Profile/saga.js
@@ -0,0 +1,111 @@
+import { takeLatest, call, put, select } from 'redux-saga/effects';
+import { api, request } from 'utils';
+import { GET_ACTIVITIES_REQUEST, GET_GENDERS_REQUEST, GET_PROFILE_REQUEST, UPDATE_PROFILE_REQUEST } from './constants';
+import {
+ makeSelectBirthday,
+ makeSelectHeight,
+ makeSelectCurrentWeight,
+ makeSelectRateOfChange,
+ makeSelectActivity,
+ makeSelectGoalWeight,
+ makeSelectGender
+} from './selectors';
+import { getActivitiesSuccessAction, getActivitiesErrorAction, getGendersSuccessAction, getGendersErrorAction, updateProfileErrorAction, updateProfileSuccessAction, getProfileErrorAction, getProfileSuccessAction } from './actions';
+
+import { makeSelectTokens } from 'containers/App/selectors'
+
+export function* getProfile() {
+ const { access } = yield select(makeSelectTokens());
+
+ const requestURL = api.profile;
+
+ const requestParameters = {
+ method: 'GET',
+ headers: {
+ Authorization: `Bearer ${access.token}`,
+ },
+ };
+
+ try {
+ const { birthday, gender, height, currentWeight, goalWeight, rateOfChange, activity } = yield call(request, requestURL, requestParameters);
+ yield put(getProfileSuccessAction({birthday, gender, height, currentWeight, goalWeight, rateOfChange, activity}));
+ } catch (error) {
+ yield put(getProfileErrorAction(error.message));
+ }
+}
+
+export function* updateProfile() {
+ const { access } = yield select(makeSelectTokens());
+
+ const birthday = yield select(makeSelectBirthday());
+ const gender = yield select(makeSelectGender());
+ const height = yield select(makeSelectHeight());
+ const currentWeight = yield select(makeSelectCurrentWeight());
+ const goalWeight = yield select(makeSelectGoalWeight());
+ const rateOfChange = yield select(makeSelectRateOfChange());
+ const activity = yield select(makeSelectActivity());
+
+ const requestURL = api.profile;
+
+ const requestParameters = {
+ method: 'POST',
+ headers: { Accept: 'application/json', 'Content-Type': 'application/json', Authorization: `Bearer ${access.token}`, },
+ body: JSON.stringify({ birthday, gender, height, currentWeight, goalWeight, rateOfChange, activity }),
+ };
+
+ try {
+ const { birthday, gender, height, currentWeight, goalWeight, rateOfChange, activity } = yield call(request, requestURL, requestParameters);
+ yield put(updateProfileSuccessAction({birthday, gender, height, currentWeight, goalWeight, rateOfChange, activity}));
+ } catch (error) {
+ yield put(updateProfileErrorAction(error.message));
+ }
+}
+
+export function* getActivities() {
+ const { access } = yield select(makeSelectTokens());
+
+ const requestURL = api.activities;
+
+ const requestParameters = {
+ method: 'GET',
+ headers: {
+ Authorization: `Bearer ${access.token}`,
+ },
+ };
+
+ try {
+ const { activities } = yield call(request, requestURL, requestParameters);
+ yield put(getActivitiesSuccessAction({ activities }));
+ } catch (error) {
+ yield put(getActivitiesErrorAction(error.message));
+ }
+}
+
+
+export function* getGenders() {
+ const { access } = yield select(makeSelectTokens());
+
+ const requestURL = api.genders;
+
+ const requestParameters = {
+ method: 'GET',
+ headers: {
+ Authorization: `Bearer ${access.token}`,
+ },
+ };
+
+ try {
+ const { genders } = yield call(request, requestURL, requestParameters);
+ yield put(getGendersSuccessAction({ genders }));
+ } catch (error) {
+ yield put(getGendersErrorAction(error.message));
+ }
+}
+
+export default function* profilePageSaga() {
+ yield takeLatest(GET_PROFILE_REQUEST, getProfile);
+ yield takeLatest(GET_ACTIVITIES_REQUEST, getActivities);
+ yield takeLatest(GET_GENDERS_REQUEST, getGenders);
+ yield takeLatest(GET_PROFILE_REQUEST, getProfile);
+ yield takeLatest(UPDATE_PROFILE_REQUEST, updateProfile);
+}
diff --git a/src/pages/Profile/selectors.js b/src/pages/Profile/selectors.js
new file mode 100644
index 0000000..ce35d29
--- /dev/null
+++ b/src/pages/Profile/selectors.js
@@ -0,0 +1,44 @@
+import { createSelector } from 'reselect';
+import { initialState } from './reducer';
+
+const selectProfilePageDomain = (state) => state.profilePage || initialState;
+
+const makeSelectError = () =>
+ createSelector(selectProfilePageDomain, (substate) => substate.error);
+
+const makeSelectBirthday = () =>
+ createSelector(selectProfilePageDomain, (substate) => substate.birthday);
+
+const makeSelectHeight = () =>
+ createSelector(selectProfilePageDomain, (substate) => substate.height);
+
+const makeSelectCurrentWeight = () =>
+ createSelector(selectProfilePageDomain, (substate) => substate.currentWeight);
+
+const makeSelectRateOfChange = () =>
+ createSelector(selectProfilePageDomain, (substate) => substate.rateOfChange);
+
+const makeSelectActivity = () =>
+ createSelector(selectProfilePageDomain, (substate) => substate.activity);
+
+const makeSelectGoalWeight = () =>
+ createSelector(selectProfilePageDomain, (substate) => substate.goalWeight);
+
+const makeSelectGender = () =>
+ createSelector(selectProfilePageDomain, (substate) => substate.gender);
+
+const makeSelectLoading = () =>
+ createSelector(selectProfilePageDomain, (substate) => substate.loading);
+
+export {
+ selectProfilePageDomain,
+ makeSelectError,
+ makeSelectBirthday,
+ makeSelectHeight,
+ makeSelectCurrentWeight,
+ makeSelectRateOfChange,
+ makeSelectActivity,
+ makeSelectGoalWeight,
+ makeSelectGender,
+ makeSelectLoading,
+};
diff --git a/src/utils/api.js b/src/utils/api.js
index dfaa36a..575f679 100644
--- a/src/utils/api.js
+++ b/src/utils/api.js
@@ -1,11 +1,17 @@
const API_BASE_URL = 'http://localhost:3001/v1'
const AUTH = 'auth';
+const PROFILE = 'profiles';
+const ACTIVITY = 'activities';
+const GENDER = 'genders';
const urls = {
auth: {
login: `${API_BASE_URL}/${AUTH}/login`,
register: `${API_BASE_URL}/${AUTH}/register`,
- }
+ },
+ profile: `${API_BASE_URL}/${PROFILE}`,
+ activities: `${API_BASE_URL}/${ACTIVITY}`,
+ genders: `${API_BASE_URL}/${GENDER}`,
}
export default urls
diff --git a/src/utils/configureStore.js b/src/utils/configureStore.js
index 5db2f3f..1627d26 100644
--- a/src/utils/configureStore.js
+++ b/src/utils/configureStore.js
@@ -1,6 +1,6 @@
import { createStore, applyMiddleware, compose } from 'redux';
import { routerMiddleware } from 'connected-react-router';
-import { createInjectorsEnhancer } from 'redux-injectors';
+import { createInjectorsEnhancer, forceReducerReload } from 'redux-injectors';
import createSagaMiddleware from 'redux-saga';
import createReducer from './reducers';
@@ -8,19 +8,17 @@ export default function configureStore(initialState = {}, history) {
let composeEnhancers = compose;
const reduxSagaMonitorOptions = {};
+ // If Redux Dev Tools and Saga Dev Tools Extensions are installed, enable them
+ /* istanbul ignore next */
if (typeof window === 'object') {
/* eslint-disable no-underscore-dangle */
if (window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__)
composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({});
-
}
const sagaMiddleware = createSagaMiddleware(reduxSagaMonitorOptions);
const { run: runSaga } = sagaMiddleware;
- // Create the store with two middlewares
- // 1. sagaMiddleware: Makes redux-sagas work
- // 2. routerMiddleware: Syncs the location/URL path to the state
const middlewares = [sagaMiddleware, routerMiddleware(history)];
const enhancers = [
@@ -37,5 +35,11 @@ export default function configureStore(initialState = {}, history) {
composeEnhancers(...enhancers),
);
+ if (module.hot) {
+ module.hot.accept('./reducers', () => {
+ forceReducerReload(store);
+ });
+ }
+
return store;
}
diff --git a/src/utils/routes.js b/src/utils/routes.js
index 53b4593..88b12fd 100644
--- a/src/utils/routes.js
+++ b/src/utils/routes.js
@@ -1,12 +1,22 @@
+import HomePage from "pages/Home";
+import ProfilePage from "pages/Profile";
+import LoginPage from "pages/Login";
const routes = {
dashboard: {
path: '/',
exact: true,
+ component: HomePage,
+ },
+ profile: {
+ path: '/profile',
+ exact: true,
+ component: ProfilePage,
},
login: {
path: '/login',
exact: true,
+ component: LoginPage,
},
}
diff --git a/yarn.lock b/yarn.lock
index 9bcd675..ffc9080 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -970,7 +970,7 @@
dependencies:
regenerator-runtime "^0.13.4"
-"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
+"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.12.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e"
integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==
@@ -1033,6 +1033,23 @@
resolved "https://registry.yarnpkg.com/@csstools/normalize.css/-/normalize.css-10.1.0.tgz#f0950bba18819512d42f7197e56c518aa491cf18"
integrity sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg==
+"@date-io/core@1.x":
+ version "1.3.13"
+ resolved "https://registry.yarnpkg.com/@date-io/core/-/core-1.3.13.tgz#90c71da493f20204b7a972929cc5c482d078b3fa"
+ integrity sha512-AlEKV7TxjeK+jxWVKcCFrfYAk8spX9aCyiToFIiLPtfQbsjmRGLIhb5VZgptQcJdHtLXo7+m0DuurwFgUToQuA==
+
+"@date-io/core@^2.10.6":
+ version "2.10.6"
+ resolved "https://registry.yarnpkg.com/@date-io/core/-/core-2.10.6.tgz#1a6e671b590a08af8bd0784f3a93670e5d2d5bd7"
+ integrity sha512-MGYt4GEB/4ZMdSbj6FS7/gPBvuhHUwnn5O6t8PlkSqGF1310qxypVyK4CZg5RQgev25L3R5eLVdNTyYrJOL8Rw==
+
+"@date-io/date-fns@^2.10.6":
+ version "2.10.6"
+ resolved "https://registry.yarnpkg.com/@date-io/date-fns/-/date-fns-2.10.6.tgz#d0afee6452d80112017f42af4912ba22d95b11b6"
+ integrity sha512-jUiIbs4VCmACy2Ml2xu3tqf0AUSZu4qQ3cRz8SoG4YPzeg1fqII8y/gTa7GJkXiH0bUKUWaf/G2dfJa9tUnmJA==
+ dependencies:
+ "@date-io/core" "^2.10.6"
+
"@emotion/hash@^0.8.0":
version "0.8.0"
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413"
@@ -1309,6 +1326,18 @@
dependencies:
"@babel/runtime" "^7.4.4"
+"@material-ui/pickers@^3.2.10":
+ version "3.2.10"
+ resolved "https://registry.yarnpkg.com/@material-ui/pickers/-/pickers-3.2.10.tgz#19df024895876eb0ec7cd239bbaea595f703f0ae"
+ integrity sha512-B8G6Obn5S3RCl7hwahkQj9sKUapwXWFjiaz/Bsw1fhYFdNMnDUolRiWQSoKPb1/oKe37Dtfszoywi1Ynbo3y8w==
+ dependencies:
+ "@babel/runtime" "^7.6.0"
+ "@date-io/core" "1.x"
+ "@types/styled-jsx" "^2.2.8"
+ clsx "^1.0.2"
+ react-transition-group "^4.0.0"
+ rifm "^0.7.0"
+
"@material-ui/styles@^4.11.1":
version "4.11.1"
resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.11.1.tgz#089338637e9c358eddccd75c32f0bafd0237d573"
@@ -1820,6 +1849,13 @@
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff"
integrity sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==
+"@types/styled-jsx@^2.2.8":
+ version "2.2.8"
+ resolved "https://registry.yarnpkg.com/@types/styled-jsx/-/styled-jsx-2.2.8.tgz#b50d13d8a3c34036282d65194554cf186bab7234"
+ integrity sha512-Yjye9VwMdYeXfS71ihueWRSxrruuXTwKCbzue4+5b2rjnQ//AtyM7myZ1BEhNhBQ/nL/RE7bdToUoLln2miKvg==
+ dependencies:
+ "@types/react" "*"
+
"@types/tapable@*", "@types/tapable@^1.0.5":
version "1.0.6"
resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.6.tgz#a9ca4b70a18b270ccb2bc0aaafefd1d486b7ea74"
@@ -3305,7 +3341,7 @@ clone-deep@^4.0.1:
kind-of "^6.0.2"
shallow-clone "^3.0.0"
-clsx@^1.0.4:
+clsx@^1.0.2, clsx@^1.0.4:
version "1.1.1"
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188"
integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==
@@ -9586,7 +9622,7 @@ react-transition-group@^2.5.0:
prop-types "^15.6.2"
react-lifecycles-compat "^3.0.4"
-react-transition-group@^4.4.0:
+react-transition-group@^4.0.0, react-transition-group@^4.4.0:
version "4.4.1"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9"
integrity sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw==
@@ -10049,6 +10085,13 @@ rgba-regex@^1.0.0:
resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3"
integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=
+rifm@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/rifm/-/rifm-0.7.0.tgz#debe951a9c83549ca6b33e5919f716044c2230be"
+ integrity sha512-DSOJTWHD67860I5ojetXdEQRIBvF6YcpNe53j0vn1vp9EUb9N80EiZTxgP+FkDKorWC8PZw052kTF4C1GOivCQ==
+ dependencies:
+ "@babel/runtime" "^7.3.1"
+
rimraf@2.6.3:
version "2.6.3"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"