react form hooks

This commit is contained in:
= 2020-12-17 15:58:07 +01:00
parent 6c807dcc30
commit 803bd65a87
11 changed files with 342 additions and 339 deletions

View File

@ -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",

View File

@ -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 (
<React.Fragment>
<Typography variant="h6" gutterBottom>
Your goal
Goal
</Typography>
<RadioGroup defaultValue={1} onChange={handleChangeGoal}>
<Grid container spacing={3} direction="column">
{isLoading ? (
<Loader />
) : (
<React.Fragment>
{goals.map(({ name, value }, index) => (
<Grid item xs={12} key={index}>
<Button variant="text" fullWidth>
{name}
<Radio color="secondary" name="goal" value={value} />
</Button>
</Grid>
))}
</React.Fragment>
)}
<Grid>
<Grid>
<Controller
name="goal"
control={control}
as={
<RadioGroup aria-label="Your goal">
<Grid container spacing={2} >
{goals.map(({ label, value }) => (
<Grid item xs={4} key={value}>
<Button variant="text" fullWidth>
<FormControlLabel
key={value}
value={value.toString()}
control={<Radio />}
label={label}
/>
</Button>
</Grid>
))}
</Grid>
</RadioGroup>
}
/>
</Grid>
</RadioGroup>
<Grid>
<Typography variant="h6" gutterBottom>
Activity
</Typography>
<Box mx={4}>
<Controller
name="activity"
control={control}
defaultValue={5}
render={({onChange, ...props}) => (
<Slider
{...props}
onChange={(_, value) => onChange(value)}
min={1.2}
step={null}
max={1.9}
marks={activities}
/>
)}
/>
</Box>
</Grid>
<Grid>
<Typography mt={2} variant="h6" gutterBottom>
Rate of change
</Typography>
<Box mx={4}>
<Controller
name="rateOfChange"
control={control}
defaultValue={0}
render={({onChange, ...props}) => (
<Slider
{...props}
onChange={(_, value) => onChange(value)}
min={0}
step={0.1}
max={1}
valueLabelDisplay="auto"
marks={ratesOfChange}
/>
)}
/>
</Box>
</Grid>
</Grid>
</React.Fragment>
);
}

View File

@ -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 (
<React.Fragment>
@ -61,79 +37,93 @@ const PersonalDetailsForm = () => {
<Grid item xs={12}>
<FormControl variant="outlined" fullWidth>
<InputLabel>Gender</InputLabel>
<Select
<Controller
control={control}
name="gender"
label="Gender"
onChange={handleChangeValue}
value={gender}
>
{genders.map(({ id, name }) => (
<MenuItem value={id} key={id}>{name}</MenuItem>
))}
</Select>
as={
<Select
label="Gender"
name="gender"
>
{genders.map(label => (
<MenuItem value={label} key={label}>{label}</MenuItem>
))}
</Select>
}
/>
</FormControl>
</Grid>
<Grid item xs={12}>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<KeyboardDatePicker
disableToolbar
inputVariant="outlined"
fullWidth
format="MM/dd/yyyy"
margin="normal"
name="birthday"
value={birthday}
onChange={handleChangeValue}
/>
</MuiPickersUtilsProvider>
<Controller
control={control}
onChange={([selected]) => selected}
name="birthday"
render={({ onChange, value }) => (
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<DatePicker
disableFuture
fullWidth
openTo="year"
format="dd/MM/yyyy"
label="Date of birth"
views={["year", "month", "date"]}
onChange={onChange}
value={value}
/>
</MuiPickersUtilsProvider>
)}
/>
</Grid>
<Grid item xs={12}>
<TextField
required
variant="outlined"
label="Height"
type="number"
<Controller
control={control}
name="height"
onChange={handleChangeValue}
value={height}
fullWidth
InputProps={{
endAdornment: <InputAdornment position="end">cm</InputAdornment>
}}
as={
<TextField
type="number"
label="Height"
variant="outlined"
fullWidth
InputProps={{
endAdornment: <InputAdornment position="end">cm</InputAdornment>
}}
/>
}
/>
</Grid>
<Grid item xs={12}>
<TextField
required
variant="outlined"
label="Weight"
type="number"
name="weight"
onChange={handleChangeValue}
value={weight}
fullWidth
InputProps={{
endAdornment: <InputAdornment position="end">Kg</InputAdornment>
}}
<Controller
control={control}
name="weight.current"
as={
<TextField
type="number"
label="Current Weight"
variant="outlined"
fullWidth
InputProps={{
endAdornment: <InputAdornment position="end">Kg</InputAdornment>
}}
/>
}
/>
</Grid>
<Grid item xs={12}>
<Typography gutterBottom>
Activity
</Typography>
<Box mx={4}>
<Slider
name="activity"
onChange={handleChangeValue}
value={activity}
min={0}
max={4}
marks={activities.map(({ name, factor, id }) => ({
name,
value: factor
}))}
/>
</Box>
<Controller
control={control}
name="weight.goal"
as={
<TextField
type="number"
label="Goal Weight"
variant="outlined"
fullWidth
InputProps={{
endAdornment: <InputAdornment position="end">Kg</InputAdornment>
}}
/>
}
/>
</Grid>
</Grid>
</React.Fragment>

View File

@ -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,
})

View File

@ -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';

View File

@ -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 <GoalForm />;
return <GoalForm/>;
case 1:
return <PersonalDetailsForm />;
return <PersonalDetailsForm/>;
case 2:
return <ReviewProfileForm />;
return <ReviewProfileForm/>;
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 = () => {
</Typography>
</React.Fragment>
) : (
<form onSubmit={handleSubmitProfile}>
{getStepContent(activeStep)}
<div className={classes.buttons}>
{activeStep !== 0 && (
<Button onClick={handleBack} className={classes.button}>
Back
</Button>
)}
<Button
variant="contained"
color="primary"
onClick={handleNext}
type={activeStep === steps.length - 1 ? 'submit' : 'button'}
className={classes.button}
>
{activeStep === steps.length - 1 ? 'Save profile' : 'Next'}
</Button>
</div>
</form>
<FormProvider {...methods}>
<form onSubmit={methods.handleSubmit(handleSubmitProfile)}>
{getStepContent(activeStep)}
<div className={classes.buttons}>
{activeStep !== 0 && (
<Button onClick={handleBack} className={classes.button}>
back
</Button>
)}
<Button
variant="contained"
color="primary"
onClick={handleNext}
type={activeStep === steps.length - 1 ? 'submit' : 'button'}
type="submit"
className={classes.button}
>
{activeStep === steps.length - 1 ? 'Save profile' : 'Next'}
</Button>
</div>
</form>
</FormProvider>
)}
</React.Fragment>
</Paper>

View File

@ -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;

View File

@ -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);
}

View File

@ -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
};

View File

@ -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

View File

@ -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"