WIP feature/Register

This commit is contained in:
elforjani3
2020-04-23 21:11:44 +02:00
parent 225a1b741c
commit 7e6b66fb74
10 changed files with 470 additions and 30 deletions

View File

@@ -0,0 +1,13 @@
import { connect } from 'react-redux';
import { submitInvite, submitSendInvite } from 'store/Invite/invite.action';
export const mapStateToProps = (state, props) => {
return {};
};
export const mapDispatchToProps = (dispatch) => ({
requestSubmitInvite: (form, token) => dispatch(submitInvite({ form, token })),
requestSendInvite: (form) => dispatch(submitSendInvite({ form })),
});
export default connect(mapStateToProps, mapDispatchToProps);

View File

@@ -0,0 +1,13 @@
import { connect } from 'react-redux';
import { submitResetPassword } from 'store/resetPassword/resetPassword.action';
export const mapStateToProps = (state, props) => {
return {};
};
export const mapDispatchToProps = (dispatch) => ({
requestResetPassword: (password) =>
dispatch(submitResetPassword({password})),
});
export default connect(mapStateToProps, mapDispatchToProps);

View File

@@ -0,0 +1,183 @@
import React, { useEffect, useMemo } from 'react';
import * as Yup from 'yup';
import { useFormik } from 'formik';
import { useIntl } from 'react-intl';
import ErrorMessage from 'components/ErrorMessage';
import AppToaster from 'components/AppToaster';
import { compose } from 'utils';
import InviteFormConnect from 'connectors/InviteForm.connect';
import { useParams } from 'react-router-dom';
import {
Button,
InputGroup,
Intent,
FormGroup,
HTMLSelect,
} from '@blueprintjs/core';
function Invite({ requestSubmitInvite }) {
const intl = useIntl();
let params = useParams('accept/:token');
const { token } = params;
const phoneRegExp = /^((\\+[1-9]{1,4}[ \\-]*)|(\\([0-9]{2,3}\\)[ \\-]*)|([0-9]{2,4})[ \\-]*)*?[0-9]{3,4}?[ \\-]*[0-9]{3,4}?$/;
const language = useMemo(
() => [
{ value: null, label: 'Select Country' },
{ value: 'Arabic', label: 'Arabic' },
{ value: 'English', label: 'English' },
],
[]
);
const ValidationSchema = Yup.object().shape({
first_name: Yup.string().required(intl.formatMessage({ id: 'required' })),
last_name: Yup.string().required(intl.formatMessage({ id: 'required' })),
email: Yup.string()
.email()
.required(intl.formatMessage({ id: 'required' })),
phone_number: Yup.string()
.matches(phoneRegExp)
.required(intl.formatMessage({ id: 'required' })),
language: Yup.string().required(
intl.formatMessage({
id: 'required',
})
),
password: Yup.string()
.min(4, 'Password has to be longer than 4 characters!')
.required('Password is required!'),
});
const initialValues = useMemo(
() => ({
first_name: '',
last_name: '',
email: '',
phone_number: '',
language: '',
password: '',
}),
[]
);
const formik = useFormik({
enableReinitialize: true,
validationSchema: ValidationSchema,
initialValues: {
...initialValues,
},
onSubmit: (values, { setSubmitting }) => {
requestSubmitInvite(values, token)
.then((response) => {
AppToaster.show({
message: 'success',
});
setSubmitting(false);
})
.catch((error) => {
setSubmitting(false);
});
},
});
const { errors, values, touched } = useMemo(() => formik, [formik]);
const requiredSpan = useMemo(() => <span class='required'>*</span>, []);
return (
<div className={'invite-form'}>
<form onSubmit={formik.handleSubmit}>
<FormGroup
label={'First Name'}
labelInfo={requiredSpan}
className={'form-group--first_name'}
intent={errors.first_name && touched.first_name && Intent.DANGER}
helperText={<ErrorMessage name={'first_name'} {...formik} />}
>
<InputGroup
intent={errors.first_name && touched.first_name && Intent.DANGER}
{...formik.getFieldProps('first_name')}
/>
</FormGroup>
<FormGroup
label={'Last Name'}
labelInfo={requiredSpan}
className={'form-group--last_name'}
intent={errors.last_name && touched.last_name && Intent.DANGER}
helperText={<ErrorMessage name={'last_name'} {...formik} />}
>
<InputGroup
intent={errors.last_name && touched.last_name && Intent.DANGER}
{...formik.getFieldProps('last_name')}
/>
</FormGroup>
<FormGroup
label={'Phone Number'}
labelInfo={requiredSpan}
className={'form-group--phone_number'}
intent={errors.phone_number && touched.phone_number && Intent.DANGER}
helperText={<ErrorMessage name={'phone_number'} {...formik} />}
>
<InputGroup
intent={
errors.phone_number && touched.phone_number && Intent.DANGER
}
{...formik.getFieldProps('phone_number')}
/>
</FormGroup>
<FormGroup
label={'Language'}
labelInfo={requiredSpan}
className={'form-group--language'}
intent={errors.language && touched.language && Intent.DANGER}
helperText={<ErrorMessage name={'language'} {...formik} />}
>
<HTMLSelect
fill={true}
options={language}
{...formik.getFieldProps('language')}
/>
</FormGroup>
<FormGroup
label={'Email'}
labelInfo={requiredSpan}
className={'form-group--email'}
intent={errors.email && touched.email && Intent.DANGER}
helperText={<ErrorMessage name={'email'} {...formik} />}
>
<InputGroup
intent={errors.email && touched.email && Intent.DANGER}
{...formik.getFieldProps('email')}
/>
</FormGroup>
<FormGroup
label={'Password'}
labelInfo={requiredSpan}
className={'form-group--password'}
intent={errors.password && touched.password && Intent.DANGER}
helperText={<ErrorMessage name={'password'} {...formik} />}
>
<InputGroup
lang={true}
type={'password'}
intent={errors.password && touched.password && Intent.DANGER}
{...formik.getFieldProps('password')}
/>
</FormGroup>
<div class='form__floating-footer'>
<Button intent={Intent.PRIMARY} type='submit'>
Invite
</Button>
</div>
</form>
</div>
);
}
export default compose(InviteFormConnect)(Invite);

View File

@@ -38,7 +38,9 @@ function Register({ requestSubmitRegister }) {
email: Yup.string()
.email()
.required(intl.formatMessage({ id: 'required' })),
phone_number: Yup.string().matches(phoneRegExp, 'required'),
phone_number: Yup.string()
.matches(phoneRegExp)
.required(intl.formatMessage({ id: 'required' })),
password: Yup.string()
.min(4, 'Password has to be longer than 8 characters!')
.required('Password is required!'),
@@ -78,8 +80,6 @@ function Register({ requestSubmitRegister }) {
},
});
console.log(formik.values);
const { errors, values, touched } = useMemo(() => formik, [formik]);
const requiredSpan = useMemo(() => <span class='required'>*</span>, []);
@@ -168,7 +168,7 @@ function Register({ requestSubmitRegister }) {
helperText={<ErrorMessage name={'email'} {...formik} />}
>
<InputGroup
intent={errors.last_name && touched.last_name && Intent.DANGER}
intent={errors.email && touched.email && Intent.DANGER}
{...formik.getFieldProps('email')}
/>
</FormGroup>

View File

@@ -1,29 +1,106 @@
import * as React from "react";
import { Link } from 'react-router-dom';
import {Button, InputGroup} from "@blueprintjs/core";
import { FormattedMessage } from 'react-intl';
import React, { useEffect, useMemo } from 'react';
import * as Yup from 'yup';
import { useFormik } from 'formik';
import { useIntl } from 'react-intl';
import {
Button,
InputGroup,
Intent,
FormGroup,
HTMLSelect,
} from '@blueprintjs/core';
import ErrorMessage from 'components/ErrorMessage';
import AppToaster from 'components/AppToaster';
import { compose } from 'utils';
import SendResetPasswordConnect from 'connectors/ResetPassword.connect';
function ResetPassword({ requestSendResetPassword }) {
const intl = useIntl();
const ValidationSchema = Yup.object().shape({
password: Yup.string()
.min(4, 'Password has to be longer than 4 characters!')
.required('Password is required!'),
confirm_password: Yup.string()
.oneOf([Yup.ref('password'), null], 'Passwords must match')
.required('Confirm Password is required'),
});
const initialValues = useMemo(
() => ({
password: '',
confirm_password: '',
}),
[]
);
const formik = useFormik({
enableReinitialize: true,
validationSchema: ValidationSchema,
initialValues: {
...initialValues,
},
onSubmit: (values, { setSubmitting }) => {
requestSendResetPassword(values.password)
.then((response) => {
AppToaster.show({
message: 'success',
});
setSubmitting(false);
})
.catch((error) => {
setSubmitting(false);
});
},
});
const { errors, values, touched } = useMemo(() => formik, [formik]);
const requiredSpan = useMemo(() => <span class='required'>*</span>, []);
export default function Login() {
return (
<div class="login-page">
<form>
<InputGroup
leftIcon="user"
placeholder={<FormattedMessage id="email_or_phone_number" />}
large={true}
className="input-group--email"
/>
<Button
fill={true}
large={true}>
<FormattedMessage id="reset_password" />
</Button>
<div className={'sendRestPassword-form'}>
<form onSubmit={formik.handleSubmit}>
<FormGroup
label={'Password'}
labelInfo={requiredSpan}
className={'form-group--password'}
intent={errors.password && touched.password && Intent.DANGER}
helperText={<ErrorMessage name={'password'} {...formik} />}
>
<InputGroup
lang={true}
type={'password'}
intent={errors.password && touched.password && Intent.DANGER}
{...formik.getFieldProps('password')}
/>
</FormGroup>
<FormGroup
label={'Confirm Password'}
labelInfo={requiredSpan}
className={'form-group--confirm_password'}
intent={
errors.confirm_password && touched.confirm_password && Intent.DANGER
}
helperText={<ErrorMessage name={'confirm_password'} {...formik} />}
>
<InputGroup
lang={true}
type={'password'}
intent={
errors.confirm_password &&
touched.confirm_password &&
Intent.DANGER
}
{...formik.getFieldProps('confirm_password')}
/>
</FormGroup>
<div class='form__floating-footer'>
<Button intent={Intent.PRIMARY} type='submit'>
Reset Password
</Button>
</div>
</form>
<div class="authentication-page__footer">
<Link to="/auth/login"><FormattedMessage id="login" /></Link>
</div>
</div>
)
}
);
}
export default compose(SendResetPasswordConnect)(ResetPassword);

View File

@@ -0,0 +1,81 @@
import React, { useEffect, useMemo } from 'react';
import * as Yup from 'yup';
import { useFormik } from 'formik';
import { useIntl } from 'react-intl';
import ErrorMessage from 'components/ErrorMessage';
import AppToaster from 'components/AppToaster';
import InviteFormConnect from 'connectors/InviteForm.connect';
import { compose } from 'utils';
import {
Button,
InputGroup,
Intent,
FormGroup,
HTMLSelect,
} from '@blueprintjs/core';
function SendInvite({ requestSendInvite }) {
const intl = useIntl();
const ValidationSchema = Yup.object().shape({
email: Yup.string()
.email()
.required(intl.formatMessage({ id: 'required' })),
});
const initialValues = useMemo(
() => ({
email: '',
}),
[]
);
const formik = useFormik({
enableReinitialize: true,
validationSchema: ValidationSchema,
initialValues: {
...initialValues,
},
onSubmit: (values, { setSubmitting }) => {
requestSendInvite(values)
.then((response) => {
AppToaster.show({
message: 'success',
});
setSubmitting(false);
})
.catch((error) => {
setSubmitting(false);
});
},
});
const { errors, values, touched } = useMemo(() => formik, [formik]);
const requiredSpan = useMemo(() => <span class='required'>*</span>, []);
return (
<div>
<form onSubmit={formik.handleSubmit}>
<FormGroup
label={'Email'}
labelInfo={requiredSpan}
className={'form-group--email'}
intent={errors.email && touched.email && Intent.DANGER}
helperText={<ErrorMessage name={'email'} {...formik} />}
>
<InputGroup
intent={errors.email && touched.email && Intent.DANGER}
{...formik.getFieldProps('email')}
/>
</FormGroup>
<div class='form__floating-footer'>
<Button intent={Intent.PRIMARY} type='submit'>
Send Invite
</Button>
</div>
</form>
</div>
);
}
export default compose(InviteFormConnect)(SendInvite);

View File

@@ -0,0 +1,29 @@
import * as React from 'react';
import { Link } from 'react-router-dom';
import { Button, InputGroup } from '@blueprintjs/core';
import { FormattedMessage } from 'react-intl';
export default function SendResetPassword() {
return (
<div class='login-page'>
<form>
<InputGroup
leftIcon='user'
placeholder={<FormattedMessage id='email_or_phone_number' />}
large={true}
className='input-group--email'
/>
<Button fill={true} large={true}>
<FormattedMessage id='send_reset_password' />
</Button>
</form>
<div class='authentication-page__footer'>
<Link to='/auth/login'>
<FormattedMessage id='login' />
</Link>
</div>
</div>
);
}

View File

@@ -17,11 +17,34 @@ export default [
loader: () => import('containers/Authentication/Register'),
}),
},
{
path: `${BASE_URL}/send_reset_password`,
name: 'auth.reset_password',
component: LazyLoader({
loader: () => import('containers/Authentication/SendResetPassword'),
}),
},
{
path: `${BASE_URL}/reset_password`,
name: 'auth.reset_password',
name: 'auth.send.reset_password',
component: LazyLoader({
loader: () => import('containers/Authentication/ResetPassword'),
}),
},
{
path: `${BASE_URL}/send_invite`,
name: 'auth.send_invite',
component: LazyLoader({
loader: () => import('containers/Authentication/SendInvite'),
}),
},
{
path: `${BASE_URL}/invite/:token`,
name: 'auth.invite',
component: LazyLoader({
loader: () => import('containers/Authentication/Invite'),
}),
},
];

View File

@@ -0,0 +1,14 @@
import ApiService from 'services/ApiService';
export const submitInvite = ({ form, token }) => {
return (dispatch) => {
return ApiService.post(`/invite/accept/${token}`, { ...form });
};
};
export const submitSendInvite = ({ form }) => {
return (dispatch) => {
return ApiService.post('invite', { form });
};
};

View File

@@ -0,0 +1,7 @@
import ApiService from 'services/ApiService';
export const submitResetPassword = (password) => {
return (dispatch) => {
return ApiService.post('auth/reset_password', password);
};
};