Add create profile secion

This commit is contained in:
= 2020-12-09 18:06:05 +01:00
parent 156b78ca39
commit 6c807dcc30
14 changed files with 192 additions and 37 deletions

View File

@ -4,7 +4,7 @@ import {Skeleton} from "@material-ui/lab";
const Loader = () => { const Loader = () => {
return ( return (
<React.Element> <div>
<Grid item xs={12}> <Grid item xs={12}>
<Button variant="text" fullWidth> <Button variant="text" fullWidth>
<Skeleton /> <Skeleton />
@ -20,7 +20,7 @@ const Loader = () => {
<Skeleton /> <Skeleton />
</Button> </Button>
</Grid> </Grid>
</React.Element> </div>
); );
}; };

View File

@ -37,7 +37,7 @@ const GoalForm = () => {
return ( return (
<React.Fragment> <React.Fragment>
<Typography variant="h6" gutterBottom> <Typography variant="h6" gutterBottom>
Your goal { JSON.stringify(error) } Your goal
</Typography> </Typography>
<RadioGroup defaultValue={1} onChange={handleChangeGoal}> <RadioGroup defaultValue={1} onChange={handleChangeGoal}>
<Grid container spacing={3} direction="column"> <Grid container spacing={3} direction="column">
@ -45,10 +45,10 @@ const GoalForm = () => {
<Loader /> <Loader />
) : ( ) : (
<React.Fragment> <React.Fragment>
{goals.map(({ label, value }, index) => ( {goals.map(({ name, value }, index) => (
<Grid item xs={12} key={index}> <Grid item xs={12} key={index}>
<Button variant="text" fullWidth> <Button variant="text" fullWidth>
{label} {name}
<Radio color="secondary" name="goal" value={value} /> <Radio color="secondary" name="goal" value={value} />
</Button> </Button>
</Grid> </Grid>

View File

@ -67,8 +67,8 @@ const PersonalDetailsForm = () => {
onChange={handleChangeValue} onChange={handleChangeValue}
value={gender} value={gender}
> >
{genders.map(({ label, value }) => ( {genders.map(({ id, name }) => (
<MenuItem value={value}>{label}</MenuItem> <MenuItem value={id} key={id}>{name}</MenuItem>
))} ))}
</Select> </Select>
</FormControl> </FormControl>
@ -128,7 +128,10 @@ const PersonalDetailsForm = () => {
value={activity} value={activity}
min={0} min={0}
max={4} max={4}
marks={activities} marks={activities.map(({ name, factor, id }) => ({
name,
value: factor
}))}
/> />
</Box> </Box>
</Grid> </Grid>

View File

@ -5,15 +5,31 @@ import {
} from './constants'; } from './constants';
import { LOGIN_SUCCESS } from 'pages/Login/constants' import { LOGIN_SUCCESS } from 'pages/Login/constants'
import { REGISTER_SUCCESS } from 'pages/Register/constants'
export const initialState = { export const initialState = {
isLogged: false, isLogged: true,
notifications: [], notifications: [],
tokens: {}, tokens: {
user: {}, access: {
}; token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1ZmQxMDExNGM3NDQ0MTJlZDQ3Y2IzZDEiLCJpYXQiOjE2MDc1MzI4MzUsImV4cCI6MTYwNzUzNDYzNSwidHlwZSI6ImFjY2VzcyJ9.S19wRggAiJYYK35dFWM_gIWuf5ULajJ2cOaA2V2vwtY',
expires: '2020-12-09T17:23:55.763Z'
},
refresh: {
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1ZmQxMDExNGM3NDQ0MTJlZDQ3Y2IzZDEiLCJpYXQiOjE2MDc1MzI4MzUsImV4cCI6MTYxMDEyNDgzNSwidHlwZSI6InJlZnJlc2gifQ.NC6BJUDKR3WBUVxo62Swytx4nkc6QtUQ7oYdJHqgDY0',
expires: '2021-01-08T16:53:55.763Z'
}
},
user: {
role: 'admin',
email: 'admin@admin.com',
id: '5fd10114c744412ed47cb3d1'
}
}
const appReducer = produce((draft, action) => { const appReducer = produce((draft, action) => {
switch(action.type) { switch(action.type) {
case REGISTER_SUCCESS:
case LOGIN_SUCCESS: case LOGIN_SUCCESS:
draft.isLogged = true; draft.isLogged = true;
draft.tokens = action.tokens; draft.tokens = action.tokens;

View File

@ -11,13 +11,13 @@ const initialState = {};
const store = configureStore(initialState, history); const store = configureStore(initialState, history);
ReactDOM.render( ReactDOM.render(
<React.StrictMode> // <React.StrictMode>
<Provider store={store}> <Provider store={store}>
<ConnectedRouter history={history}> <ConnectedRouter history={history}>
<App /> <App />
</ConnectedRouter> </ConnectedRouter>
</Provider> </Provider>,
</React.StrictMode>, // </React.StrictMode>,
document.getElementById('root') document.getElementById('root')
); );

View File

@ -21,12 +21,6 @@ import { loginInputChange, loginAction } from './actions'
import {routes} from "../../utils"; import {routes} from "../../utils";
import {makeStyles} from "@material-ui/core/styles"; import {makeStyles} from "@material-ui/core/styles";
const stateSelector = createStructuredSelector({
email: makeSelectEmail(),
password: makeSelectPassword(),
loading: makeSelectLoading(),
});
const useStyles = makeStyles((theme) => ({ const useStyles = makeStyles((theme) => ({
paper: { paper: {
marginTop: theme.spacing(8), marginTop: theme.spacing(8),
@ -43,6 +37,12 @@ const useStyles = makeStyles((theme) => ({
}, },
})); }));
const stateSelector = createStructuredSelector({
email: makeSelectEmail(),
password: makeSelectPassword(),
loading: makeSelectLoading(),
});
const key = 'loginPage' const key = 'loginPage'
const Login = () => { const Login = () => {
const classes = useStyles() const classes = useStyles()

View File

@ -2,7 +2,7 @@ import produce from 'immer';
import {LOGIN_INPUT_CHANGE, LOGIN_ERROR, LOGIN_REQUEST, LOGIN_SUCCESS} from './constants'; import {LOGIN_INPUT_CHANGE, LOGIN_ERROR, LOGIN_REQUEST, LOGIN_SUCCESS} from './constants';
export const initialState = { export const initialState = {
loading: false, isLoading: false,
error: {}, error: {},
email: 'admin@admin.com', email: 'admin@admin.com',
password: 'Kox32113@#$', password: 'Kox32113@#$',
@ -11,15 +11,15 @@ export const initialState = {
const loginPageReducer = produce((draft, action) => { const loginPageReducer = produce((draft, action) => {
switch(action.type) { switch(action.type) {
case LOGIN_SUCCESS: case LOGIN_SUCCESS:
draft.loading = false; draft.isLoading = false;
break; break;
case LOGIN_REQUEST: case LOGIN_REQUEST:
draft.loading = true; draft.isLoading = true;
break; break;
case LOGIN_ERROR: case LOGIN_ERROR:
draft.loading = false; draft.isLoading = false;
draft.error = action.error; draft.error = action.error;
break; break;

View File

@ -74,8 +74,8 @@ export function* getActivities() {
}; };
try { try {
const { activities } = yield call(request, requestURL, requestParameters); const { results } = yield call(request, requestURL, requestParameters);
yield put(getActivitiesSuccessAction({ activities })); yield put(getActivitiesSuccessAction({ activities: results }));
} catch (error) { } catch (error) {
yield put(getActivitiesErrorAction({error: error.message})); yield put(getActivitiesErrorAction({error: error.message}));
} }
@ -94,8 +94,8 @@ export function* getGenders() {
}; };
try { try {
const { genders } = yield call(request, requestURL, requestParameters); const { results } = yield call(request, requestURL, requestParameters);
yield put(getGendersSuccessAction({ genders })); yield put(getGendersSuccessAction({ genders: results }));
} catch (error) { } catch (error) {
yield put(getGendersErrorAction({ error: error.message })); yield put(getGendersErrorAction({ error: error.message }));
} }
@ -113,8 +113,8 @@ export function* getGoals() {
}; };
try { try {
const { goals } = yield call(request, requestURL, requestParameters); const { results } = yield call(request, requestURL, requestParameters);
yield put(getGoalsSuccessAction({ goals })); yield put(getGoalsSuccessAction({ goals: results }));
} catch (error) { } catch (error) {
yield put(getGoalsErrorAction({ error: error.message })); yield put(getGoalsErrorAction({ error: error.message }));
} }

View File

@ -0,0 +1,22 @@
import { REGISTER_INPUT_CHANGE, REGISTER_REQUEST, REGISTER_SUCCESS, REGISTER_ERROR } from './constants';
export const registerInputChange = ({name, value}) => ({
type: REGISTER_INPUT_CHANGE,
name,
value,
})
export const registerAction = () => ({
type: REGISTER_REQUEST,
})
export const registerSuccessAction = ({user, tokens}) => ({
type: REGISTER_SUCCESS,
user,
tokens,
})
export const registerErrorAction = ({error}) => ({
type: REGISTER_ERROR,
error,
})

View File

@ -0,0 +1,5 @@
export const REGISTER_REQUEST = 'app/registerPage/REGISTER_REQUEST';
export const REGISTER_SUCCESS = 'app/registerPage/REGISTER_SUCCESS';
export const REGISTER_ERROR = 'app/registerPage/REGISTER_ERROR';
export const REGISTER_INPUT_CHANGE = 'app/registerPage/REGISTER_INPUT_CHANGE';

View File

@ -1,7 +1,14 @@
import React from 'react'; import React from 'react';
import { makeStyles } from '@material-ui/core/styles'; import { makeStyles } from '@material-ui/core/styles';
import {Container, Typography, Grid, Button, TextField, FormControlLabel, Checkbox, Link} from '@material-ui/core'; import {Container, Typography, Grid, Button, TextField, Link} from '@material-ui/core';
import { routes } from 'utils'; import { routes } from 'utils';
import {useInjectReducer, useInjectSaga} from "redux-injectors";
import {useDispatch, useSelector} from "react-redux";
import reducer from "./reducer";
import saga from "./saga";
import {registerAction, registerInputChange} from "./actions";
import {createStructuredSelector} from "reselect";
import {makeSelectEmail, makeSelectIsLoading, makeSelectPassword} from "./selectors";
const useStyles = makeStyles((theme) => ({ const useStyles = makeStyles((theme) => ({
paper: { paper: {
@ -19,8 +26,28 @@ const useStyles = makeStyles((theme) => ({
}, },
})); }));
const stateSelector = createStructuredSelector({
email: makeSelectEmail(),
password: makeSelectPassword(),
isLoading: makeSelectIsLoading(),
});
const key = 'registerPage'
const RegisterPage = () => { const RegisterPage = () => {
const classes = useStyles(); const classes = useStyles();
useInjectReducer({ key, reducer });
useInjectSaga({ key, saga });
const { email, password, isLoading } = useSelector(stateSelector)
const dispatch = useDispatch();
const onChangeInput = ({target: { name, value }}) => {
dispatch(registerInputChange({name, value}))
}
const handleSubmit = (event) => {
event.preventDefault()
dispatch(registerAction())
}
return ( return (
<Container component="main" maxWidth="xs"> <Container component="main" maxWidth="xs">
@ -28,7 +55,7 @@ const RegisterPage = () => {
<Typography component="h1" variant="h5"> <Typography component="h1" variant="h5">
Create Account Create Account
</Typography> </Typography>
<form className={classes.form} noValidate> <form className={classes.form} onSubmit={handleSubmit} noValidate>
<TextField <TextField
variant="outlined" variant="outlined"
margin="normal" margin="normal"
@ -38,6 +65,8 @@ const RegisterPage = () => {
label="Email Address" label="Email Address"
name="email" name="email"
autoComplete="email" autoComplete="email"
value={email}
onChange={onChangeInput}
autoFocus autoFocus
/> />
<TextField <TextField
@ -49,15 +78,14 @@ const RegisterPage = () => {
label="Password" label="Password"
type="password" type="password"
id="password" id="password"
value={password}
onChange={onChangeInput}
autoComplete="current-password" autoComplete="current-password"
/> />
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<Button <Button
type="submit" type="submit"
fullWidth fullWidth
disabled={isLoading}
variant="contained" variant="contained"
color="primary" color="primary"
className={classes.submit} className={classes.submit}

View File

@ -0,0 +1,32 @@
import produce from 'immer';
import {REGISTER_INPUT_CHANGE, REGISTER_ERROR, REGISTER_REQUEST, REGISTER_SUCCESS} from './constants';
export const initialState = {
isLoading: false,
error: {},
email: 'admin@admin.com',
password: 'Kox32113@#$',
};
const registerPageReducer = produce((draft, action) => {
switch(action.type) {
case REGISTER_SUCCESS:
draft.isLoading = false;
break;
case REGISTER_REQUEST:
draft.isLoading = true;
break;
case REGISTER_ERROR:
draft.isLoading = false;
draft.error = action.error;
break;
case REGISTER_INPUT_CHANGE:
draft[action.name] = action.value;
break;
}
}, initialState);
export default registerPageReducer;

View File

@ -0,0 +1,30 @@
import { takeLatest, call, put, select } from 'redux-saga/effects';
import { push } from 'connected-react-router';
import { api, request, routes } from 'utils';
import { REGISTER_REQUEST } from './constants';
import { makeSelectPassword, makeSelectEmail } from './selectors';
import { registerSuccessAction, registerErrorAction } from './actions';
export function* register() {
const email = yield select(makeSelectEmail());
const password = yield select(makeSelectPassword());
const requestURL = api.auth.register;
const requestParameters = {
method: 'POST',
headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password }),
};
try {
const { user, tokens } = yield call(request, requestURL, requestParameters);
yield put(registerSuccessAction({user, tokens}));
yield put(push(routes.profile.path));
} catch (error) {
yield put(registerErrorAction({ error: error.message }));
}
}
export default function* registerPageSaga() {
yield takeLatest(REGISTER_REQUEST, register);
}

View File

@ -0,0 +1,19 @@
import { createSelector } from 'reselect';
import { initialState } from './reducer';
const selectRegisterPageDomain = (state) => state.registerPage || initialState;
const makeSelectEmail = () =>
createSelector(selectRegisterPageDomain, (substate) => substate.email);
const makeSelectPassword = () =>
createSelector(selectRegisterPageDomain, (substate) => substate.password);
const makeSelectIsLoading = () =>
createSelector(selectRegisterPageDomain, (substate) => substate.isLoading);
export {
selectRegisterPageDomain,
makeSelectEmail,
makeSelectPassword,
makeSelectIsLoading,
};