react form hooks
This commit is contained in:
parent
6c807dcc30
commit
803bd65a87
@ -13,14 +13,17 @@
|
|||||||
"@testing-library/user-event": "^12.1.10",
|
"@testing-library/user-event": "^12.1.10",
|
||||||
"connected-react-router": "^6.8.0",
|
"connected-react-router": "^6.8.0",
|
||||||
"date-fns": "^2.16.1",
|
"date-fns": "^2.16.1",
|
||||||
|
"formik": "^2.2.6",
|
||||||
"history": "4.10.1",
|
"history": "4.10.1",
|
||||||
"immer": "^8.0.0",
|
"immer": "^8.0.0",
|
||||||
|
"joi": "^17.3.0",
|
||||||
"lodash": "^4.17.20",
|
"lodash": "^4.17.20",
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
"quagga": "^0.12.1",
|
"quagga": "^0.12.1",
|
||||||
"react": "^17.0.1",
|
"react": "^17.0.1",
|
||||||
"react-dom": "^17.0.1",
|
"react-dom": "^17.0.1",
|
||||||
"react-helmet": "^6.1.0",
|
"react-helmet": "^6.1.0",
|
||||||
|
"react-hook-form": "^6.13.1",
|
||||||
"react-redux": "^7.2.2",
|
"react-redux": "^7.2.2",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scripts": "4.0.0",
|
"react-scripts": "4.0.0",
|
||||||
|
@ -1,62 +1,103 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React from 'react';
|
||||||
import { Grid, Button, Typography, Radio, RadioGroup } from '@material-ui/core';
|
import {Grid, FormControlLabel, Slider, Button, Typography, Radio, RadioGroup, Box} from '@material-ui/core';
|
||||||
import {useInjectReducer, useInjectSaga} from "redux-injectors";
|
import {useInjectReducer} from "redux-injectors";
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import {createStructuredSelector} from "reselect";
|
import {createStructuredSelector} from "reselect";
|
||||||
|
import { useFormContext, Controller } from "react-hook-form";
|
||||||
import reducer from "pages/Profile/reducer";
|
import reducer from "pages/Profile/reducer";
|
||||||
import saga from "pages/Profile/saga";
|
|
||||||
import { profileInputChange, getGoalsAction } from 'pages/Profile/actions'
|
|
||||||
import {
|
import {
|
||||||
makeSelectError,
|
|
||||||
makeSelectIsLoading,
|
|
||||||
makeSelectGoals,
|
makeSelectGoals,
|
||||||
|
makeSelectActivities,
|
||||||
|
makeSelectRatesOfChange,
|
||||||
} from "pages/Profile/selectors";
|
} from "pages/Profile/selectors";
|
||||||
import Loader from './Loader'
|
|
||||||
|
|
||||||
const stateSelector = createStructuredSelector({
|
const stateSelector = createStructuredSelector({
|
||||||
isLoading: makeSelectIsLoading(),
|
|
||||||
error: makeSelectError(),
|
|
||||||
goals: makeSelectGoals(),
|
goals: makeSelectGoals(),
|
||||||
|
activities: makeSelectActivities(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const key = 'profilePage'
|
const key = 'profilePage'
|
||||||
const GoalForm = () => {
|
const GoalForm = () => {
|
||||||
useInjectReducer({ key, reducer });
|
useInjectReducer({ key, reducer });
|
||||||
useInjectSaga({ key, saga });
|
const { goals, activities, ratesOfChange } = useSelector(stateSelector)
|
||||||
const dispatch = useDispatch()
|
const { control } = useFormContext()
|
||||||
const { goals, error, isLoading } = useSelector(stateSelector)
|
|
||||||
|
|
||||||
const handleChangeGoal = ({ target: { name, value }}) => {
|
|
||||||
dispatch(profileInputChange({ name, value }))
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
dispatch(getGoalsAction())
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Typography variant="h6" gutterBottom>
|
<Typography variant="h6" gutterBottom>
|
||||||
Your goal
|
Goal
|
||||||
</Typography>
|
</Typography>
|
||||||
<RadioGroup defaultValue={1} onChange={handleChangeGoal}>
|
<Grid>
|
||||||
<Grid container spacing={3} direction="column">
|
<Grid>
|
||||||
{isLoading ? (
|
<Controller
|
||||||
<Loader />
|
name="goal"
|
||||||
) : (
|
control={control}
|
||||||
<React.Fragment>
|
as={
|
||||||
{goals.map(({ name, value }, index) => (
|
<RadioGroup aria-label="Your goal">
|
||||||
<Grid item xs={12} key={index}>
|
<Grid container spacing={2} >
|
||||||
<Button variant="text" fullWidth>
|
{goals.map(({ label, value }) => (
|
||||||
{name}
|
<Grid item xs={4} key={value}>
|
||||||
<Radio color="secondary" name="goal" value={value} />
|
<Button variant="text" fullWidth>
|
||||||
</Button>
|
<FormControlLabel
|
||||||
</Grid>
|
key={value}
|
||||||
))}
|
value={value.toString()}
|
||||||
</React.Fragment>
|
control={<Radio />}
|
||||||
)}
|
label={label}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</RadioGroup>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</Grid>
|
</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>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,56 +1,32 @@
|
|||||||
import 'date-fns';
|
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 {Typography, InputLabel, Box, Grid, InputAdornment, Select, FormControl, MenuItem, TextField, Slider} from '@material-ui/core';
|
||||||
import DateFnsUtils from '@date-io/date-fns';
|
import DateFnsUtils from '@date-io/date-fns';
|
||||||
|
import { useFormContext, Controller } from "react-hook-form";
|
||||||
import {
|
import {
|
||||||
MuiPickersUtilsProvider,
|
MuiPickersUtilsProvider,
|
||||||
KeyboardDatePicker,
|
DatePicker,
|
||||||
} from '@material-ui/pickers';
|
} from '@material-ui/pickers';
|
||||||
import {useInjectReducer, useInjectSaga} from "redux-injectors";
|
import {useInjectReducer} from "redux-injectors";
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import {createStructuredSelector} from "reselect";
|
import {createStructuredSelector} from "reselect";
|
||||||
import reducer from "pages/Profile/reducer";
|
import reducer from "pages/Profile/reducer";
|
||||||
import saga from "pages/Profile/saga";
|
|
||||||
import { profileInputChange, getActivitiesAction, getGendersAction } from 'pages/Profile/actions'
|
|
||||||
import {
|
import {
|
||||||
makeSelectError,
|
|
||||||
makeSelectIsLoading,
|
|
||||||
makeSelectActivities,
|
makeSelectActivities,
|
||||||
makeSelectGenders,
|
makeSelectGenders,
|
||||||
makeSelectWeight,
|
|
||||||
makeSelectHeight,
|
|
||||||
makeSelectBirthday,
|
|
||||||
makeSelectActivity,
|
|
||||||
makeSelectGender,
|
|
||||||
} from "pages/Profile/selectors";
|
} from "pages/Profile/selectors";
|
||||||
|
|
||||||
const stateSelector = createStructuredSelector({
|
const stateSelector = createStructuredSelector({
|
||||||
isLoading: makeSelectIsLoading(),
|
|
||||||
error: makeSelectError(),
|
|
||||||
activities: makeSelectActivities(),
|
activities: makeSelectActivities(),
|
||||||
genders: makeSelectGenders(),
|
genders: makeSelectGenders(),
|
||||||
weight: makeSelectWeight(),
|
|
||||||
height: makeSelectHeight(),
|
|
||||||
birthday: makeSelectBirthday(),
|
|
||||||
activity: makeSelectActivity(),
|
|
||||||
gender: makeSelectGender(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const key = 'profilePage'
|
const key = 'profilePage'
|
||||||
const PersonalDetailsForm = () => {
|
const PersonalDetailsForm = () => {
|
||||||
useInjectReducer({ key, reducer });
|
useInjectReducer({ key, reducer });
|
||||||
useInjectSaga({ key, saga });
|
const { activities, genders } = useSelector(stateSelector)
|
||||||
const dispatch = useDispatch()
|
const { register, control } = useFormContext()
|
||||||
const { gender, activity, birthday, height, weight, activities, genders, error, isLoading } = useSelector(stateSelector)
|
|
||||||
|
|
||||||
const handleChangeValue = ({ target: { name, value }}) => {
|
|
||||||
dispatch(profileInputChange({ name, value }))
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
dispatch(getActivitiesAction())
|
|
||||||
dispatch(getGendersAction())
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
@ -61,79 +37,93 @@ const PersonalDetailsForm = () => {
|
|||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<FormControl variant="outlined" fullWidth>
|
<FormControl variant="outlined" fullWidth>
|
||||||
<InputLabel>Gender</InputLabel>
|
<InputLabel>Gender</InputLabel>
|
||||||
<Select
|
<Controller
|
||||||
|
control={control}
|
||||||
name="gender"
|
name="gender"
|
||||||
label="Gender"
|
as={
|
||||||
onChange={handleChangeValue}
|
<Select
|
||||||
value={gender}
|
label="Gender"
|
||||||
>
|
name="gender"
|
||||||
{genders.map(({ id, name }) => (
|
>
|
||||||
<MenuItem value={id} key={id}>{name}</MenuItem>
|
{genders.map(label => (
|
||||||
))}
|
<MenuItem value={label} key={label}>{label}</MenuItem>
|
||||||
</Select>
|
))}
|
||||||
|
</Select>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<MuiPickersUtilsProvider utils={DateFnsUtils}>
|
<Controller
|
||||||
<KeyboardDatePicker
|
control={control}
|
||||||
disableToolbar
|
onChange={([selected]) => selected}
|
||||||
inputVariant="outlined"
|
name="birthday"
|
||||||
fullWidth
|
render={({ onChange, value }) => (
|
||||||
format="MM/dd/yyyy"
|
<MuiPickersUtilsProvider utils={DateFnsUtils}>
|
||||||
margin="normal"
|
<DatePicker
|
||||||
name="birthday"
|
disableFuture
|
||||||
value={birthday}
|
fullWidth
|
||||||
onChange={handleChangeValue}
|
openTo="year"
|
||||||
/>
|
format="dd/MM/yyyy"
|
||||||
</MuiPickersUtilsProvider>
|
label="Date of birth"
|
||||||
|
views={["year", "month", "date"]}
|
||||||
|
onChange={onChange}
|
||||||
|
value={value}
|
||||||
|
/>
|
||||||
|
</MuiPickersUtilsProvider>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<TextField
|
<Controller
|
||||||
required
|
control={control}
|
||||||
variant="outlined"
|
|
||||||
label="Height"
|
|
||||||
type="number"
|
|
||||||
name="height"
|
name="height"
|
||||||
onChange={handleChangeValue}
|
as={
|
||||||
value={height}
|
<TextField
|
||||||
fullWidth
|
type="number"
|
||||||
InputProps={{
|
label="Height"
|
||||||
endAdornment: <InputAdornment position="end">cm</InputAdornment>
|
variant="outlined"
|
||||||
}}
|
fullWidth
|
||||||
|
InputProps={{
|
||||||
|
endAdornment: <InputAdornment position="end">cm</InputAdornment>
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<TextField
|
<Controller
|
||||||
required
|
control={control}
|
||||||
variant="outlined"
|
name="weight.current"
|
||||||
label="Weight"
|
as={
|
||||||
type="number"
|
<TextField
|
||||||
name="weight"
|
type="number"
|
||||||
onChange={handleChangeValue}
|
label="Current Weight"
|
||||||
value={weight}
|
variant="outlined"
|
||||||
fullWidth
|
fullWidth
|
||||||
InputProps={{
|
InputProps={{
|
||||||
endAdornment: <InputAdornment position="end">Kg</InputAdornment>
|
endAdornment: <InputAdornment position="end">Kg</InputAdornment>
|
||||||
}}
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<Typography gutterBottom>
|
<Controller
|
||||||
Activity
|
control={control}
|
||||||
</Typography>
|
name="weight.goal"
|
||||||
<Box mx={4}>
|
as={
|
||||||
<Slider
|
<TextField
|
||||||
name="activity"
|
type="number"
|
||||||
onChange={handleChangeValue}
|
label="Goal Weight"
|
||||||
value={activity}
|
variant="outlined"
|
||||||
min={0}
|
fullWidth
|
||||||
max={4}
|
InputProps={{
|
||||||
marks={activities.map(({ name, factor, id }) => ({
|
endAdornment: <InputAdornment position="end">Kg</InputAdornment>
|
||||||
name,
|
}}
|
||||||
value: factor
|
/>
|
||||||
}))}
|
}
|
||||||
/>
|
/>
|
||||||
</Box>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
@ -1,13 +1,4 @@
|
|||||||
import {
|
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,
|
PROFILE_INPUT_CHANGE,
|
||||||
GET_PROFILE_REQUEST,
|
GET_PROFILE_REQUEST,
|
||||||
GET_PROFILE_SUCCESS,
|
GET_PROFILE_SUCCESS,
|
||||||
@ -43,15 +34,15 @@ export const getProfileErrorAction = ({error}) => ({
|
|||||||
error,
|
error,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
export const updateProfileAction = () => ({
|
export const updateProfileAction = () => ({
|
||||||
type: UPDATE_PROFILE_REQUEST,
|
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,
|
type: UPDATE_PROFILE_SUCCESS,
|
||||||
birthday,
|
birthday,
|
||||||
gender,
|
gender,
|
||||||
|
goal,
|
||||||
height,
|
height,
|
||||||
weight,
|
weight,
|
||||||
goalWeight,
|
goalWeight,
|
||||||
@ -64,45 +55,3 @@ export const updateProfileErrorAction = ({error}) => ({
|
|||||||
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,
|
|
||||||
})
|
|
||||||
|
|
||||||
|
@ -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_SUCCESS = 'app/ProfilePage/UPDATE_PROFILE_SUCCESS';
|
||||||
export const UPDATE_PROFILE_ERROR = 'app/ProfilePage/UPDATE_PROFILE_ERROR';
|
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';
|
export const PROFILE_INPUT_CHANGE = 'app/ProfilePage/PROFILE_INPUT_CHANGE';
|
||||||
|
@ -3,6 +3,7 @@ import { makeStyles } from '@material-ui/core/styles';
|
|||||||
import {Paper, Stepper, Step, StepLabel, Button, Typography } from '@material-ui/core';
|
import {Paper, Stepper, Step, StepLabel, Button, Typography } from '@material-ui/core';
|
||||||
import {useInjectReducer, useInjectSaga} from "redux-injectors";
|
import {useInjectReducer, useInjectSaga} from "redux-injectors";
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { useForm, useFormContext, FormProvider } from "react-hook-form";
|
||||||
import GoalForm from 'components/GoalForm';
|
import GoalForm from 'components/GoalForm';
|
||||||
import PersonalDetailsForm from 'components/PersonalDetailsForm';
|
import PersonalDetailsForm from 'components/PersonalDetailsForm';
|
||||||
import ReviewProfileForm from 'components/ReviewProfileForm';
|
import ReviewProfileForm from 'components/ReviewProfileForm';
|
||||||
@ -49,11 +50,11 @@ const steps = ['Your goal', 'Personal details', 'Review your profile'];
|
|||||||
const getStepContent = (step) => {
|
const getStepContent = (step) => {
|
||||||
switch (step) {
|
switch (step) {
|
||||||
case 0:
|
case 0:
|
||||||
return <GoalForm />;
|
return <GoalForm/>;
|
||||||
case 1:
|
case 1:
|
||||||
return <PersonalDetailsForm />;
|
return <PersonalDetailsForm/>;
|
||||||
case 2:
|
case 2:
|
||||||
return <ReviewProfileForm />;
|
return <ReviewProfileForm/>;
|
||||||
default:
|
default:
|
||||||
throw new Error('Unknown step');
|
throw new Error('Unknown step');
|
||||||
}
|
}
|
||||||
@ -63,6 +64,20 @@ const key = 'profilePage'
|
|||||||
const ProfilePage = () => {
|
const ProfilePage = () => {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const [activeStep, setActiveStep] = useState(0);
|
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 });
|
useInjectReducer({ key, reducer });
|
||||||
useInjectSaga({ key, saga });
|
useInjectSaga({ key, saga });
|
||||||
@ -77,9 +92,8 @@ const ProfilePage = () => {
|
|||||||
setActiveStep(activeStep - 1);
|
setActiveStep(activeStep - 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmitProfile = (event) => {
|
const handleSubmitProfile = data => {
|
||||||
event.preventDefault();
|
console.log('data', data)
|
||||||
dispatch(updateProfileAction())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -107,25 +121,28 @@ const ProfilePage = () => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
) : (
|
) : (
|
||||||
<form onSubmit={handleSubmitProfile}>
|
<FormProvider {...methods}>
|
||||||
{getStepContent(activeStep)}
|
<form onSubmit={methods.handleSubmit(handleSubmitProfile)}>
|
||||||
<div className={classes.buttons}>
|
{getStepContent(activeStep)}
|
||||||
{activeStep !== 0 && (
|
<div className={classes.buttons}>
|
||||||
<Button onClick={handleBack} className={classes.button}>
|
{activeStep !== 0 && (
|
||||||
Back
|
<Button onClick={handleBack} className={classes.button}>
|
||||||
</Button>
|
back
|
||||||
)}
|
</Button>
|
||||||
<Button
|
)}
|
||||||
variant="contained"
|
<Button
|
||||||
color="primary"
|
variant="contained"
|
||||||
onClick={handleNext}
|
color="primary"
|
||||||
type={activeStep === steps.length - 1 ? 'submit' : 'button'}
|
onClick={handleNext}
|
||||||
className={classes.button}
|
type={activeStep === steps.length - 1 ? 'submit' : 'button'}
|
||||||
>
|
type="submit"
|
||||||
{activeStep === steps.length - 1 ? 'Save profile' : 'Next'}
|
className={classes.button}
|
||||||
</Button>
|
>
|
||||||
</div>
|
{activeStep === steps.length - 1 ? 'Save profile' : 'Next'}
|
||||||
</form>
|
</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</FormProvider>
|
||||||
)}
|
)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
@ -1,14 +1,5 @@
|
|||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
import {
|
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,
|
PROFILE_INPUT_CHANGE,
|
||||||
GET_PROFILE_REQUEST,
|
GET_PROFILE_REQUEST,
|
||||||
GET_PROFILE_SUCCESS,
|
GET_PROFILE_SUCCESS,
|
||||||
@ -19,61 +10,78 @@ import {
|
|||||||
} from './constants';
|
} from './constants';
|
||||||
|
|
||||||
export const initialState = {
|
export const initialState = {
|
||||||
activities: [],
|
activities: [
|
||||||
goals: [],
|
{
|
||||||
genders: [],
|
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,
|
isLoading: false,
|
||||||
error: {},
|
error: {},
|
||||||
gender: '',
|
gender: '',
|
||||||
|
goal: 0,
|
||||||
birthday: new Date(),
|
birthday: new Date(),
|
||||||
height: 0,
|
height: 0,
|
||||||
weight: 0,
|
weight: {
|
||||||
goalWeight: 0,
|
current: 0,
|
||||||
|
goal: 0,
|
||||||
|
},
|
||||||
rateOfChange: 0,
|
rateOfChange: 0,
|
||||||
activity: 0,
|
activity: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const loginPageReducer = produce((draft, action) => {
|
const loginPageReducer = produce((draft, action) => {
|
||||||
switch(action.type) {
|
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 GET_PROFILE_SUCCESS:
|
||||||
case UPDATE_PROFILE_SUCCESS:
|
case UPDATE_PROFILE_SUCCESS:
|
||||||
draft.birthday = action.birthday;
|
draft.birthday = action.birthday;
|
||||||
draft.gender = action.gender;
|
draft.gender = action.gender;
|
||||||
|
draft.goal = action.goal;
|
||||||
draft.height = action.height;
|
draft.height = action.height;
|
||||||
draft.weight = action.weight;
|
draft.weight.current = action.weight.current;
|
||||||
draft.goalWeight = action.goalWeight;
|
draft.weight.goal = action.weight.goal;
|
||||||
draft.rateOfChange = action.rateOfChange;
|
draft.rateOfChange = action.rateOfChange;
|
||||||
draft.activity = action.activity;
|
draft.activity = action.activity;
|
||||||
draft.isLoading = false;
|
draft.isLoading = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GET_ACTIVITIES_REQUEST:
|
|
||||||
case GET_GENDERS_REQUEST:
|
|
||||||
case GET_PROFILE_REQUEST:
|
case GET_PROFILE_REQUEST:
|
||||||
case GET_GOALS_REQUEST:
|
|
||||||
case UPDATE_PROFILE_REQUEST:
|
case UPDATE_PROFILE_REQUEST:
|
||||||
draft.isLoading = true;
|
draft.isLoading = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GET_ACTIVITIES_ERROR:
|
|
||||||
case GET_GENDERS_ERROR:
|
|
||||||
case GET_PROFILE_ERROR:
|
case GET_PROFILE_ERROR:
|
||||||
case GET_GOALS_ERROR:
|
|
||||||
case UPDATE_PROFILE_ERROR:
|
case UPDATE_PROFILE_ERROR:
|
||||||
draft.isLoading = false;
|
draft.isLoading = false;
|
||||||
draft.error = action.error;
|
draft.error = action.error;
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import { takeLatest, call, put, select } from 'redux-saga/effects';
|
import { takeLatest, call, put, select } from 'redux-saga/effects';
|
||||||
import { api, request } from 'utils';
|
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 {
|
import {
|
||||||
makeSelectBirthday,
|
makeSelectBirthday,
|
||||||
makeSelectHeight,
|
makeSelectHeight,
|
||||||
makeSelectWeight,
|
makeSelectWeight,
|
||||||
makeSelectRateOfChange,
|
makeSelectRateOfChange,
|
||||||
makeSelectActivity,
|
makeSelectActivity,
|
||||||
makeSelectGoalWeight,
|
makeSelectGoal,
|
||||||
makeSelectGender
|
makeSelectGender
|
||||||
} from './selectors';
|
} 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'
|
import { makeSelectTokens } from 'containers/App/selectors'
|
||||||
|
|
||||||
@ -37,11 +37,11 @@ export function* getProfile() {
|
|||||||
export function* updateProfile() {
|
export function* updateProfile() {
|
||||||
const { access } = yield select(makeSelectTokens());
|
const { access } = yield select(makeSelectTokens());
|
||||||
|
|
||||||
const birthday = yield select(makeSelectBirthday());
|
|
||||||
const gender = yield select(makeSelectGender());
|
const gender = yield select(makeSelectGender());
|
||||||
|
const goal = yield select(makeSelectGoal());
|
||||||
|
const birthday = yield select(makeSelectBirthday());
|
||||||
const height = yield select(makeSelectHeight());
|
const height = yield select(makeSelectHeight());
|
||||||
const weight = yield select(makeSelectWeight());
|
const weight = yield select(makeSelectWeight());
|
||||||
const goalWeight = yield select(makeSelectGoalWeight());
|
|
||||||
const rateOfChange = yield select(makeSelectRateOfChange());
|
const rateOfChange = yield select(makeSelectRateOfChange());
|
||||||
const activity = yield select(makeSelectActivity());
|
const activity = yield select(makeSelectActivity());
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ export function* updateProfile() {
|
|||||||
const requestParameters = {
|
const requestParameters = {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { Accept: 'application/json', 'Content-Type': 'application/json', Authorization: `Bearer ${access.token}`, },
|
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 {
|
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() {
|
export default function* profilePageSaga() {
|
||||||
yield takeLatest(GET_PROFILE_REQUEST, getProfile);
|
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);
|
yield takeLatest(UPDATE_PROFILE_REQUEST, updateProfile);
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@ const makeSelectRateOfChange = () =>
|
|||||||
const makeSelectActivity = () =>
|
const makeSelectActivity = () =>
|
||||||
createSelector(selectProfilePageDomain, (substate) => substate.activity);
|
createSelector(selectProfilePageDomain, (substate) => substate.activity);
|
||||||
|
|
||||||
const makeSelectGoalWeight = () =>
|
const makeSelectGoal = () =>
|
||||||
createSelector(selectProfilePageDomain, (substate) => substate.goalWeight);
|
createSelector(selectProfilePageDomain, (substate) => substate.goal);
|
||||||
|
|
||||||
const makeSelectGender = () =>
|
const makeSelectGender = () =>
|
||||||
createSelector(selectProfilePageDomain, (substate) => substate.gender);
|
createSelector(selectProfilePageDomain, (substate) => substate.gender);
|
||||||
@ -39,6 +39,10 @@ const makeSelectActivities = () =>
|
|||||||
const makeSelectGenders = () =>
|
const makeSelectGenders = () =>
|
||||||
createSelector(selectProfilePageDomain, (substate) => substate.genders);
|
createSelector(selectProfilePageDomain, (substate) => substate.genders);
|
||||||
|
|
||||||
|
const makeSelectRatesOfChange = () =>
|
||||||
|
createSelector(selectProfilePageDomain, (substate) => substate.ratesOfChange);
|
||||||
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
selectProfilePageDomain,
|
selectProfilePageDomain,
|
||||||
makeSelectError,
|
makeSelectError,
|
||||||
@ -47,10 +51,11 @@ export {
|
|||||||
makeSelectWeight,
|
makeSelectWeight,
|
||||||
makeSelectRateOfChange,
|
makeSelectRateOfChange,
|
||||||
makeSelectActivity,
|
makeSelectActivity,
|
||||||
makeSelectGoalWeight,
|
makeSelectGoal,
|
||||||
makeSelectGender,
|
makeSelectGender,
|
||||||
makeSelectIsLoading,
|
makeSelectIsLoading,
|
||||||
makeSelectGoals,
|
makeSelectGoals,
|
||||||
makeSelectActivities,
|
makeSelectActivities,
|
||||||
makeSelectGenders,
|
makeSelectGenders,
|
||||||
|
makeSelectRatesOfChange
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
const API_BASE_URL = 'http://localhost:3001/v1'
|
const API_BASE_URL = 'http://localhost:3001/v1'
|
||||||
const AUTH = 'auth';
|
const AUTH = 'auth';
|
||||||
const PROFILE = 'profiles';
|
const PROFILE = 'profiles';
|
||||||
const ACTIVITY = 'activities';
|
|
||||||
const GENDER = 'genders';
|
|
||||||
const GOALS = 'goals';
|
|
||||||
|
|
||||||
const urls = {
|
const urls = {
|
||||||
auth: {
|
auth: {
|
||||||
@ -11,9 +8,6 @@ const urls = {
|
|||||||
register: `${API_BASE_URL}/${AUTH}/register`,
|
register: `${API_BASE_URL}/${AUTH}/register`,
|
||||||
},
|
},
|
||||||
profile: `${API_BASE_URL}/${PROFILE}`,
|
profile: `${API_BASE_URL}/${PROFILE}`,
|
||||||
activities: `${API_BASE_URL}/${ACTIVITY}`,
|
|
||||||
genders: `${API_BASE_URL}/${GENDER}`,
|
|
||||||
goals: `${API_BASE_URL}/${GOALS}`,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default urls
|
export default urls
|
||||||
|
75
yarn.lock
75
yarn.lock
@ -1081,6 +1081,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.5.1.tgz#fde96064ca446dec8c55a8c2f130957b070c6e06"
|
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.5.1.tgz#fde96064ca446dec8c55a8c2f130957b070c6e06"
|
||||||
integrity sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow==
|
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":
|
"@hapi/joi@^15.1.0":
|
||||||
version "15.1.1"
|
version "15.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.1.1.tgz#c675b8a71296f02833f8d6d243b34c57b8ce19d7"
|
resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.1.1.tgz#c675b8a71296f02833f8d6d243b34c57b8ce19d7"
|
||||||
@ -1098,6 +1103,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@hapi/hoek" "^8.3.0"
|
"@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":
|
"@istanbuljs/load-nyc-config@^1.0.0":
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
|
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"
|
estree-walker "^1.0.1"
|
||||||
picomatch "^2.2.2"
|
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":
|
"@sinonjs/commons@^1.7.0":
|
||||||
version "1.8.1"
|
version "1.8.1"
|
||||||
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217"
|
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"
|
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
|
||||||
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
|
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:
|
deepmerge@^4.2.2:
|
||||||
version "4.2.2"
|
version "4.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
|
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"
|
combined-stream "^1.0.6"
|
||||||
mime-types "^2.1.12"
|
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:
|
forwarded@~0.1.2:
|
||||||
version "0.1.2"
|
version "0.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
|
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-assert "^1.0.0"
|
||||||
minimalistic-crypto-utils "^1.0.1"
|
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"
|
version "3.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
||||||
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
|
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
|
||||||
@ -6869,6 +6916,17 @@ jest@26.6.0:
|
|||||||
import-local "^3.0.2"
|
import-local "^3.0.2"
|
||||||
jest-cli "^26.6.0"
|
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:
|
jpeg-js@^0.3.2:
|
||||||
version "0.3.7"
|
version "0.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.3.7.tgz#471a89d06011640592d314158608690172b1028d"
|
resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.3.7.tgz#471a89d06011640592d314158608690172b1028d"
|
||||||
@ -7266,6 +7324,11 @@ locate-path@^5.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
p-locate "^4.1.0"
|
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:
|
lodash._reinterpolate@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
|
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"
|
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.8.tgz#474ed11d04fc6bda3af643447d85e9127ed6b5de"
|
||||||
integrity sha512-HvPuUQnLp5H7TouGq3kzBeioJmXms1wHy9EGjz2OURWBp4qZO6AfGEcnxts1D/CbwPLRAgTMPCEgYhA3sEM4vw==
|
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:
|
react-fast-compare@^3.1.1:
|
||||||
version "3.2.0"
|
version "3.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb"
|
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-fast-compare "^3.1.1"
|
||||||
react-side-effect "^2.1.0"
|
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:
|
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"
|
version "16.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||||
|
Loading…
Reference in New Issue
Block a user