diff --git a/package.json b/package.json index e432200..6c5a13e 100644 --- a/package.json +++ b/package.json @@ -13,14 +13,17 @@ "@testing-library/user-event": "^12.1.10", "connected-react-router": "^6.8.0", "date-fns": "^2.16.1", + "formik": "^2.2.6", "history": "4.10.1", "immer": "^8.0.0", + "joi": "^17.3.0", "lodash": "^4.17.20", "prop-types": "^15.7.2", "quagga": "^0.12.1", "react": "^17.0.1", "react-dom": "^17.0.1", "react-helmet": "^6.1.0", + "react-hook-form": "^6.13.1", "react-redux": "^7.2.2", "react-router-dom": "^5.2.0", "react-scripts": "4.0.0", diff --git a/src/components/GoalForm/index.js b/src/components/GoalForm/index.js index a5f77b1..1561c82 100644 --- a/src/components/GoalForm/index.js +++ b/src/components/GoalForm/index.js @@ -1,62 +1,103 @@ -import React, { useEffect } from 'react'; -import { Grid, Button, Typography, Radio, RadioGroup } from '@material-ui/core'; -import {useInjectReducer, useInjectSaga} from "redux-injectors"; -import { useSelector, useDispatch } from 'react-redux'; +import React from 'react'; +import {Grid, FormControlLabel, Slider, Button, Typography, Radio, RadioGroup, Box} from '@material-ui/core'; +import {useInjectReducer} from "redux-injectors"; +import { useSelector } from 'react-redux'; import {createStructuredSelector} from "reselect"; +import { useFormContext, Controller } from "react-hook-form"; import reducer from "pages/Profile/reducer"; -import saga from "pages/Profile/saga"; -import { profileInputChange, getGoalsAction } from 'pages/Profile/actions' import { - makeSelectError, - makeSelectIsLoading, makeSelectGoals, + makeSelectActivities, + makeSelectRatesOfChange, } from "pages/Profile/selectors"; -import Loader from './Loader' const stateSelector = createStructuredSelector({ - isLoading: makeSelectIsLoading(), - error: makeSelectError(), goals: makeSelectGoals(), + activities: makeSelectActivities(), }); const key = 'profilePage' const GoalForm = () => { useInjectReducer({ key, reducer }); - useInjectSaga({ key, saga }); - const dispatch = useDispatch() - const { goals, error, isLoading } = useSelector(stateSelector) - - const handleChangeGoal = ({ target: { name, value }}) => { - dispatch(profileInputChange({ name, value })) - } - - useEffect(() => { - dispatch(getGoalsAction()) - }, []) + const { goals, activities, ratesOfChange } = useSelector(stateSelector) + const { control } = useFormContext() return ( - Your goal + Goal - - - {isLoading ? ( - - ) : ( - - {goals.map(({ name, value }, index) => ( - - - - ))} - - )} + + + + + {goals.map(({ label, value }) => ( + + + + ))} + + + } + /> - + + + Activity + + + ( + onChange(value)} + min={1.2} + step={null} + max={1.9} + marks={activities} + /> + )} + /> + + + + + Rate of change + + + ( + onChange(value)} + min={0} + step={0.1} + max={1} + valueLabelDisplay="auto" + marks={ratesOfChange} + /> + )} + /> + + + ); } diff --git a/src/components/PersonalDetailsForm/index.js b/src/components/PersonalDetailsForm/index.js index ba900e6..af8d426 100644 --- a/src/components/PersonalDetailsForm/index.js +++ b/src/components/PersonalDetailsForm/index.js @@ -1,56 +1,32 @@ import 'date-fns'; -import React, { useEffect } from 'react'; +import React from 'react'; import {Typography, InputLabel, Box, Grid, InputAdornment, Select, FormControl, MenuItem, TextField, Slider} from '@material-ui/core'; import DateFnsUtils from '@date-io/date-fns'; +import { useFormContext, Controller } from "react-hook-form"; import { MuiPickersUtilsProvider, - KeyboardDatePicker, + DatePicker, } from '@material-ui/pickers'; -import {useInjectReducer, useInjectSaga} from "redux-injectors"; -import { useSelector, useDispatch } from 'react-redux'; +import {useInjectReducer} from "redux-injectors"; +import { useSelector } from 'react-redux'; import {createStructuredSelector} from "reselect"; import reducer from "pages/Profile/reducer"; -import saga from "pages/Profile/saga"; -import { profileInputChange, getActivitiesAction, getGendersAction } from 'pages/Profile/actions' import { - makeSelectError, - makeSelectIsLoading, makeSelectActivities, makeSelectGenders, - makeSelectWeight, - makeSelectHeight, - makeSelectBirthday, - makeSelectActivity, - makeSelectGender, } from "pages/Profile/selectors"; const stateSelector = createStructuredSelector({ - isLoading: makeSelectIsLoading(), - error: makeSelectError(), activities: makeSelectActivities(), genders: makeSelectGenders(), - weight: makeSelectWeight(), - height: makeSelectHeight(), - birthday: makeSelectBirthday(), - activity: makeSelectActivity(), - gender: makeSelectGender(), }); const key = 'profilePage' const PersonalDetailsForm = () => { useInjectReducer({ key, reducer }); - useInjectSaga({ key, saga }); - const dispatch = useDispatch() - const { gender, activity, birthday, height, weight, activities, genders, error, isLoading } = useSelector(stateSelector) + const { activities, genders } = useSelector(stateSelector) + const { register, control } = useFormContext() - const handleChangeValue = ({ target: { name, value }}) => { - dispatch(profileInputChange({ name, value })) - } - - useEffect(() => { - dispatch(getActivitiesAction()) - dispatch(getGendersAction()) - }, []) return ( @@ -61,79 +37,93 @@ const PersonalDetailsForm = () => { Gender - + as={ + + } + /> - - - + selected} + name="birthday" + render={({ onChange, value }) => ( + + + + )} + /> - cm - }} + as={ + cm + }} + /> + } /> - Kg - }} + Kg + }} + /> + } /> - - Activity - - - ({ - name, - value: factor - }))} - /> - + Kg + }} + /> + } + /> diff --git a/src/pages/Profile/actions.js b/src/pages/Profile/actions.js index adfe348..aa0bb98 100644 --- a/src/pages/Profile/actions.js +++ b/src/pages/Profile/actions.js @@ -1,13 +1,4 @@ import { - GET_GOALS_REQUEST, - GET_GOALS_SUCCESS, - GET_GOALS_ERROR, - 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, @@ -43,15 +34,15 @@ export const getProfileErrorAction = ({error}) => ({ error, }) - export const updateProfileAction = () => ({ type: UPDATE_PROFILE_REQUEST, }) -export const updateProfileSuccessAction = ({birthday, gender, height, weight, goalWeight, rateOfChange, activity}) => ({ +export const updateProfileSuccessAction = ({birthday, goal, gender, height, weight, goalWeight, rateOfChange, activity}) => ({ type: UPDATE_PROFILE_SUCCESS, birthday, gender, + goal, height, weight, goalWeight, @@ -64,45 +55,3 @@ export const updateProfileErrorAction = ({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, -}) - -export const getGoalsAction = () => ({ - type: GET_GOALS_REQUEST, -}) - -export const getGoalsSuccessAction = ({ goals }) => ({ - type: GET_GOALS_SUCCESS, - goals, -}) - -export const getGoalsErrorAction = ({error}) => ({ - type: GET_GOALS_ERROR, - error, -}) - diff --git a/src/pages/Profile/constants.js b/src/pages/Profile/constants.js index 4ce361c..f1e7d02 100644 --- a/src/pages/Profile/constants.js +++ b/src/pages/Profile/constants.js @@ -6,18 +6,4 @@ 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_GOALS_REQUEST = 'app/ProfilePage/GET_GOALS_REQUEST'; -export const GET_GOALS_SUCCESS = 'app/ProfilePage/GET_GOALS_SUCCESS'; -export const GET_GOALS_ERROR = 'app/ProfilePage/GET_GOALS_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 index d7434f8..9674528 100644 --- a/src/pages/Profile/index.js +++ b/src/pages/Profile/index.js @@ -3,6 +3,7 @@ import { makeStyles } from '@material-ui/core/styles'; import {Paper, Stepper, Step, StepLabel, Button, Typography } from '@material-ui/core'; import {useInjectReducer, useInjectSaga} from "redux-injectors"; import { useDispatch } from 'react-redux'; +import { useForm, useFormContext, FormProvider } from "react-hook-form"; import GoalForm from 'components/GoalForm'; import PersonalDetailsForm from 'components/PersonalDetailsForm'; import ReviewProfileForm from 'components/ReviewProfileForm'; @@ -49,11 +50,11 @@ const steps = ['Your goal', 'Personal details', 'Review your profile']; const getStepContent = (step) => { switch (step) { case 0: - return ; + return ; case 1: - return ; + return ; case 2: - return ; + return ; default: throw new Error('Unknown step'); } @@ -63,6 +64,20 @@ const key = 'profilePage' const ProfilePage = () => { const classes = useStyles(); const [activeStep, setActiveStep] = useState(0); + const methods = useForm({ + defaultValues: { + gender: '', + goal: 0, + birthday: '', + height: 0, + weight: { + current: 0, + goal: 0, + }, + rateOfChange: 0, + activity: 0, + } + }); useInjectReducer({ key, reducer }); useInjectSaga({ key, saga }); @@ -77,9 +92,8 @@ const ProfilePage = () => { setActiveStep(activeStep - 1); }; - const handleSubmitProfile = (event) => { - event.preventDefault(); - dispatch(updateProfileAction()) + const handleSubmitProfile = data => { + console.log('data', data) } return ( @@ -107,25 +121,28 @@ const ProfilePage = () => { ) : ( -
- {getStepContent(activeStep)} -
- {activeStep !== 0 && ( - - )} - -
-
+ +
+ {getStepContent(activeStep)} +
+ {activeStep !== 0 && ( + + )} + +
+
+
)} diff --git a/src/pages/Profile/reducer.js b/src/pages/Profile/reducer.js index 20bc36d..dbbf8d1 100644 --- a/src/pages/Profile/reducer.js +++ b/src/pages/Profile/reducer.js @@ -1,14 +1,5 @@ import produce from 'immer'; import { - GET_GOALS_REQUEST, - GET_GOALS_SUCCESS, - GET_GOALS_ERROR, - 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, @@ -19,61 +10,78 @@ import { } from './constants'; export const initialState = { - activities: [], - goals: [], - genders: [], + activities: [ + { + label: 'very low', + value: 1.2 + }, + { + label: 'low', + value: 1.375 + }, + { + label: 'medium', + value: 1.55 + },{ + label: 'high', + value: 1.725 + }, + { + label: 'very high', + value: 1.9 + }, + ], + goals: [ + { + label: 'lose weight', + value: -1, + }, + { + label: 'maintain weight', + value: 0, + }, + { + label: 'put on weight', + value: 1, + } + ], + ratesOfChange: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1], + genders: ['male', 'female'], isLoading: false, error: {}, gender: '', + goal: 0, birthday: new Date(), height: 0, - weight: 0, - goalWeight: 0, + weight: { + current: 0, + goal: 0, + }, rateOfChange: 0, activity: 0, }; const loginPageReducer = produce((draft, action) => { switch(action.type) { - case GET_ACTIVITIES_SUCCESS: - draft.activities = action.activities; - draft.isLoading = false; - break; - - case GET_GOALS_SUCCESS: - draft.goals = action.goals; - draft.isLoading = false; - break; - - case GET_GENDERS_SUCCESS: - draft.genders = action.genders; - draft.isLoading = false; - break; - case GET_PROFILE_SUCCESS: case UPDATE_PROFILE_SUCCESS: draft.birthday = action.birthday; draft.gender = action.gender; + draft.goal = action.goal; draft.height = action.height; - draft.weight = action.weight; - draft.goalWeight = action.goalWeight; + draft.weight.current = action.weight.current; + draft.weight.goal = action.weight.goal; draft.rateOfChange = action.rateOfChange; draft.activity = action.activity; draft.isLoading = false; break; - case GET_ACTIVITIES_REQUEST: - case GET_GENDERS_REQUEST: case GET_PROFILE_REQUEST: - case GET_GOALS_REQUEST: case UPDATE_PROFILE_REQUEST: draft.isLoading = true; break; - case GET_ACTIVITIES_ERROR: - case GET_GENDERS_ERROR: case GET_PROFILE_ERROR: - case GET_GOALS_ERROR: case UPDATE_PROFILE_ERROR: draft.isLoading = false; draft.error = action.error; diff --git a/src/pages/Profile/saga.js b/src/pages/Profile/saga.js index 533acfc..bb439c5 100644 --- a/src/pages/Profile/saga.js +++ b/src/pages/Profile/saga.js @@ -1,16 +1,16 @@ import { takeLatest, call, put, select } from 'redux-saga/effects'; import { api, request } from 'utils'; -import { GET_GOALS_REQUEST, GET_ACTIVITIES_REQUEST, GET_GENDERS_REQUEST, GET_PROFILE_REQUEST, UPDATE_PROFILE_REQUEST } from './constants'; +import { GET_PROFILE_REQUEST, UPDATE_PROFILE_REQUEST } from './constants'; import { makeSelectBirthday, makeSelectHeight, makeSelectWeight, makeSelectRateOfChange, makeSelectActivity, - makeSelectGoalWeight, + makeSelectGoal, makeSelectGender } from './selectors'; -import { getGoalsErrorAction, getGoalsSuccessAction, getActivitiesSuccessAction, getActivitiesErrorAction, getGendersSuccessAction, getGendersErrorAction, updateProfileErrorAction, updateProfileSuccessAction, getProfileErrorAction, getProfileSuccessAction } from './actions'; +import { updateProfileErrorAction, updateProfileSuccessAction, getProfileErrorAction, getProfileSuccessAction } from './actions'; import { makeSelectTokens } from 'containers/App/selectors' @@ -37,11 +37,11 @@ export function* getProfile() { export function* updateProfile() { const { access } = yield select(makeSelectTokens()); - const birthday = yield select(makeSelectBirthday()); const gender = yield select(makeSelectGender()); + const goal = yield select(makeSelectGoal()); + const birthday = yield select(makeSelectBirthday()); const height = yield select(makeSelectHeight()); const weight = yield select(makeSelectWeight()); - const goalWeight = yield select(makeSelectGoalWeight()); const rateOfChange = yield select(makeSelectRateOfChange()); const activity = yield select(makeSelectActivity()); @@ -50,7 +50,7 @@ export function* updateProfile() { const requestParameters = { method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'application/json', Authorization: `Bearer ${access.token}`, }, - body: JSON.stringify({ birthday, gender, height, weight, goalWeight, rateOfChange, activity }), + body: JSON.stringify({ birthday, gender, height, weight, goal, rateOfChange, activity }), }; try { @@ -61,70 +61,7 @@ export function* updateProfile() { } } -export function* getActivities() { - const { access } = yield select(makeSelectTokens()); - - const requestURL = api.activities; - - const requestParameters = { - method: 'GET', - headers: { - Authorization: `Bearer ${access.token}`, - }, - }; - - try { - const { results } = yield call(request, requestURL, requestParameters); - yield put(getActivitiesSuccessAction({ activities: results })); - } catch (error) { - yield put(getActivitiesErrorAction({error: 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 { results } = yield call(request, requestURL, requestParameters); - yield put(getGendersSuccessAction({ genders: results })); - } catch (error) { - yield put(getGendersErrorAction({ error: error.message })); - } -} -export function* getGoals() { - const { access } = yield select(makeSelectTokens()); - - const requestURL = api.goals; - - const requestParameters = { - method: 'GET', - headers: { - Authorization: `Bearer ${access.token}`, - }, - }; - - try { - const { results } = yield call(request, requestURL, requestParameters); - yield put(getGoalsSuccessAction({ goals: results })); - } catch (error) { - yield put(getGoalsErrorAction({ error: 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(GET_GOALS_REQUEST, getGoals); yield takeLatest(UPDATE_PROFILE_REQUEST, updateProfile); } diff --git a/src/pages/Profile/selectors.js b/src/pages/Profile/selectors.js index 8deee14..a209fde 100644 --- a/src/pages/Profile/selectors.js +++ b/src/pages/Profile/selectors.js @@ -21,8 +21,8 @@ const makeSelectRateOfChange = () => const makeSelectActivity = () => createSelector(selectProfilePageDomain, (substate) => substate.activity); -const makeSelectGoalWeight = () => - createSelector(selectProfilePageDomain, (substate) => substate.goalWeight); +const makeSelectGoal = () => + createSelector(selectProfilePageDomain, (substate) => substate.goal); const makeSelectGender = () => createSelector(selectProfilePageDomain, (substate) => substate.gender); @@ -39,6 +39,10 @@ const makeSelectActivities = () => const makeSelectGenders = () => createSelector(selectProfilePageDomain, (substate) => substate.genders); +const makeSelectRatesOfChange = () => + createSelector(selectProfilePageDomain, (substate) => substate.ratesOfChange); + + export { selectProfilePageDomain, makeSelectError, @@ -47,10 +51,11 @@ export { makeSelectWeight, makeSelectRateOfChange, makeSelectActivity, - makeSelectGoalWeight, + makeSelectGoal, makeSelectGender, makeSelectIsLoading, makeSelectGoals, makeSelectActivities, makeSelectGenders, + makeSelectRatesOfChange }; diff --git a/src/utils/api.js b/src/utils/api.js index 2a6cd90..cbd4991 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -1,9 +1,6 @@ const API_BASE_URL = 'http://localhost:3001/v1' const AUTH = 'auth'; const PROFILE = 'profiles'; -const ACTIVITY = 'activities'; -const GENDER = 'genders'; -const GOALS = 'goals'; const urls = { auth: { @@ -11,9 +8,6 @@ const urls = { register: `${API_BASE_URL}/${AUTH}/register`, }, profile: `${API_BASE_URL}/${PROFILE}`, - activities: `${API_BASE_URL}/${ACTIVITY}`, - genders: `${API_BASE_URL}/${GENDER}`, - goals: `${API_BASE_URL}/${GOALS}`, } export default urls diff --git a/yarn.lock b/yarn.lock index 71e1b29..4d9d28c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1081,6 +1081,11 @@ resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.5.1.tgz#fde96064ca446dec8c55a8c2f130957b070c6e06" integrity sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow== +"@hapi/hoek@^9.0.0": + version "9.1.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.1.0.tgz#6c9eafc78c1529248f8f4d92b0799a712b6052c6" + integrity sha512-i9YbZPN3QgfighY/1X1Pu118VUz2Fmmhd6b2n0/O8YVgGGfw0FbUYoA97k7FkpGJ+pLCFEDLUmAPPV4D1kpeFw== + "@hapi/joi@^15.1.0": version "15.1.1" resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.1.1.tgz#c675b8a71296f02833f8d6d243b34c57b8ce19d7" @@ -1098,6 +1103,13 @@ dependencies: "@hapi/hoek" "^8.3.0" +"@hapi/topo@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.0.0.tgz#c19af8577fa393a06e9c77b60995af959be721e7" + integrity sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw== + dependencies: + "@hapi/hoek" "^9.0.0" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -1511,6 +1523,23 @@ estree-walker "^1.0.1" picomatch "^2.2.2" +"@sideway/address@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.0.tgz#0b301ada10ac4e0e3fa525c90615e0b61a72b78d" + integrity sha512-wAH/JYRXeIFQRsxerIuLjgUu2Xszam+O5xKeatJ4oudShOOirfmsQ1D6LL54XOU2tizpCYku+s1wmU0SYdpoSA== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/formula@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" + integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== + +"@sideway/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" + integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + "@sinonjs/commons@^1.7.0": version "1.8.1" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217" @@ -4045,6 +4074,11 @@ deep-is@^0.1.3, deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= +deepmerge@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170" + integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA== + deepmerge@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" @@ -5224,6 +5258,19 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" +formik@^2.2.6: + version "2.2.6" + resolved "https://registry.yarnpkg.com/formik/-/formik-2.2.6.tgz#378a4bafe4b95caf6acf6db01f81f3fe5147559d" + integrity sha512-Kxk2zQRafy56zhLmrzcbryUpMBvT0tal5IvcifK5+4YNGelKsnrODFJ0sZQRMQboblWNym4lAW3bt+tf2vApSA== + dependencies: + deepmerge "^2.1.1" + hoist-non-react-statics "^3.3.0" + lodash "^4.17.14" + lodash-es "^4.17.14" + react-fast-compare "^2.0.1" + tiny-warning "^1.0.2" + tslib "^1.10.0" + forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" @@ -5625,7 +5672,7 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.2: +hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -6869,6 +6916,17 @@ jest@26.6.0: import-local "^3.0.2" jest-cli "^26.6.0" +joi@^17.3.0: + version "17.3.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.3.0.tgz#f1be4a6ce29bc1716665819ac361dfa139fff5d2" + integrity sha512-Qh5gdU6niuYbUIUV5ejbsMiiFmBdw8Kcp8Buj2JntszCkCfxJ9Cz76OtHxOZMPXrt5810iDIXs+n1nNVoquHgg== + dependencies: + "@hapi/hoek" "^9.0.0" + "@hapi/topo" "^5.0.0" + "@sideway/address" "^4.1.0" + "@sideway/formula" "^3.0.0" + "@sideway/pinpoint" "^2.0.0" + jpeg-js@^0.3.2: version "0.3.7" resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.3.7.tgz#471a89d06011640592d314158608690172b1028d" @@ -7266,6 +7324,11 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +lodash-es@^4.17.14: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78" + integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ== + lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -9453,6 +9516,11 @@ react-error-overlay@^6.0.8: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.8.tgz#474ed11d04fc6bda3af643447d85e9127ed6b5de" integrity sha512-HvPuUQnLp5H7TouGq3kzBeioJmXms1wHy9EGjz2OURWBp4qZO6AfGEcnxts1D/CbwPLRAgTMPCEgYhA3sEM4vw== +react-fast-compare@^2.0.1: + version "2.0.4" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" + integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== + react-fast-compare@^3.1.1: version "3.2.0" resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" @@ -9468,6 +9536,11 @@ react-helmet@^6.1.0: react-fast-compare "^3.1.1" react-side-effect "^2.1.0" +react-hook-form@^6.13.1: + version "6.13.1" + resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-6.13.1.tgz#b9c0aa61f746db8169ed5e1050de21cacb1947d6" + integrity sha512-Q0N7MYcbA8SigYufb02h9z97ZKCpIbe62rywOTPsK4Ntvh6fRTGDXSuzWuRhLHhArLoWbGrWYSNSS4tlb+OFXg== + react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"