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"