mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-21 15:20:34 +00:00
WIP / Design login and register page.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { submitResetPassword } from 'store/resetPassword/resetPassword.action';
|
import { submitResetPassword } from 'store/authentication/authentication.actions';
|
||||||
|
|
||||||
export const mapStateToProps = (state, props) => {
|
export const mapStateToProps = (state, props) => {
|
||||||
return {};
|
return {};
|
||||||
@@ -7,7 +7,7 @@ export const mapStateToProps = (state, props) => {
|
|||||||
|
|
||||||
export const mapDispatchToProps = (dispatch) => ({
|
export const mapDispatchToProps = (dispatch) => ({
|
||||||
requestResetPassword: (password) =>
|
requestResetPassword: (password) =>
|
||||||
dispatch(submitResetPassword({password})),
|
dispatch(submitResetPassword({ password })),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps);
|
export default connect(mapStateToProps, mapDispatchToProps);
|
||||||
|
|||||||
13
client/src/connectors/SendResetPassword.connect.js
Normal file
13
client/src/connectors/SendResetPassword.connect.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { submitSendResetPassword } from 'store/authentication/authentication.actions';
|
||||||
|
|
||||||
|
export const mapStateToProps = (state, props) => {
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const mapDispatchToProps = (dispatch) => ({
|
||||||
|
requestSendResetPassword: (email) =>
|
||||||
|
dispatch(submitSendResetPassword({ email })),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps);
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useMemo } from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
@@ -13,8 +13,14 @@ import {
|
|||||||
Intent,
|
Intent,
|
||||||
FormGroup,
|
FormGroup,
|
||||||
HTMLSelect,
|
HTMLSelect,
|
||||||
|
Icon,
|
||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
|
|
||||||
|
import { Row, Col } from 'react-grid-system';
|
||||||
|
import IconLog from 'components/Icon';
|
||||||
|
import Copyright from './copyright';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
function Invite({ requestSubmitInvite }) {
|
function Invite({ requestSubmitInvite }) {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
let params = useParams('accept/:token');
|
let params = useParams('accept/:token');
|
||||||
@@ -23,18 +29,12 @@ function Invite({ requestSubmitInvite }) {
|
|||||||
|
|
||||||
const phoneRegExp = /^((\\+[1-9]{1,4}[ \\-]*)|(\\([0-9]{2,3}\\)[ \\-]*)|([0-9]{2,4})[ \\-]*)*?[0-9]{3,4}?[ \\-]*[0-9]{3,4}?$/;
|
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({
|
const ValidationSchema = Yup.object().shape({
|
||||||
first_name: Yup.string().required(),
|
first_name: Yup.string().required(),
|
||||||
last_name: Yup.string().required(),
|
last_name: Yup.string().required(),
|
||||||
email: Yup.string().email().required(),
|
email: Yup.string().email().required(),
|
||||||
phone_number: Yup.string().matches(phoneRegExp).required(),
|
phone_number: Yup.string().matches(phoneRegExp).required(),
|
||||||
language: Yup.string().required(),
|
|
||||||
password: Yup.string()
|
password: Yup.string()
|
||||||
.min(4, 'Password has to be longer than 4 characters!')
|
.min(4, 'Password has to be longer than 4 characters!')
|
||||||
.required('Password is required!'),
|
.required('Password is required!'),
|
||||||
@@ -51,122 +51,175 @@ function Invite({ requestSubmitInvite }) {
|
|||||||
}),
|
}),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
const {
|
const formik = useFormik({
|
||||||
handleSubmit,
|
|
||||||
errors,
|
|
||||||
values,
|
|
||||||
touched,
|
|
||||||
getFieldProps,
|
|
||||||
} = useFormik({
|
|
||||||
enableReinitialize: true,
|
enableReinitialize: true,
|
||||||
validationSchema: ValidationSchema,
|
validationSchema: ValidationSchema,
|
||||||
initialValues: {
|
initialValues: {
|
||||||
...initialValues,
|
...initialValues,
|
||||||
},
|
},
|
||||||
onSubmit: (values, { setSubmitting }) => {
|
onSubmit: (values, { setSubmitting }) => {
|
||||||
requestSubmitInvite(values, token).then((response) => {
|
requestSubmitInvite(values, token)
|
||||||
AppToaster.show({
|
.then((response) => {
|
||||||
message: 'success',
|
AppToaster.show({
|
||||||
|
message: 'success',
|
||||||
|
});
|
||||||
|
setSubmitting(false);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setSubmitting(false);
|
||||||
});
|
});
|
||||||
setSubmitting(false);
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
setSubmitting(false);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const requiredSpan = useMemo(() => <span class='required'>*</span>, []);
|
const requiredSpan = useMemo(() => <span class='required'>*</span>, []);
|
||||||
|
|
||||||
|
const [shown, setShown] = useState(false);
|
||||||
|
|
||||||
|
const passwordRevealer = () => {
|
||||||
|
setShown(!shown);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div className={'invite-form'}>
|
<div className={'invite-form'}>
|
||||||
<form onSubmit={handleSubmit}>
|
<IconLog
|
||||||
<FormGroup
|
className={'invite-form__icon-section'}
|
||||||
label={'First Name'}
|
icon='bigcapital'
|
||||||
labelInfo={requiredSpan}
|
iconSize={150}
|
||||||
className={'form-group--first_name'}
|
/>
|
||||||
intent={errors.first_name && touched.first_name && Intent.DANGER}
|
<form onSubmit={formik.handleSubmit}>
|
||||||
helperText={<ErrorMessage name={'first_name'} />}
|
<div className={'invite-form__label-section'}>
|
||||||
>
|
<h3>Welcome to Bigcapital</h3>
|
||||||
<InputGroup
|
<p>
|
||||||
intent={errors.first_name && touched.first_name && Intent.DANGER}
|
Enter your personal information <b>{'Organization Name'}</b>{' '}
|
||||||
{...getFieldProps('first_name')}
|
Organization.
|
||||||
/>
|
</p>
|
||||||
</FormGroup>
|
</div>
|
||||||
|
|
||||||
<FormGroup
|
<Row>
|
||||||
label={'Last Name'}
|
<Col md={6}>
|
||||||
labelInfo={requiredSpan}
|
<FormGroup
|
||||||
className={'form-group--last_name'}
|
label={'First Name'}
|
||||||
intent={errors.last_name && touched.last_name && Intent.DANGER}
|
className={'form-group--first_name'}
|
||||||
helperText={<ErrorMessage name={'last_name'} />}
|
intent={
|
||||||
>
|
formik.errors.first_name &&
|
||||||
<InputGroup
|
formik.touched.first_name &&
|
||||||
intent={errors.last_name && touched.last_name && Intent.DANGER}
|
Intent.DANGER
|
||||||
{...getFieldProps('last_name')}
|
}
|
||||||
/>
|
helperText={<ErrorMessage name={'first_name'} {...formik} />}
|
||||||
</FormGroup>
|
>
|
||||||
|
<InputGroup
|
||||||
|
intent={
|
||||||
|
formik.errors.first_name &&
|
||||||
|
formik.touched.first_name &&
|
||||||
|
Intent.DANGER
|
||||||
|
}
|
||||||
|
{...formik.getFieldProps('first_name')}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</Col>
|
||||||
|
<Col md={6}>
|
||||||
|
<FormGroup
|
||||||
|
label={'Last Name'}
|
||||||
|
className={'form-group--last_name'}
|
||||||
|
intent={
|
||||||
|
formik.errors.last_name &&
|
||||||
|
formik.touched.last_name &&
|
||||||
|
Intent.DANGER
|
||||||
|
}
|
||||||
|
helperText={<ErrorMessage name={'last_name'} {...formik} />}
|
||||||
|
>
|
||||||
|
<InputGroup
|
||||||
|
intent={
|
||||||
|
formik.errors.last_name &&
|
||||||
|
formik.touched.last_name &&
|
||||||
|
Intent.DANGER
|
||||||
|
}
|
||||||
|
{...formik.getFieldProps('last_name')}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<div>
|
||||||
|
<FormGroup
|
||||||
|
label={'Phone Number'}
|
||||||
|
className={'form-group--phone_number'}
|
||||||
|
intent={
|
||||||
|
formik.errors.phone_number &&
|
||||||
|
formik.touched.phone_number &&
|
||||||
|
Intent.DANGER
|
||||||
|
}
|
||||||
|
helperText={<ErrorMessage name={'phone_number'} {...formik} />}
|
||||||
|
>
|
||||||
|
<InputGroup
|
||||||
|
intent={
|
||||||
|
formik.errors.phone_number &&
|
||||||
|
formik.touched.phone_number &&
|
||||||
|
Intent.DANGER
|
||||||
|
}
|
||||||
|
{...formik.getFieldProps('phone_number')}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</div>
|
||||||
|
|
||||||
<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'} />}
|
|
||||||
>
|
|
||||||
<InputGroup
|
|
||||||
intent={(errors.phone_number && touched.phone_number) && Intent.DANGER}
|
|
||||||
{...getFieldProps('phone_number')}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
|
|
||||||
<FormGroup
|
|
||||||
label={'Language'}
|
|
||||||
labelInfo={requiredSpan}
|
|
||||||
className={'form-group--language'}
|
|
||||||
intent={(errors.language && touched.language) && Intent.DANGER}
|
|
||||||
helperText={<ErrorMessage name={'language'} />}
|
|
||||||
>
|
|
||||||
<HTMLSelect
|
|
||||||
fill={true}
|
|
||||||
options={language}
|
|
||||||
{...getFieldProps('language')}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
|
|
||||||
<FormGroup
|
|
||||||
label={'Email'}
|
label={'Email'}
|
||||||
labelInfo={requiredSpan}
|
|
||||||
className={'form-group--email'}
|
className={'form-group--email'}
|
||||||
intent={(errors.email && touched.email) && Intent.DANGER}
|
intent={errors.email && touched.email && Intent.DANGER}
|
||||||
helperText={<ErrorMessage name={'email'} />}
|
helperText={<ErrorMessage name={'email'} />}
|
||||||
>
|
>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
intent={errors.email && touched.email && Intent.DANGER}
|
intent={errors.email && touched.email && Intent.DANGER}
|
||||||
{...getFieldProps('email')}
|
{...getFieldProps('email')}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup> */}
|
||||||
|
<div>
|
||||||
|
<FormGroup
|
||||||
|
label={'Password'}
|
||||||
|
labelInfo={
|
||||||
|
<span onClick={() => passwordRevealer()}>
|
||||||
|
<Icon icon='eye-open' />
|
||||||
|
Show
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
className={'form-group--password'}
|
||||||
|
intent={
|
||||||
|
formik.errors.password && formik.touched.password && Intent.DANGER
|
||||||
|
}
|
||||||
|
helperText={<ErrorMessage name={'password'} {...formik} />}
|
||||||
|
>
|
||||||
|
<InputGroup
|
||||||
|
lang={true}
|
||||||
|
type={shown ? 'text' : 'password'}
|
||||||
|
intent={
|
||||||
|
formik.errors.password &&
|
||||||
|
formik.touched.password &&
|
||||||
|
Intent.DANGER
|
||||||
|
}
|
||||||
|
{...formik.getFieldProps('password')}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</div>
|
||||||
|
|
||||||
<FormGroup
|
<div className={'invite-form__statement-section'}>
|
||||||
label={'Password'}
|
<p>
|
||||||
labelInfo={requiredSpan}
|
You email address is <b>{'xxx@gamil.com'},</b> <br />
|
||||||
className={'form-group--password'}
|
You will use this address to sign in to Bigcapital.
|
||||||
intent={(errors.password && touched.password) && Intent.DANGER}
|
</p>
|
||||||
helperText={<ErrorMessage name={'password'} />}
|
<p>
|
||||||
>
|
By signing in or creating an account, you agree with our <br />
|
||||||
<InputGroup
|
<Link>Terms & Conditions</Link> and <Link> Privacy Statement</Link>
|
||||||
lang={true}
|
</p>
|
||||||
type={'password'}
|
</div>
|
||||||
intent={(errors.password && touched.password) && Intent.DANGER}
|
<div class='invite-form__floating-footer'>
|
||||||
{...getFieldProps('password')}
|
<Button
|
||||||
/>
|
className={'btn-invite'}
|
||||||
</FormGroup>
|
intent={Intent.PRIMARY}
|
||||||
|
type='submit'
|
||||||
<div class='form__floating-footer'>
|
>
|
||||||
<Button intent={Intent.PRIMARY} type='submit'>
|
Create Account
|
||||||
Invite
|
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
<Copyright />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,42 +1,47 @@
|
|||||||
import React, { useEffect } from "react";
|
import React, { useEffect, useState } from 'react';
|
||||||
import {Link, useHistory} from 'react-router-dom';
|
import { Link, useHistory } from 'react-router-dom';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import {useFormik} from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import {connect} from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {useIntl} from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
InputGroup,
|
InputGroup,
|
||||||
Intent,
|
Intent,
|
||||||
FormGroup,
|
FormGroup,
|
||||||
} from "@blueprintjs/core";
|
Checkbox,
|
||||||
|
Icon,
|
||||||
|
} from '@blueprintjs/core';
|
||||||
import login from 'store/authentication/authentication.actions';
|
import login from 'store/authentication/authentication.actions';
|
||||||
import {hasErrorType, isAuthenticated} from 'store/authentication/authentication.reducer';
|
import {
|
||||||
|
hasErrorType,
|
||||||
|
isAuthenticated,
|
||||||
|
} from 'store/authentication/authentication.reducer';
|
||||||
import AuthenticationToaster from 'components/AppToaster';
|
import AuthenticationToaster from 'components/AppToaster';
|
||||||
import t from 'store/types';
|
import t from 'store/types';
|
||||||
|
import ErrorMessage from 'components/ErrorMessage';
|
||||||
|
import IconLog from 'components/Icon';
|
||||||
|
import Copyright from './copyright';
|
||||||
|
|
||||||
const ERRORS_TYPES = {
|
const ERRORS_TYPES = {
|
||||||
INVALID_DETAILS: 'INVALID_DETAILS',
|
INVALID_DETAILS: 'INVALID_DETAILS',
|
||||||
USER_INACTIVE: 'USER_INACTIVE',
|
USER_INACTIVE: 'USER_INACTIVE',
|
||||||
};
|
};
|
||||||
function Login({
|
function Login({ login, errors, clearErrors, hasError }) {
|
||||||
login,
|
|
||||||
errors,
|
|
||||||
clearErrors,
|
|
||||||
hasError,
|
|
||||||
}) {
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
|
|
||||||
|
const [shown, setShown] = useState(false);
|
||||||
|
|
||||||
// Validation schema.
|
// Validation schema.
|
||||||
const loginValidationSchema = Yup.object().shape({
|
const loginValidationSchema =
|
||||||
crediential: Yup
|
Yup.object().shape({
|
||||||
.string()
|
crediential: Yup.string()
|
||||||
.required(intl.formatMessage({'id': 'required'}))
|
.required(intl.formatMessage({ id: 'required' }))
|
||||||
.email(intl.formatMessage({id: 'invalid_email_or_phone_numner'})),
|
.email(intl.formatMessage({ id: 'invalid_email_or_phone_numner' })),
|
||||||
password: Yup
|
password: Yup.string()
|
||||||
.string()
|
.required(intl.formatMessage({ id: 'required' }))
|
||||||
.required(intl.formatMessage({id: 'required'}))
|
|
||||||
.min(4),
|
.min(4),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -65,11 +70,13 @@ function Login({
|
|||||||
}
|
}
|
||||||
if (hasError(ERRORS_TYPES.USER_INACTIVE)) {
|
if (hasError(ERRORS_TYPES.USER_INACTIVE)) {
|
||||||
toastBuilders.push({
|
toastBuilders.push({
|
||||||
message: intl.formatMessage({ id: 'the_user_has_been_suspended_from_admin' }),
|
message: intl.formatMessage({
|
||||||
|
id: 'the_user_has_been_suspended_from_admin',
|
||||||
|
}),
|
||||||
intent: Intent.WARNING,
|
intent: Intent.WARNING,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
toastBuilders.forEach(builder => {
|
toastBuilders.forEach((builder) => {
|
||||||
AuthenticationToaster.show(builder);
|
AuthenticationToaster.show(builder);
|
||||||
});
|
});
|
||||||
}, [hasError, intl]);
|
}, [hasError, intl]);
|
||||||
@@ -81,53 +88,87 @@ function Login({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const passwordRevealer = () => {
|
||||||
|
setShown(!shown);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="login-page">
|
<div className='login-form'>
|
||||||
|
<IconLog
|
||||||
|
className={'login-form__icon-section'}
|
||||||
|
icon='bigcapital'
|
||||||
|
iconSize={150}
|
||||||
|
/>
|
||||||
<form onSubmit={formik.handleSubmit}>
|
<form onSubmit={formik.handleSubmit}>
|
||||||
<FormGroup
|
<div className={'login-form__label-section'}>
|
||||||
className={'form-group--crediential'}
|
<h3>Log in</h3>
|
||||||
intent={formik.errors.crediential && Intent.DANGER}
|
Need a Bigcapital account ?
|
||||||
helperText={formik.errors.crediential && formik.errors.crediential}>
|
<Link to='/auth/register'> Create an account</Link>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<FormGroup
|
||||||
|
label={'Email or Phone Number'}
|
||||||
|
intent={
|
||||||
|
formik.errors.crediential &&
|
||||||
|
formik.touched.crediential &&
|
||||||
|
Intent.DANGER
|
||||||
|
}
|
||||||
|
helperText={<ErrorMessage name={'crediential'} {...formik} />}
|
||||||
|
>
|
||||||
|
<InputGroup
|
||||||
|
intent={
|
||||||
|
formik.errors.crediential &&
|
||||||
|
formik.touched.crediential &&
|
||||||
|
Intent.DANGER
|
||||||
|
}
|
||||||
|
large={true}
|
||||||
|
{...formik.getFieldProps('crediential')}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<FormGroup
|
||||||
|
label={'Password'}
|
||||||
|
labelInfo={
|
||||||
|
<span onClick={() => passwordRevealer()}>
|
||||||
|
<Icon icon='eye-open' />
|
||||||
|
Show
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
intent={
|
||||||
|
formik.errors.password && formik.touched.password && Intent.DANGER
|
||||||
|
}
|
||||||
|
helperText={<ErrorMessage name={'password'} {...formik} />}
|
||||||
|
>
|
||||||
|
<InputGroup
|
||||||
|
large={true}
|
||||||
|
intent={
|
||||||
|
formik.errors.password &&
|
||||||
|
formik.touched.password &&
|
||||||
|
Intent.DANGER
|
||||||
|
}
|
||||||
|
type={shown ? 'text' : 'password'}
|
||||||
|
{...formik.getFieldProps('password')}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</div>
|
||||||
|
<div className={'login-form__checkbox-section'}>
|
||||||
|
<Checkbox>Keep me logged in</Checkbox>
|
||||||
|
</div>
|
||||||
|
|
||||||
<InputGroup
|
<div className={'login-form__floating-footer-section'}>
|
||||||
leftIcon="user"
|
<Button
|
||||||
placeholder={intl.formatMessage({'id': 'email_or_phone_number'})}
|
className={'btn-login'}
|
||||||
large={true}
|
type={'submit'}
|
||||||
intent={formik.errors.crediential && Intent.DANGER}
|
intent={Intent.PRIMARY}
|
||||||
{...formik.getFieldProps('crediential')} />
|
fill={true}
|
||||||
</FormGroup>
|
lang={true}
|
||||||
|
>
|
||||||
<FormGroup
|
{intl.formatMessage({ id: 'Log in' })}
|
||||||
className={'form-group--password'}
|
</Button>
|
||||||
intent={formik.errors.password && Intent.DANGER}
|
</div>
|
||||||
helperText={formik.errors.password && formik.errors.password}>
|
|
||||||
|
|
||||||
<InputGroup
|
|
||||||
leftIcon="info-sign"
|
|
||||||
placeholder={intl.formatMessage({'id': 'password'})}
|
|
||||||
large={true}
|
|
||||||
intent={formik.errors.password && Intent.DANGER}
|
|
||||||
type={"password"}
|
|
||||||
{...formik.getFieldProps('password')} />
|
|
||||||
</FormGroup>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
fill={true}
|
|
||||||
large={true}>
|
|
||||||
{intl.formatMessage({'id': 'login '})}
|
|
||||||
</Button>
|
|
||||||
</form>
|
</form>
|
||||||
|
<Copyright />
|
||||||
<div className="authentication-page__footer">
|
|
||||||
<Link to="/auth/send_reset_password">
|
|
||||||
{intl.formatMessage({'id': 'reset_password '})}
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<Link to="/auth/register">
|
|
||||||
{intl.formatMessage({'id': 'register '})}
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -138,8 +179,8 @@ const mapStateToProps = (state) => ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
login: form => dispatch(login({ form })),
|
login: (form) => dispatch(login({ form })),
|
||||||
clearErrors: () => dispatch({ type: t.LOGIN_CLEAR_ERRORS }),
|
clearErrors: () => dispatch({ type: t.LOGIN_CLEAR_ERRORS }),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(Login);
|
export default connect(mapStateToProps, mapDispatchToProps)(Login);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useMemo } from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
@@ -8,20 +8,27 @@ import {
|
|||||||
Intent,
|
Intent,
|
||||||
FormGroup,
|
FormGroup,
|
||||||
HTMLSelect,
|
HTMLSelect,
|
||||||
|
Icon,
|
||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
import RegisterFromConnect from 'connectors/RegisterForm.connect';
|
import RegisterFromConnect from 'connectors/RegisterForm.connect';
|
||||||
import ErrorMessage from 'components/ErrorMessage';
|
import ErrorMessage from 'components/ErrorMessage';
|
||||||
import AppToaster from 'components/AppToaster';
|
import AppToaster from 'components/AppToaster';
|
||||||
import { compose, regExpCollection } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
import { Row, Col } from 'react-grid-system';
|
||||||
|
import IconLog from 'components/Icon';
|
||||||
|
import Copyright from './copyright';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
// import { compose, regExpCollection } from 'utils';
|
||||||
|
|
||||||
function Register({
|
function Register({ requestSubmitRegister }) {
|
||||||
requestSubmitRegister,
|
|
||||||
}) {
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const Country = useMemo(() => [
|
const Country = useMemo(
|
||||||
{ value: null, label: 'Select Country' },
|
() => [
|
||||||
{ value: 'libya', label: 'Libya' },
|
{ value: null, label: 'Select Country' },
|
||||||
], []);
|
{ value: 'libya', label: 'Libya' },
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
const ValidationSchema = Yup.object().shape({
|
const ValidationSchema = Yup.object().shape({
|
||||||
organization_name: Yup.string().required(),
|
organization_name: Yup.string().required(),
|
||||||
@@ -29,32 +36,28 @@ function Register({
|
|||||||
last_name: Yup.string().required(),
|
last_name: Yup.string().required(),
|
||||||
email: Yup.string().email().required(),
|
email: Yup.string().email().required(),
|
||||||
phone_number: Yup.string()
|
phone_number: Yup.string()
|
||||||
.matches(regExpCollection.phoneNumber)
|
.matches()
|
||||||
.required(intl.formatMessage({ id: 'required' })),
|
.required(intl.formatMessage({ id: 'required' })),
|
||||||
password: Yup.string()
|
password: Yup.string()
|
||||||
.min(4, 'Password has to be longer than 8 characters!')
|
.min(4, 'Password has to be longer than 8 characters!')
|
||||||
.required('Password is required!'),
|
.required('Password is required!'),
|
||||||
country: Yup.string().required(intl.formatMessage({ id: 'required' })),
|
// country: Yup.string().required(intl.formatMessage({ id: 'required' })),
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialValues = useMemo(() => ({
|
const initialValues = useMemo(
|
||||||
organization_name: '',
|
() => ({
|
||||||
first_name: '',
|
organization_name: '',
|
||||||
last_name: '',
|
first_name: '',
|
||||||
email: '',
|
last_name: '',
|
||||||
phone_number: '',
|
email: '',
|
||||||
password: '',
|
phone_number: '',
|
||||||
country: '',
|
password: '',
|
||||||
}), []);
|
// country: '',
|
||||||
|
}),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
const {
|
const formik = useFormik({
|
||||||
getFieldProps,
|
|
||||||
getFieldMeta,
|
|
||||||
errors,
|
|
||||||
values,
|
|
||||||
touched,
|
|
||||||
handleSubmit,
|
|
||||||
} = useFormik({
|
|
||||||
enableReinitialize: true,
|
enableReinitialize: true,
|
||||||
validationSchema: ValidationSchema,
|
validationSchema: ValidationSchema,
|
||||||
initialValues: {
|
initialValues: {
|
||||||
@@ -76,120 +79,173 @@ function Register({
|
|||||||
|
|
||||||
const requiredSpan = useMemo(() => <span class='required'>*</span>, []);
|
const requiredSpan = useMemo(() => <span class='required'>*</span>, []);
|
||||||
|
|
||||||
|
const [shown, setShown] = useState(false);
|
||||||
|
|
||||||
|
const passwordRevealer = () => {
|
||||||
|
setShown(!shown);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'register-form'}>
|
<div className={'register-form'}>
|
||||||
<form onSubmit={handleSubmit}>
|
<IconLog
|
||||||
<FormGroup
|
className={'register-form__icon-section'}
|
||||||
label={'Organization Name'}
|
icon='bigcapital'
|
||||||
labelInfo={requiredSpan}
|
iconSize={150}
|
||||||
className={'form-group--name'}
|
/>
|
||||||
intent={
|
<form onSubmit={formik.handleSubmit}>
|
||||||
(errors.organization_name && touched.organization_name) &&
|
<div className={'register-form__label-section'}>
|
||||||
Intent.DANGER
|
<h3>
|
||||||
}
|
Register a New <br />
|
||||||
helperText={<ErrorMessage name={'organization_name'} />}
|
Organization.
|
||||||
>
|
</h3>
|
||||||
<InputGroup
|
You have a bigcapital account ?<Link to='/auth/login'> Login</Link>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<FormGroup
|
||||||
|
label={'Organization Name'}
|
||||||
|
className={'form-group--name'}
|
||||||
intent={
|
intent={
|
||||||
(errors.organization_name &&
|
formik.errors.organization_name &&
|
||||||
touched.organization_name) &&
|
formik.touched.organization_name &&
|
||||||
Intent.DANGER
|
Intent.DANGER
|
||||||
}
|
}
|
||||||
{...getFieldProps('organization_name')}
|
helperText={<ErrorMessage {...formik} name={'organization_name'} />}
|
||||||
/>
|
>
|
||||||
</FormGroup>
|
<InputGroup
|
||||||
|
intent={
|
||||||
|
formik.errors.organization_name &&
|
||||||
|
formik.touched.organization_name &&
|
||||||
|
formik.Intent.DANGER
|
||||||
|
}
|
||||||
|
{...formik.getFieldProps('organization_name')}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</div>
|
||||||
|
<Row className={'name-section'}>
|
||||||
|
<Col md={6}>
|
||||||
|
<FormGroup
|
||||||
|
label={'First Name'}
|
||||||
|
intent={
|
||||||
|
formik.errors.first_name &&
|
||||||
|
formik.touched.first_name &&
|
||||||
|
Intent.DANGER
|
||||||
|
}
|
||||||
|
helperText={<ErrorMessage name={'first_name'} {...formik} />}
|
||||||
|
>
|
||||||
|
<InputGroup
|
||||||
|
intent={
|
||||||
|
formik.errors.first_name &&
|
||||||
|
formik.touched.first_name &&
|
||||||
|
Intent.DANGER
|
||||||
|
}
|
||||||
|
{...formik.getFieldProps('first_name')}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</Col>
|
||||||
|
<Col md={6}>
|
||||||
|
<FormGroup
|
||||||
|
label={'Last Name'}
|
||||||
|
intent={
|
||||||
|
formik.errors.last_name &&
|
||||||
|
formik.touched.last_name &&
|
||||||
|
Intent.DANGER
|
||||||
|
}
|
||||||
|
helperText={<ErrorMessage name={'last_name'} {...formik} />}
|
||||||
|
>
|
||||||
|
<InputGroup
|
||||||
|
intent={
|
||||||
|
formik.errors.last_name &&
|
||||||
|
formik.touched.last_name &&
|
||||||
|
Intent.DANGER
|
||||||
|
}
|
||||||
|
{...formik.getFieldProps('last_name')}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
<FormGroup
|
<div>
|
||||||
label={'First Name'}
|
<FormGroup
|
||||||
labelInfo={requiredSpan}
|
label={'Phone Number'}
|
||||||
className={'form-group--first_name'}
|
intent={
|
||||||
intent={(errors.first_name && touched.first_name) && Intent.DANGER}
|
formik.errors.phone_number &&
|
||||||
helperText={<ErrorMessage name={'first_name'} />}
|
formik.touched.phone_number &&
|
||||||
>
|
Intent.DANGER
|
||||||
<InputGroup
|
}
|
||||||
intent={errors.first_name && touched.first_name && Intent.DANGER}
|
helperText={<ErrorMessage name={'phone_number'} {...formik} />}
|
||||||
{...getFieldProps('first_name')}
|
>
|
||||||
/>
|
<InputGroup
|
||||||
</FormGroup>
|
intent={
|
||||||
|
formik.errors.phone_number &&
|
||||||
<FormGroup
|
formik.touched.phone_number &&
|
||||||
label={'Last Name'}
|
Intent.DANGER
|
||||||
labelInfo={requiredSpan}
|
}
|
||||||
className={'form-group--last_name'}
|
{...formik.getFieldProps('phone_number')}
|
||||||
intent={errors.last_name && touched.last_name && Intent.DANGER}
|
/>
|
||||||
helperText={<ErrorMessage name={'last_name'} />}
|
</FormGroup>
|
||||||
>
|
</div>
|
||||||
<InputGroup
|
<div>
|
||||||
intent={errors.last_name && touched.last_name && Intent.DANGER}
|
<FormGroup
|
||||||
{...getFieldProps('last_name')}
|
label={'Email'}
|
||||||
/>
|
intent={
|
||||||
</FormGroup>
|
formik.errors.email && formik.touched.email && Intent.DANGER
|
||||||
|
}
|
||||||
<FormGroup
|
helperText={<ErrorMessage name={'email'} {...formik} />}
|
||||||
label={'Country'}
|
>
|
||||||
labelInfo={requiredSpan}
|
<InputGroup
|
||||||
className={'form-group--country'}
|
intent={
|
||||||
intent={(errors.country && touched.country) && Intent.DANGER}
|
formik.errors.email && formik.touched.email && Intent.DANGER
|
||||||
helperText={<ErrorMessage name={'country'} />}
|
}
|
||||||
>
|
{...formik.getFieldProps('email')}
|
||||||
<HTMLSelect
|
/>
|
||||||
fill={true}
|
</FormGroup>
|
||||||
options={Country}
|
</div>
|
||||||
{...getFieldProps('country')}
|
<div>
|
||||||
/>
|
<FormGroup
|
||||||
</FormGroup>
|
label={'Password'}
|
||||||
|
labelInfo={
|
||||||
<FormGroup
|
<span onClick={() => passwordRevealer()}>
|
||||||
label={'Phone Number'}
|
<Icon icon='eye-open' />
|
||||||
labelInfo={requiredSpan}
|
Show
|
||||||
className={'form-group--phone_number'}
|
</span>
|
||||||
intent={(errors.phone_number && touched.phone_number) && Intent.DANGER}
|
}
|
||||||
helperText={<ErrorMessage name={'phone_number'} />}
|
className={'form-group--password'}
|
||||||
>
|
intent={
|
||||||
<InputGroup
|
formik.errors.password && formik.touched.password && Intent.DANGER
|
||||||
intent={(errors.phone_number && touched.phone_number) && Intent.DANGER}
|
}
|
||||||
{...getFieldProps('phone_number')}
|
helperText={<ErrorMessage name={'password'} {...formik} />}
|
||||||
/>
|
>
|
||||||
</FormGroup>
|
<InputGroup
|
||||||
|
lang={true}
|
||||||
<FormGroup
|
type={shown ? 'text' : 'password'}
|
||||||
label={'Email'}
|
intent={
|
||||||
labelInfo={requiredSpan}
|
formik.errors.password &&
|
||||||
className={'form-group--email'}
|
formik.touched.password &&
|
||||||
intent={(errors.email && touched.email) && Intent.DANGER}
|
Intent.DANGER
|
||||||
helperText={<ErrorMessage name={'email'} />}
|
}
|
||||||
>
|
{...formik.getFieldProps('password')}
|
||||||
<InputGroup
|
/>
|
||||||
intent={errors.email && touched.email && Intent.DANGER}
|
</FormGroup>
|
||||||
{...getFieldProps('email')}
|
</div>
|
||||||
/>
|
<div className={'register-form__statement-section'}>
|
||||||
</FormGroup>
|
<p>
|
||||||
|
By signing in or creating an account, you agree with our <br />
|
||||||
<FormGroup
|
<Link>Terms & Conditions</Link> and <Link> Privacy Statement</Link>
|
||||||
label={'Password'}
|
</p>
|
||||||
labelInfo={requiredSpan}
|
</div>
|
||||||
className={'form-group--password'}
|
<div className={'register-form__floating-footer-section'}>
|
||||||
intent={(errors.password && touched.password) && Intent.DANGER}
|
<Button
|
||||||
helperText={<ErrorMessage name={'password'} />}
|
className={'btn-register'}
|
||||||
>
|
intent={Intent.PRIMARY}
|
||||||
<InputGroup
|
type='submit'
|
||||||
lang={true}
|
>
|
||||||
type={'password'}
|
|
||||||
intent={(errors.password && touched.password) && Intent.DANGER}
|
|
||||||
{...getFieldProps('password')}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
|
|
||||||
<div class='form__floating-footer'>
|
|
||||||
<Button intent={Intent.PRIMARY} type='submit'>
|
|
||||||
Register
|
Register
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
<Copyright />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
export default compose(RegisterFromConnect)(Register);
|
||||||
RegisterFromConnect,
|
|
||||||
)(Register);
|
|
||||||
|
|||||||
@@ -12,11 +12,12 @@ import {
|
|||||||
import ErrorMessage from 'components/ErrorMessage';
|
import ErrorMessage from 'components/ErrorMessage';
|
||||||
import AppToaster from 'components/AppToaster';
|
import AppToaster from 'components/AppToaster';
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
import SendResetPasswordConnect from 'connectors/ResetPassword.connect';
|
import ResetPasswordConnect from 'connectors/ResetPassword.connect';
|
||||||
|
import Icon from 'components/Icon';
|
||||||
|
import Copyright from './copyright';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
function ResetPassword({
|
function ResetPassword({ requestSendResetPassword }) {
|
||||||
requestSendResetPassword,
|
|
||||||
}) {
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const ValidationSchema = Yup.object().shape({
|
const ValidationSchema = Yup.object().shape({
|
||||||
password: Yup.string()
|
password: Yup.string()
|
||||||
@@ -27,19 +28,15 @@ function ResetPassword({
|
|||||||
.required('Confirm Password is required'),
|
.required('Confirm Password is required'),
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialValues = useMemo(() => ({
|
const initialValues = useMemo(
|
||||||
password: '',
|
() => ({
|
||||||
confirm_password: '',
|
password: '',
|
||||||
}), []);
|
confirm_password: '',
|
||||||
|
}),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
const {
|
const formik= useFormik({
|
||||||
errors,
|
|
||||||
values,
|
|
||||||
touched,
|
|
||||||
getFieldMeta,
|
|
||||||
getFieldProps,
|
|
||||||
handleSubmit,
|
|
||||||
} = useFormik({
|
|
||||||
enableReinitialize: true,
|
enableReinitialize: true,
|
||||||
validationSchema: ValidationSchema,
|
validationSchema: ValidationSchema,
|
||||||
initialValues: {
|
initialValues: {
|
||||||
@@ -62,52 +59,66 @@ function ResetPassword({
|
|||||||
const requiredSpan = useMemo(() => <span class='required'>*</span>, []);
|
const requiredSpan = useMemo(() => <span class='required'>*</span>, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'sendRestPassword-form'}>
|
<div className={'submit-np-form'}>
|
||||||
<form onSubmit={handleSubmit}>
|
<div>
|
||||||
<FormGroup
|
<Icon
|
||||||
label={'Password'}
|
className={'submit-np-form__icon-section'}
|
||||||
labelInfo={requiredSpan}
|
icon='bigcapital'
|
||||||
className={'form-group--password'}
|
iconSize={150}
|
||||||
intent={errors.password && touched.password && Intent.DANGER}
|
/>
|
||||||
helperText={<ErrorMessage name={'password'} />}
|
</div>
|
||||||
>
|
<form onSubmit={formik.handleSubmit}>
|
||||||
<InputGroup
|
<div className={'submit-np-form__label-section'}>
|
||||||
lang={true}
|
<h3>Choose a new password</h3>
|
||||||
type={'password'}
|
You remembered your password ? <Link to='/auth/login'>Login</Link>
|
||||||
intent={errors.password && touched.password && Intent.DANGER}
|
</div>
|
||||||
{...getFieldProps('password')}
|
<div>
|
||||||
/>
|
<FormGroup
|
||||||
</FormGroup>
|
label={'Password'}
|
||||||
|
intent={formik.errors.password && formik.touched.password && Intent.DANGER}
|
||||||
<FormGroup
|
helperText={<ErrorMessage name={'password'} {...formik} />}
|
||||||
label={'Confirm Password'}
|
>
|
||||||
labelInfo={requiredSpan}
|
<InputGroup
|
||||||
className={'form-group--confirm_password'}
|
lang={true}
|
||||||
intent={
|
type={'password'}
|
||||||
errors.confirm_password && touched.confirm_password && Intent.DANGER
|
intent={formik.errors.password && formik.touched.password && Intent.DANGER}
|
||||||
}
|
{...formik.getFieldProps('password')}
|
||||||
helperText={<ErrorMessage name={'confirm_password'} />}
|
/>
|
||||||
>
|
</FormGroup>
|
||||||
<InputGroup
|
</div>
|
||||||
lang={true}
|
<div>
|
||||||
type={'password'}
|
<FormGroup
|
||||||
|
label={'New Password'}
|
||||||
|
labelInfo={'(again):'}
|
||||||
intent={
|
intent={
|
||||||
errors.confirm_password &&
|
formik.errors.confirm_password &&
|
||||||
touched.confirm_password &&
|
formik.touched.confirm_password &&
|
||||||
Intent.DANGER
|
Intent.DANGER
|
||||||
}
|
}
|
||||||
{...getFieldProps('confirm_password')}
|
helperText={<ErrorMessage name={'confirm_password'} {...formik} />}
|
||||||
/>
|
>
|
||||||
</FormGroup>
|
<InputGroup
|
||||||
|
lang={true}
|
||||||
|
type={'password'}
|
||||||
|
intent={
|
||||||
|
formik.errors.confirm_password &&
|
||||||
|
formik.touched.confirm_password &&
|
||||||
|
Intent.DANGER
|
||||||
|
}
|
||||||
|
{...formik.getFieldProps('confirm_password')}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class='form__floating-footer'>
|
<div class='submit-np-form__floating-footer-section'>
|
||||||
<Button intent={Intent.PRIMARY} type='submit'>
|
<Button className={'btn-new'} intent={Intent.PRIMARY} type='submit'>
|
||||||
Reset Password
|
Submit
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
<Copyright />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(SendResetPasswordConnect)(ResetPassword);
|
export default compose(ResetPasswordConnect)(ResetPassword);
|
||||||
|
|||||||
@@ -1,29 +1,114 @@
|
|||||||
import * as React from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import * as Yup from 'yup';
|
||||||
import { Button, InputGroup } from '@blueprintjs/core';
|
import { useFormik } from 'formik';
|
||||||
|
import { useIntl } from 'react-intl';
|
||||||
|
import { Link, useHistory } from 'react-router-dom';
|
||||||
|
import { Button, InputGroup, Intent, FormGroup } from '@blueprintjs/core';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
import ErrorMessage from 'components/ErrorMessage';
|
||||||
|
import Icon from 'components/Icon';
|
||||||
|
import Copyright from './copyright';
|
||||||
|
import SendResetPasswordConnect from 'connectors/SendResetPassword.connect';
|
||||||
|
import { compose } from 'utils';
|
||||||
|
import AppToaster from 'components/AppToaster';
|
||||||
|
|
||||||
export default function SendResetPassword() {
|
function SendResetPassword({ requestSendResetPassword }) {
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const phoneRegExp = /^((\\+[1-9]{1,4}[ \\-]*)|(\\([0-9]{2,3}\\)[ \\-]*)|([0-9]{2,4})[ \\-]*)*?[0-9]{3,4}?[ \\-]*[0-9]{3,4}?$/;
|
||||||
|
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
|
// Validation schema.
|
||||||
|
|
||||||
|
const ValidationSchema = Yup.object().shape({
|
||||||
|
crediential: Yup.string('')
|
||||||
|
.required(intl.formatMessage({ id: 'required' }))
|
||||||
|
.email(intl.formatMessage({ id: 'invalid_email_or_phone_numner' })),
|
||||||
|
});
|
||||||
|
|
||||||
|
const initialValues = useMemo(
|
||||||
|
() => ({
|
||||||
|
crediential: '',
|
||||||
|
}),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Formik validation
|
||||||
|
const formik = useFormik({
|
||||||
|
enableReinitialize: true,
|
||||||
|
validationSchema: ValidationSchema,
|
||||||
|
initialValues: {
|
||||||
|
...initialValues,
|
||||||
|
},
|
||||||
|
onSubmit: (values, { setSubmitting }) => {
|
||||||
|
requestSendResetPassword(values.crediential)
|
||||||
|
.then((response) => {
|
||||||
|
AppToaster.show({
|
||||||
|
message:
|
||||||
|
'Check your email for a link to reset your password. If it doesn’t appear within a few minutes, check your spam folder.',
|
||||||
|
});
|
||||||
|
history.push('/auth/login');
|
||||||
|
setSubmitting(false);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setSubmitting(false);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
return (
|
return (
|
||||||
<div class='login-page'>
|
<div class='reset-form'>
|
||||||
<form>
|
<Icon
|
||||||
<InputGroup
|
className={'reset-form__icon-section'}
|
||||||
leftIcon='user'
|
icon='bigcapital'
|
||||||
placeholder={<FormattedMessage id='email_or_phone_number' />}
|
iconSize={150}
|
||||||
large={true}
|
/>
|
||||||
className='input-group--email'
|
<form onSubmit={formik.handleSubmit}>
|
||||||
/>
|
<div className={'reset-form__label-section'}>
|
||||||
|
<h3>You Can't login ?</h3>
|
||||||
<Button fill={true} large={true}>
|
<p>We'll send a recovery link to your email</p>
|
||||||
<FormattedMessage id='send_reset_password' />
|
</div>
|
||||||
</Button>
|
<div>
|
||||||
|
<FormGroup
|
||||||
|
label={'Email or Phone Number'}
|
||||||
|
intent={
|
||||||
|
formik.errors.crediential &&
|
||||||
|
formik.touched.crediential &&
|
||||||
|
Intent.DANGER
|
||||||
|
}
|
||||||
|
helperText={<ErrorMessage name={'crediential'} {...formik} />}
|
||||||
|
>
|
||||||
|
<InputGroup
|
||||||
|
intent={
|
||||||
|
formik.errors.crediential &&
|
||||||
|
formik.touched.crediential &&
|
||||||
|
Intent.DANGER
|
||||||
|
}
|
||||||
|
large={true}
|
||||||
|
{...formik.getFieldProps('crediential')}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</div>
|
||||||
|
<div className={'reset-form__floating-section'}>
|
||||||
|
<Button
|
||||||
|
className={'btn-send'}
|
||||||
|
type={'submit'}
|
||||||
|
intent={Intent.PRIMARY}
|
||||||
|
fill={true}
|
||||||
|
>
|
||||||
|
{intl.formatMessage({ id: 'Send Reset Password Mail' })}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class='authentication-page__footer'>
|
<div class='reset-form__footer-section'>
|
||||||
<Link to='/auth/login'>
|
<Link to='/auth/login'>
|
||||||
<FormattedMessage id='login' />
|
<FormattedMessage id='Return to log in' />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
<Copyright />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default compose(SendResetPasswordConnect)(SendResetPassword);
|
||||||
|
|||||||
79
client/src/containers/Authentication/copyright.js
Normal file
79
client/src/containers/Authentication/copyright.js
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Row, Col } from 'react-grid-system';
|
||||||
|
|
||||||
|
function Copyright() {
|
||||||
|
return (
|
||||||
|
<Row className={'copyright-page'}>
|
||||||
|
<Col md={12}>
|
||||||
|
<svg
|
||||||
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
|
width='180'
|
||||||
|
height='18'
|
||||||
|
viewBox='0 0 195 18'
|
||||||
|
>
|
||||||
|
<text
|
||||||
|
data-name='© 2001–2020 All Rights Reserved. '
|
||||||
|
transform='translate(0 13)'
|
||||||
|
fill='#666'
|
||||||
|
font-size='13'
|
||||||
|
font-family='SegoeUI, Segoe UI'
|
||||||
|
>
|
||||||
|
<tspan x='0' y='2'>
|
||||||
|
© 2001–2020 All Rights Reserved.
|
||||||
|
</tspan>
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
</Col>
|
||||||
|
<Col md={12}>
|
||||||
|
<svg
|
||||||
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
|
width='121'
|
||||||
|
height='20'
|
||||||
|
viewBox='0 0 121.499 26'
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
id='Component_2_5'
|
||||||
|
data-name='Component 2 – 5'
|
||||||
|
transform='translate(29.499 3)'
|
||||||
|
>
|
||||||
|
<text
|
||||||
|
id='Bigcapital.'
|
||||||
|
transform='translate(0 18)'
|
||||||
|
fill='#a3a3a3'
|
||||||
|
font-size='18'
|
||||||
|
font-family='SegoeUI-Bold, Segoe UI'
|
||||||
|
font-weight='700'
|
||||||
|
// letter-spacing='-0.005em'
|
||||||
|
line-height='14'
|
||||||
|
>
|
||||||
|
<tspan x='0' y='0'>
|
||||||
|
Bigcapital
|
||||||
|
</tspan>
|
||||||
|
<tspan y='0' font-size='14'>
|
||||||
|
.
|
||||||
|
</tspan>
|
||||||
|
</text>
|
||||||
|
</g>
|
||||||
|
<rect
|
||||||
|
id='Rectangle_107'
|
||||||
|
data-name='Rectangle 107'
|
||||||
|
width='2.919'
|
||||||
|
height='16.053'
|
||||||
|
transform='translate(21.566 10.444) rotate(45)'
|
||||||
|
fill='#a3a3a3'
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id='Rectangle_108'
|
||||||
|
data-name='Rectangle 108'
|
||||||
|
width='2.919'
|
||||||
|
height='16.053'
|
||||||
|
transform='translate(11.351 11.903) rotate(45)'
|
||||||
|
fill='#a3a3a3'
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Copyright;
|
||||||
@@ -4,34 +4,49 @@ import t from 'store/types';
|
|||||||
export default function login({ form }) {
|
export default function login({ form }) {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
ApiService.post('auth/login', form).then(response => {
|
ApiService.post('auth/login', form)
|
||||||
const { data } = response;
|
.then((response) => {
|
||||||
|
const { data } = response;
|
||||||
|
|
||||||
dispatch({ type: t.LOGIN_CLEAR_ERRORS });
|
dispatch({ type: t.LOGIN_CLEAR_ERRORS });
|
||||||
if (data.token && data.user) {
|
if (data.token && data.user) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: t.LOGIN_SUCCESS,
|
type: t.LOGIN_SUCCESS,
|
||||||
payload: {
|
payload: {
|
||||||
user: data.user,
|
user: data.user,
|
||||||
token: data.token,
|
token: data.token,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
resolve(response);
|
resolve(response);
|
||||||
}).catch((error) => {
|
})
|
||||||
const { response } = error;
|
.catch((error) => {
|
||||||
const { data } = response;
|
const { response } = error;
|
||||||
const { errors } = data;
|
const { data } = response;
|
||||||
|
const { errors } = data;
|
||||||
|
|
||||||
dispatch({type: t.LOGIN_CLEAR_ERRORS});
|
dispatch({ type: t.LOGIN_CLEAR_ERRORS });
|
||||||
|
|
||||||
if (errors){
|
if (errors) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: t.LOGIN_FAILURE, errors,
|
type: t.LOGIN_FAILURE,
|
||||||
});
|
errors,
|
||||||
}
|
});
|
||||||
reject(error);
|
}
|
||||||
});
|
reject(error);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const submitResetPassword = (password) => {
|
||||||
|
return (dispatch) => {
|
||||||
|
return ApiService.post('auth/reset_password', password);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const submitSendResetPassword = (email) => {
|
||||||
|
return (dispatch) => {
|
||||||
|
return ApiService.post('auth/send_reset_password', email);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
|
@import './normalize.scss';
|
||||||
|
|
||||||
@import "./normalize.scss";
|
$pt-popover-box-shadow: 0 0 0 1px rgba(16, 22, 26, 0.02),
|
||||||
|
0 2px 4px rgba(16, 22, 26, 0.1), 0 8px 24px rgba(16, 22, 26, 0.1);
|
||||||
|
|
||||||
$pt-popover-box-shadow: 0 0 0 1px rgba(16, 22, 26, 0.02), 0 2px 4px rgba(16, 22, 26, 0.1), 0 8px 24px rgba(16, 22, 26, 0.1);
|
@import '@blueprintjs/core/src/common/_variables.scss';
|
||||||
|
|
||||||
@import "@blueprintjs/core/src/common/_variables.scss";
|
|
||||||
// @import "@blueprintjs/core/src/common/colors.scss";
|
// @import "@blueprintjs/core/src/common/colors.scss";
|
||||||
|
|
||||||
$menu-item-color-hover: $light-gray4;
|
$menu-item-color-hover: $light-gray4;
|
||||||
@@ -12,52 +12,62 @@ $menu-item-color-active: $light-gray3;
|
|||||||
$breadcrumbs-collapsed-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#6B8193' enable-background='new 0 0 16 16' xml:space='preserve'><g><circle cx='2' cy='8.03' r='2'/><circle cx='14' cy='8.03' r='2'/><circle cx='8' cy='8.03' r='2'/></g></svg>");
|
$breadcrumbs-collapsed-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#6B8193' enable-background='new 0 0 16 16' xml:space='preserve'><g><circle cx='2' cy='8.03' r='2'/><circle cx='14' cy='8.03' r='2'/><circle cx='8' cy='8.03' r='2'/></g></svg>");
|
||||||
|
|
||||||
// Blueprint framework.
|
// Blueprint framework.
|
||||||
@import "@blueprintjs/core/src/blueprint.scss";
|
@import '@blueprintjs/core/src/blueprint.scss';
|
||||||
@import "@blueprintjs/datetime/src/blueprint-datetime.scss";
|
@import '@blueprintjs/datetime/src/blueprint-datetime.scss';
|
||||||
|
|
||||||
@import "basscss";
|
@import 'basscss';
|
||||||
|
|
||||||
$pt-font-family: Noto Sans, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Open Sans, Helvetica Neue, Icons16, sans-serif;
|
$pt-font-family: Noto Sans, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto,
|
||||||
|
Oxygen, Ubuntu, Cantarell, Open Sans, Helvetica Neue, Icons16, sans-serif;
|
||||||
|
|
||||||
@import "functions";
|
@import 'functions';
|
||||||
|
|
||||||
// Objects
|
// Objects
|
||||||
@import "objects/form";
|
@import 'objects/form';
|
||||||
@import "objects/typography";
|
@import 'objects/typography';
|
||||||
@import "objects/buttons";
|
@import 'objects/buttons';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
@import "components/data-table";
|
@import 'components/data-table';
|
||||||
@import "components/dialog";
|
@import 'components/dialog';
|
||||||
|
|
||||||
// Pages
|
|
||||||
@import "pages/dashboard";
|
|
||||||
@import "pages/accounts-chart";
|
|
||||||
@import "pages/authentication";
|
|
||||||
@import "pages/expense-form";
|
|
||||||
@import "pages/financial-statements";
|
|
||||||
@import "pages/make-journal-entries";
|
|
||||||
@import "pages/preferences";
|
|
||||||
@import "pages/view-form";
|
|
||||||
@import "pages/manual-journals";
|
|
||||||
@import "pages/item-category";
|
|
||||||
@import "pages/items";
|
|
||||||
@import "pages/currency";
|
|
||||||
// Views
|
|
||||||
@import "views/filter-dropdown";
|
|
||||||
@import "views/sidebar";
|
|
||||||
|
|
||||||
.#{$ns}-tooltip{
|
// Pages
|
||||||
|
@import 'pages/dashboard';
|
||||||
|
@import 'pages/accounts-chart';
|
||||||
|
@import 'pages/authentication';
|
||||||
|
@import 'pages/expense-form';
|
||||||
|
@import 'pages/financial-statements';
|
||||||
|
@import 'pages/make-journal-entries';
|
||||||
|
@import 'pages/preferences';
|
||||||
|
@import 'pages/view-form';
|
||||||
|
@import 'pages/manual-journals';
|
||||||
|
@import 'pages/item-category';
|
||||||
|
@import 'pages/items';
|
||||||
|
@import 'pages/currency';
|
||||||
|
// Views
|
||||||
|
@import 'views/filter-dropdown';
|
||||||
|
@import 'views/sidebar';
|
||||||
|
|
||||||
|
.#{$ns}-tooltip {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[data-icon='bigcapital'] {
|
[data-icon='bigcapital'] {
|
||||||
path{
|
path {
|
||||||
fill: #004dd0;
|
fill: #004dd0;
|
||||||
}
|
}
|
||||||
.path-1,
|
.path-1,
|
||||||
.path-13{
|
.path-13 {
|
||||||
fill: #2d95fd;
|
fill: #2d95fd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.App {
|
||||||
|
background-color: #fcfdff;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
// flex-direction: column;
|
||||||
|
// align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
// font-size: calc(10px + 2vmin);
|
||||||
|
// color: white;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,26 +1,266 @@
|
|||||||
|
.authentication-page {
|
||||||
|
&__form-wrapper {
|
||||||
.authentication-page{
|
|
||||||
&__form-wrapper{
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 350px;
|
max-width: 450px;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-page{
|
// Login Form
|
||||||
|
.login-form {
|
||||||
|
width: 385px;
|
||||||
|
|
||||||
.input-group{
|
&__icon-section {
|
||||||
&--email-phone-number{
|
margin: 0 auto;
|
||||||
margin-bottom: 1rem;
|
}
|
||||||
|
|
||||||
|
&__label-section {
|
||||||
|
h3 {
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 14px;
|
||||||
}
|
}
|
||||||
&--password{
|
a {
|
||||||
margin-bottom: 1rem;
|
text-decoration: underline;
|
||||||
|
color: #0040bd;
|
||||||
|
}
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
.bp3-form-group {
|
||||||
|
.bp3-form-content {
|
||||||
|
width: 384px;
|
||||||
|
min-height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.bp3-icon-eye-open {
|
||||||
|
display: inline-block;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
vertical-align: text-bottom;
|
||||||
|
margin: 0px 5px 0px 265px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__checkbox-section {
|
||||||
|
margin: -10px 0 30px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__floating-footer-section {
|
||||||
|
margin: 0px 0px 24px 0px;
|
||||||
|
|
||||||
|
.btn-login {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: #0052cc;
|
||||||
|
min-height: 45px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&__footer{
|
|
||||||
margin-top: 1rem;
|
//Register Form
|
||||||
text-align: center;
|
|
||||||
|
.register-form {
|
||||||
|
width: 384px;
|
||||||
|
|
||||||
|
&__icon-section {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label-section {
|
||||||
|
h3 {
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
margin-bottom: 35px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: #0040bd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.bp3-input {
|
||||||
|
min-height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__statement-section {
|
||||||
|
margin-top: -10px;
|
||||||
|
p {
|
||||||
|
font-size: 13px;
|
||||||
|
margin-top: -10px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
line-height: 25px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.bp3-icon-eye-open {
|
||||||
|
display: inline-block;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
vertical-align: text-bottom;
|
||||||
|
margin: 0px 5px 0px 265px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__floating-footer-section {
|
||||||
|
margin: 25px 0px 25px 0px;
|
||||||
|
|
||||||
|
.btn-register {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: #0052cc;
|
||||||
|
min-height: 45px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// Send Reset Form
|
||||||
|
|
||||||
|
.reset-form {
|
||||||
|
width: 385px;
|
||||||
|
&__icon-section {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label-section {
|
||||||
|
h3 {
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__footer-section {
|
||||||
|
padding: 14px 16px;
|
||||||
|
border-top: 1px solid #ececec;
|
||||||
|
margin: 0px 0px 25px auto;
|
||||||
|
border-bottom: 1px solid #ececec;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #0040bd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__floating-section {
|
||||||
|
margin: 30px 0px 25px auto;
|
||||||
|
|
||||||
|
.btn-send {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: #0052cc;
|
||||||
|
min-height: 45px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset New Password Form
|
||||||
|
|
||||||
|
.submit-np-form {
|
||||||
|
width: 384px;
|
||||||
|
|
||||||
|
&__icon-section {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
&__label-section {
|
||||||
|
h3 {
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: #0040bd;
|
||||||
|
}
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bp3-input {
|
||||||
|
min-height: 40px;
|
||||||
|
}
|
||||||
|
&__floating-footer-section {
|
||||||
|
margin: 20px 0px 30px auto;
|
||||||
|
|
||||||
|
.btn-new {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: #0052cc;
|
||||||
|
min-height: 45px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invite Accept Form
|
||||||
|
|
||||||
|
.invite-form {
|
||||||
|
width: 384px;
|
||||||
|
|
||||||
|
&__icon-section {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
&__label-section {
|
||||||
|
h3 {
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
.bp3-input {
|
||||||
|
min-height: 40px;
|
||||||
|
}
|
||||||
|
.bp3-icon-eye-open {
|
||||||
|
display: inline-block;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
vertical-align: text-bottom;
|
||||||
|
margin: 0px 5px 0px 265px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__statement-section {
|
||||||
|
margin-top: -10px;
|
||||||
|
p {
|
||||||
|
font-size: 13px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
line-height: 25px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__floating-footer {
|
||||||
|
margin: 20px 0px 20px auto;
|
||||||
|
|
||||||
|
.btn-invite {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: #0052cc;
|
||||||
|
min-height: 45px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bp3-icon-bigcapital {
|
||||||
|
display: inline-block;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
vertical-align: text-bottom;
|
||||||
|
margin-left: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copyright Page
|
||||||
|
.copyright-page {
|
||||||
|
text-align: center;
|
||||||
|
line-height: 14px;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user