mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-23 16:19:49 +00:00
feat(webapp): style tweaks to authentication pages
This commit is contained in:
@@ -13,7 +13,7 @@ import AppIntlLoader from './AppIntlLoader';
|
|||||||
import PrivateRoute from '@/components/Guards/PrivateRoute';
|
import PrivateRoute from '@/components/Guards/PrivateRoute';
|
||||||
import GlobalErrors from '@/containers/GlobalErrors/GlobalErrors';
|
import GlobalErrors from '@/containers/GlobalErrors/GlobalErrors';
|
||||||
import DashboardPrivatePages from '@/components/Dashboard/PrivatePages';
|
import DashboardPrivatePages from '@/components/Dashboard/PrivatePages';
|
||||||
import Authentication from '@/components/Authentication';
|
import { Authentication } from '@/containers/Authentication/Authentication';
|
||||||
|
|
||||||
import { SplashScreen, DashboardThemeProvider } from '../components';
|
import { SplashScreen, DashboardThemeProvider } from '../components';
|
||||||
import { queryConfig } from '../hooks/query/base';
|
import { queryConfig } from '../hooks/query/base';
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
// @ts-nocheck
|
|
||||||
import React from 'react';
|
|
||||||
import { Redirect, Route, Switch, Link, useLocation } from 'react-router-dom';
|
|
||||||
import BodyClassName from 'react-body-classname';
|
|
||||||
import { TransitionGroup, CSSTransition } from 'react-transition-group';
|
|
||||||
import authenticationRoutes from '@/routes/authentication';
|
|
||||||
import { Icon, FormattedMessage as T } from '@/components';
|
|
||||||
import { useIsAuthenticated } from '@/hooks/state';
|
|
||||||
import '@/style/pages/Authentication/Auth.scss';
|
|
||||||
|
|
||||||
function PageFade(props) {
|
|
||||||
return <CSSTransition {...props} classNames="authTransition" timeout={500} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function AuthenticationWrapper({ ...rest }) {
|
|
||||||
const to = { pathname: '/' };
|
|
||||||
const location = useLocation();
|
|
||||||
const isAuthenticated = useIsAuthenticated();
|
|
||||||
const locationKey = location.pathname;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{isAuthenticated ? (
|
|
||||||
<Redirect to={to} />
|
|
||||||
) : (
|
|
||||||
<BodyClassName className={'authentication'}>
|
|
||||||
<div class="authentication-page">
|
|
||||||
<a
|
|
||||||
href={'http://bigcapital.ly'}
|
|
||||||
className={'authentication-page__goto-bigcapital'}
|
|
||||||
>
|
|
||||||
<T id={'go_to_bigcapital_com'} />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<div class="authentication-page__form-wrapper">
|
|
||||||
<div class="authentication-insider">
|
|
||||||
<div className={'authentication-insider__logo-section'}>
|
|
||||||
<Icon icon="bigcapital" height={37} width={214} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<TransitionGroup>
|
|
||||||
<PageFade key={locationKey}>
|
|
||||||
<Switch>
|
|
||||||
{authenticationRoutes.map((route, index) => (
|
|
||||||
<Route
|
|
||||||
key={index}
|
|
||||||
path={route.path}
|
|
||||||
exact={route.exact}
|
|
||||||
component={route.component}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</Switch>
|
|
||||||
</PageFade>
|
|
||||||
</TransitionGroup>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</BodyClassName>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,20 +1,7 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import moment from 'moment';
|
|
||||||
import intl from 'react-intl-universal';
|
|
||||||
import { Icon } from '@/components/Icon';
|
import { Icon } from '@/components/Icon';
|
||||||
|
|
||||||
export default function AuthCopyright() {
|
export default function AuthCopyright() {
|
||||||
return (
|
return <Icon width={122} height={22} icon={'bigcapital'} />;
|
||||||
<div class="auth-copyright">
|
|
||||||
<div class="auth-copyright__text">
|
|
||||||
{intl.get('all_rights_reserved', {
|
|
||||||
pre: moment().subtract(1, 'years').year(),
|
|
||||||
current: moment().get('year'),
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Icon width={122} height={22} icon={'bigcapital'} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
import AuthCopyright from './AuthCopyright';
|
import AuthCopyright from './AuthCopyright';
|
||||||
|
import { AuthInsiderContent, AuthInsiderCopyright } from './_components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authentication insider page.
|
* Authentication insider page.
|
||||||
@@ -9,16 +11,21 @@ export default function AuthInsider({
|
|||||||
logo = true,
|
logo = true,
|
||||||
copyright = true,
|
copyright = true,
|
||||||
children,
|
children,
|
||||||
|
classNames,
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div class="authentication-insider__content">
|
<AuthInsiderContent>
|
||||||
<div class="authentication-insider__form">
|
<AuthInsiderContentWrap className={classNames?.content}>
|
||||||
{ children }
|
{children}
|
||||||
</div>
|
</AuthInsiderContentWrap>
|
||||||
|
|
||||||
<div class="authentication-insider__footer">
|
{copyright && (
|
||||||
|
<AuthInsiderCopyright className={classNames?.copyrightWrap}>
|
||||||
<AuthCopyright />
|
<AuthCopyright />
|
||||||
</div>
|
</AuthInsiderCopyright>
|
||||||
</div>
|
)}
|
||||||
|
</AuthInsiderContent>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AuthInsiderContentWrap = styled.div``;
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
|
import { Redirect, Route, Switch, useLocation } from 'react-router-dom';
|
||||||
|
import BodyClassName from 'react-body-classname';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { TransitionGroup, CSSTransition } from 'react-transition-group';
|
||||||
|
|
||||||
|
import authenticationRoutes from '@/routes/authentication';
|
||||||
|
import { Icon, FormattedMessage as T } from '@/components';
|
||||||
|
import { useIsAuthenticated } from '@/hooks/state';
|
||||||
|
|
||||||
|
import '@/style/pages/Authentication/Auth.scss';
|
||||||
|
|
||||||
|
export function Authentication() {
|
||||||
|
const to = { pathname: '/' };
|
||||||
|
const location = useLocation();
|
||||||
|
const isAuthenticated = useIsAuthenticated();
|
||||||
|
const locationKey = location.pathname;
|
||||||
|
|
||||||
|
if (isAuthenticated) {
|
||||||
|
return <Redirect to={to} />;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<BodyClassName className={'authentication'}>
|
||||||
|
<AuthPage>
|
||||||
|
<AuthInsider>
|
||||||
|
<AuthLogo>
|
||||||
|
<Icon icon="bigcapital" height={37} width={214} />
|
||||||
|
</AuthLogo>
|
||||||
|
|
||||||
|
<TransitionGroup>
|
||||||
|
<CSSTransition
|
||||||
|
timeout={500}
|
||||||
|
key={locationKey}
|
||||||
|
classNames="authTransition"
|
||||||
|
>
|
||||||
|
<Switch>
|
||||||
|
{authenticationRoutes.map((route, index) => (
|
||||||
|
<Route
|
||||||
|
key={index}
|
||||||
|
path={route.path}
|
||||||
|
exact={route.exact}
|
||||||
|
component={route.component}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Switch>
|
||||||
|
</CSSTransition>
|
||||||
|
</TransitionGroup>
|
||||||
|
</AuthInsider>
|
||||||
|
</AuthPage>
|
||||||
|
</BodyClassName>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const AuthPage = styled.div``;
|
||||||
|
const AuthInsider = styled.div`
|
||||||
|
width: 384px;
|
||||||
|
margin: 0 auto;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
padding-top: 80px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const AuthLogo = styled.div`
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
`;
|
||||||
@@ -11,6 +11,7 @@ import { useInviteAcceptContext } from './InviteAcceptProvider';
|
|||||||
import { AppToaster } from '@/components';
|
import { AppToaster } from '@/components';
|
||||||
import { InviteAcceptSchema } from './utils';
|
import { InviteAcceptSchema } from './utils';
|
||||||
import InviteAcceptFormContent from './InviteAcceptFormContent';
|
import InviteAcceptFormContent from './InviteAcceptFormContent';
|
||||||
|
import { AuthInsiderCard } from './_components';
|
||||||
|
|
||||||
export default function InviteAcceptForm() {
|
export default function InviteAcceptForm() {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@@ -80,23 +81,13 @@ export default function InviteAcceptForm() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'invite-form'}>
|
<AuthInsiderCard>
|
||||||
<div className={'authentication-page__label-section'}>
|
|
||||||
<h3>
|
|
||||||
<T id={'welcome_to_bigcapital'} />
|
|
||||||
</h3>
|
|
||||||
<p>
|
|
||||||
<T id={'enter_your_personal_information'} />{' '}
|
|
||||||
<b>{inviteValue.organization_name}</b> <T id={'organization'} />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Formik
|
<Formik
|
||||||
validationSchema={InviteAcceptSchema}
|
validationSchema={InviteAcceptSchema}
|
||||||
initialValues={inviteValue}
|
initialValues={inviteValue}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
component={InviteAcceptFormContent}
|
component={InviteAcceptFormContent}
|
||||||
/>
|
/>
|
||||||
</div>
|
</AuthInsiderCard>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import { Button, InputGroup, Intent, FormGroup } from '@blueprintjs/core';
|
import { InputGroup, Intent } from '@blueprintjs/core';
|
||||||
import { Form, ErrorMessage, FastField, useFormikContext } from 'formik';
|
import { Form, useFormikContext } from 'formik';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Col, Row, FormattedMessage as T } from '@/components';
|
|
||||||
import { inputIntent } from '@/utils';
|
import { Col, FFormGroup, Row, FormattedMessage as T } from '@/components';
|
||||||
import { useInviteAcceptContext } from './InviteAcceptProvider';
|
import { useInviteAcceptContext } from './InviteAcceptProvider';
|
||||||
import { PasswordRevealer } from './components';
|
import { PasswordRevealer } from './components';
|
||||||
|
import { AuthSubmitButton } from './_components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invite user form.
|
* Invite user form.
|
||||||
@@ -34,75 +35,25 @@ export default function InviteUserFormContent() {
|
|||||||
<Form>
|
<Form>
|
||||||
<Row>
|
<Row>
|
||||||
<Col md={6}>
|
<Col md={6}>
|
||||||
<FastField name={'first_name'}>
|
<FFormGroup name={'first_name'} label={<T id={'first_name'} />}>
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
<InputGroup name={'first_name'} />
|
||||||
<FormGroup
|
</FFormGroup>
|
||||||
label={<T id={'first_name'} />}
|
|
||||||
className={'form-group--first_name'}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name={'first_name'} />}
|
|
||||||
>
|
|
||||||
<InputGroup
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col md={6}>
|
<Col md={6}>
|
||||||
<FastField name={'last_name'}>
|
<FFormGroup name={'last_name'} label={<T id={'last_name'} />}>
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
<InputGroup name={'last_name'} />
|
||||||
<FormGroup
|
</FFormGroup>
|
||||||
label={<T id={'last_name'} />}
|
|
||||||
className={'form-group--last_name'}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name={'last_name'} />}
|
|
||||||
>
|
|
||||||
<InputGroup
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<FastField name={'phone_number'}>
|
<FFormGroup
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
name={'password'}
|
||||||
<FormGroup
|
|
||||||
label={<T id={'phone_number'} />}
|
|
||||||
className={'form-group--phone_number'}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name={'phone_number'} />}
|
|
||||||
>
|
|
||||||
<InputGroup intent={inputIntent({ error, touched })} {...field} />
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
|
|
||||||
<FastField name={'password'}>
|
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
|
||||||
<FormGroup
|
|
||||||
label={<T id={'password'} />}
|
label={<T id={'password'} />}
|
||||||
labelInfo={
|
labelInfo={<PasswordRevealer onChange={handlePasswordRevealerChange} />}
|
||||||
<PasswordRevealer onChange={handlePasswordRevealerChange} />
|
|
||||||
}
|
|
||||||
className={'form-group--password has-password-revealer'}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name={'password'} />}
|
|
||||||
>
|
>
|
||||||
<InputGroup
|
<InputGroup name={'password'} />
|
||||||
lang={true}
|
</FFormGroup>
|
||||||
type={passwordType}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
|
|
||||||
<div className={'invite-form__statement-section'}>
|
<div className={'invite-form__statement-section'}>
|
||||||
<p>
|
<p>
|
||||||
@@ -117,16 +68,14 @@ export default function InviteUserFormContent() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={'authentication-page__submit-button-wrap'}>
|
<AuthSubmitButton
|
||||||
<Button
|
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
type="submit"
|
type="submit"
|
||||||
fill={true}
|
fill={true}
|
||||||
loading={isSubmitting}
|
loading={isSubmitting}
|
||||||
>
|
>
|
||||||
<T id={'create_account'} />
|
<T id={'create_account'} />
|
||||||
</Button>
|
</AuthSubmitButton>
|
||||||
</div>
|
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,25 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { Formik } from 'formik';
|
import { Formik } from 'formik';
|
||||||
import { AppToaster as Toaster, FormattedMessage as T } from '@/components';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { AppToaster as Toaster, FormattedMessage as T } from '@/components';
|
||||||
import AuthInsider from '@/containers/Authentication/AuthInsider';
|
import AuthInsider from '@/containers/Authentication/AuthInsider';
|
||||||
import { useAuthLogin } from '@/hooks/query';
|
import { useAuthLogin } from '@/hooks/query';
|
||||||
|
|
||||||
import LoginForm from './LoginForm';
|
import LoginForm from './LoginForm';
|
||||||
import { LoginSchema, transformLoginErrorsToToasts } from './utils';
|
import { LoginSchema, transformLoginErrorsToToasts } from './utils';
|
||||||
|
import {
|
||||||
|
AuthFooterLinks,
|
||||||
|
AuthFooterLink,
|
||||||
|
AuthInsiderCard,
|
||||||
|
} from './_components';
|
||||||
|
|
||||||
|
const initialValues = {
|
||||||
|
crediential: '',
|
||||||
|
password: '',
|
||||||
|
keepLoggedIn: false
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Login page.
|
* Login page.
|
||||||
@@ -38,34 +49,32 @@ export default function Login() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<AuthInsider>
|
<AuthInsider>
|
||||||
<div className="login-form">
|
<AuthInsiderCard>
|
||||||
<div className={'authentication-page__label-section'}>
|
|
||||||
<h3>
|
|
||||||
<T id={'log_in'} />
|
|
||||||
</h3>
|
|
||||||
{/* <T id={'need_bigcapital_account'} />
|
|
||||||
<Link to="/auth/register">
|
|
||||||
{' '}
|
|
||||||
<T id={'create_an_account'} />
|
|
||||||
</Link> */}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={{
|
initialValues={initialValues}
|
||||||
crediential: '',
|
|
||||||
password: '',
|
|
||||||
}}
|
|
||||||
validationSchema={LoginSchema}
|
validationSchema={LoginSchema}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
component={LoginForm}
|
component={LoginForm}
|
||||||
/>
|
/>
|
||||||
|
</AuthInsiderCard>
|
||||||
|
|
||||||
<div class="authentication-page__footer-links">
|
<LoginFooterLinks />
|
||||||
<Link to={'/auth/send_reset_password'}>
|
|
||||||
<T id={'forget_my_password'} />
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</AuthInsider>
|
</AuthInsider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function LoginFooterLinks() {
|
||||||
|
return (
|
||||||
|
<AuthFooterLinks>
|
||||||
|
<AuthFooterLink>
|
||||||
|
Don't have an account? <Link to={'/auth/register'}>Sign up</Link>
|
||||||
|
</AuthFooterLink>
|
||||||
|
|
||||||
|
<AuthFooterLink>
|
||||||
|
<Link to={'/auth/send_reset_password'}>
|
||||||
|
<T id={'forget_my_password'} />
|
||||||
|
</Link>
|
||||||
|
</AuthFooterLink>
|
||||||
|
</AuthFooterLinks>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,89 +1,63 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import {
|
import { Button, Intent } from '@blueprintjs/core';
|
||||||
Button,
|
import { Form } from 'formik';
|
||||||
InputGroup,
|
import { Tooltip2 } from '@blueprintjs/popover2';
|
||||||
Intent,
|
|
||||||
FormGroup,
|
import { FFormGroup, FInputGroup, FCheckbox, T } from '@/components';
|
||||||
Checkbox,
|
import { AuthSubmitButton } from './_components';
|
||||||
} from '@blueprintjs/core';
|
|
||||||
import { Form, ErrorMessage, Field } from 'formik';
|
|
||||||
import { T } from '@/components';
|
|
||||||
import { inputIntent } from '@/utils';
|
|
||||||
import { PasswordRevealer } from './components';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Login form.
|
* Login form.
|
||||||
*/
|
*/
|
||||||
export default function LoginForm({ isSubmitting }) {
|
export default function LoginForm({ isSubmitting }) {
|
||||||
const [passwordType, setPasswordType] = React.useState('password');
|
const [showPassword, setShowPassword] = useState<boolean>(false);
|
||||||
|
|
||||||
// Handle password revealer changing.
|
// Handle password revealer changing.
|
||||||
const handlePasswordRevealerChange = React.useCallback(
|
const handleLockClick = () => {
|
||||||
(shown) => {
|
setShowPassword(!showPassword);
|
||||||
const type = shown ? 'text' : 'password';
|
};
|
||||||
setPasswordType(type);
|
|
||||||
},
|
const lockButton = (
|
||||||
[setPasswordType],
|
<Tooltip2 content={`${showPassword ? 'Hide' : 'Show'} Password`}>
|
||||||
|
<Button
|
||||||
|
icon={showPassword ? 'unlock' : 'lock'}
|
||||||
|
intent={Intent.WARNING}
|
||||||
|
minimal={true}
|
||||||
|
onClick={handleLockClick}
|
||||||
|
small={true}
|
||||||
|
/>
|
||||||
|
</Tooltip2>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form className={'authentication-page__form'}>
|
<Form>
|
||||||
<Field name={'crediential'}>
|
<FFormGroup name={'crediential'} label={<T id={'email'} />}>
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
<FInputGroup name={'crediential'} large={true} />
|
||||||
<FormGroup
|
</FFormGroup>
|
||||||
label={<T id={'email_or_phone_number'} />}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name={'crediential'} />}
|
|
||||||
className={'form-group--crediential'}
|
|
||||||
>
|
|
||||||
<InputGroup
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
large={true}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</Field>
|
|
||||||
|
|
||||||
<Field name={'password'}>
|
<FFormGroup name={'password'} label={<T id={'password'} />}>
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
<FInputGroup
|
||||||
<FormGroup
|
name={'password'}
|
||||||
label={<T id={'password'} />}
|
|
||||||
labelInfo={
|
|
||||||
<PasswordRevealer onChange={handlePasswordRevealerChange} />
|
|
||||||
}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name={'password'} />}
|
|
||||||
className={'form-group--password has-password-revealer'}
|
|
||||||
>
|
|
||||||
<InputGroup
|
|
||||||
large={true}
|
large={true}
|
||||||
intent={inputIntent({ error, touched })}
|
type={showPassword ? 'text' : 'password'}
|
||||||
type={passwordType}
|
rightElement={lockButton}
|
||||||
{...field}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FFormGroup>
|
||||||
)}
|
|
||||||
</Field>
|
|
||||||
|
|
||||||
<div className={'login-form__checkbox-section'}>
|
<FCheckbox name={'keepLoggedIn'}>
|
||||||
<Checkbox large={true} className={'checkbox--remember-me'}>
|
|
||||||
<T id={'keep_me_logged_in'} />
|
<T id={'keep_me_logged_in'} />
|
||||||
</Checkbox>
|
</FCheckbox>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={'authentication-page__submit-button-wrap'}>
|
<AuthSubmitButton
|
||||||
<Button
|
|
||||||
type={'submit'}
|
type={'submit'}
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
fill={true}
|
fill={true}
|
||||||
lang={true}
|
large={true}
|
||||||
loading={isSubmitting}
|
loading={isSubmitting}
|
||||||
>
|
>
|
||||||
<T id={'log_in'} />
|
<T id={'log_in'} />
|
||||||
</Button>
|
</AuthSubmitButton>
|
||||||
</div>
|
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,18 @@ import { useAuthLogin, useAuthRegister } from '@/hooks/query/authentication';
|
|||||||
|
|
||||||
import RegisterForm from './RegisterForm';
|
import RegisterForm from './RegisterForm';
|
||||||
import { RegisterSchema, transformRegisterErrorsToForm } from './utils';
|
import { RegisterSchema, transformRegisterErrorsToForm } from './utils';
|
||||||
|
import {
|
||||||
|
AuthFooterLinks,
|
||||||
|
AuthFooterLink,
|
||||||
|
AuthInsiderCard,
|
||||||
|
} from './_components';
|
||||||
|
|
||||||
|
const initialValues = {
|
||||||
|
first_name: '',
|
||||||
|
last_name: '',
|
||||||
|
email: '',
|
||||||
|
password: '',
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register form.
|
* Register form.
|
||||||
@@ -19,18 +31,6 @@ export default function RegisterUserForm() {
|
|||||||
const { mutateAsync: authLoginMutate } = useAuthLogin();
|
const { mutateAsync: authLoginMutate } = useAuthLogin();
|
||||||
const { mutateAsync: authRegisterMutate } = useAuthRegister();
|
const { mutateAsync: authRegisterMutate } = useAuthRegister();
|
||||||
|
|
||||||
const initialValues = useMemo(
|
|
||||||
() => ({
|
|
||||||
first_name: '',
|
|
||||||
last_name: '',
|
|
||||||
email: '',
|
|
||||||
phone_number: '',
|
|
||||||
password: '',
|
|
||||||
country: 'LY',
|
|
||||||
}),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleSubmit = (values, { setSubmitting, setErrors }) => {
|
const handleSubmit = (values, { setSubmitting, setErrors }) => {
|
||||||
authRegisterMutate(values)
|
authRegisterMutate(values)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
@@ -66,24 +66,32 @@ export default function RegisterUserForm() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<AuthInsider>
|
<AuthInsider>
|
||||||
<div className={'register-form'}>
|
<AuthInsiderCard>
|
||||||
<div className={'authentication-page__label-section'}>
|
|
||||||
<h3>
|
|
||||||
<T id={'register_a_new_organization'} />
|
|
||||||
</h3>
|
|
||||||
<T id={'you_have_a_bigcapital_account'} />
|
|
||||||
<Link to="/auth/login">
|
|
||||||
<T id={'login'} />
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
validationSchema={RegisterSchema}
|
validationSchema={RegisterSchema}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
component={RegisterForm}
|
component={RegisterForm}
|
||||||
/>
|
/>
|
||||||
</div>
|
</AuthInsiderCard>
|
||||||
|
|
||||||
|
<RegisterFooterLinks />
|
||||||
</AuthInsider>
|
</AuthInsider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function RegisterFooterLinks() {
|
||||||
|
return (
|
||||||
|
<AuthFooterLinks>
|
||||||
|
<AuthFooterLink>
|
||||||
|
Return to <Link to={'/auth/login'}>Sign In</Link>
|
||||||
|
</AuthFooterLink>
|
||||||
|
|
||||||
|
<AuthFooterLink>
|
||||||
|
<Link to={'/auth/send_reset_password'}>
|
||||||
|
<T id={'forget_my_password'} />
|
||||||
|
</Link>
|
||||||
|
</AuthFooterLink>
|
||||||
|
</AuthFooterLinks>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,148 +1,97 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { Form } from 'formik';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import {
|
import { Intent, Button } from '@blueprintjs/core';
|
||||||
Button,
|
|
||||||
InputGroup,
|
|
||||||
Intent,
|
|
||||||
FormGroup,
|
|
||||||
Spinner,
|
|
||||||
} from '@blueprintjs/core';
|
|
||||||
import { ErrorMessage, Field, Form } from 'formik';
|
|
||||||
import { FormattedMessage as T } from '@/components';
|
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Row, Col, If } from '@/components';
|
import { Tooltip2 } from '@blueprintjs/popover2';
|
||||||
import { PasswordRevealer } from './components';
|
import styled from 'styled-components';
|
||||||
import { inputIntent } from '@/utils';
|
|
||||||
|
import {
|
||||||
|
FFormGroup,
|
||||||
|
FInputGroup,
|
||||||
|
Row,
|
||||||
|
Col,
|
||||||
|
FormattedMessage as T,
|
||||||
|
} from '@/components';
|
||||||
|
import { AuthSubmitButton, AuthenticationLoadingOverlay } from './_components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register form.
|
* Register form.
|
||||||
*/
|
*/
|
||||||
export default function RegisterForm({ isSubmitting }) {
|
export default function RegisterForm({ isSubmitting }) {
|
||||||
const [passwordType, setPasswordType] = React.useState('password');
|
const [showPassword, setShowPassword] = React.useState<boolean>(false);
|
||||||
|
|
||||||
// Handle password revealer changing.
|
// Handle password revealer changing.
|
||||||
const handlePasswordRevealerChange = React.useCallback(
|
const handleLockClick = () => {
|
||||||
(shown) => {
|
setShowPassword(!showPassword);
|
||||||
const type = shown ? 'text' : 'password';
|
};
|
||||||
setPasswordType(type);
|
|
||||||
},
|
const lockButton = (
|
||||||
[setPasswordType],
|
<Tooltip2 content={`${showPassword ? 'Hide' : 'Show'} Password`}>
|
||||||
|
<Button
|
||||||
|
icon={showPassword ? 'unlock' : 'lock'}
|
||||||
|
intent={Intent.WARNING}
|
||||||
|
minimal={true}
|
||||||
|
onClick={handleLockClick}
|
||||||
|
small={true}
|
||||||
|
/>
|
||||||
|
</Tooltip2>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form className={'authentication-page__form'}>
|
<Form className={'authentication-page__form'}>
|
||||||
<Row className={'name-section'}>
|
<Row className={'name-section'}>
|
||||||
<Col md={6}>
|
<Col md={6}>
|
||||||
<Field name={'first_name'}>
|
<FFormGroup name={'first_name'} label={<T id={'first_name'} />}>
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
<FInputGroup name={'first_name'} large={true} />
|
||||||
<FormGroup
|
</FFormGroup>
|
||||||
label={<T id={'first_name'} />}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name={'first_name'} />}
|
|
||||||
className={'form-group--first-name'}
|
|
||||||
>
|
|
||||||
<InputGroup
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</Field>
|
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col md={6}>
|
<Col md={6}>
|
||||||
<Field name={'last_name'}>
|
<FFormGroup name={'last_name'} label={<T id={'last_name'} />}>
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
<FInputGroup name={'last_name'} large={true} />
|
||||||
<FormGroup
|
</FFormGroup>
|
||||||
label={<T id={'last_name'} />}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name={'last_name'} />}
|
|
||||||
className={'form-group--last-name'}
|
|
||||||
>
|
|
||||||
<InputGroup
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</Field>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Field name={'phone_number'}>
|
<FFormGroup name={'email'} label={<T id={'email'} />}>
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
<FInputGroup name={'email'} large={true} />
|
||||||
<FormGroup
|
</FFormGroup>
|
||||||
label={<T id={'phone_number'} />}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name={'phone_number'} />}
|
|
||||||
className={'form-group--phone-number'}
|
|
||||||
>
|
|
||||||
<InputGroup intent={inputIntent({ error, touched })} {...field} />
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</Field>
|
|
||||||
|
|
||||||
<Field name={'email'}>
|
<FFormGroup name={'password'} label={<T id={'password'} />}>
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
<FInputGroup
|
||||||
<FormGroup
|
name={'password'}
|
||||||
label={<T id={'email'} />}
|
type={showPassword ? 'text' : 'password'}
|
||||||
intent={inputIntent({ error, touched })}
|
rightElement={lockButton}
|
||||||
helperText={<ErrorMessage name={'email'} />}
|
large={true}
|
||||||
className={'form-group--email'}
|
|
||||||
>
|
|
||||||
<InputGroup intent={inputIntent({ error, touched })} {...field} />
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</Field>
|
|
||||||
|
|
||||||
<Field name={'password'}>
|
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
|
||||||
<FormGroup
|
|
||||||
label={<T id={'password'} />}
|
|
||||||
labelInfo={
|
|
||||||
<PasswordRevealer onChange={handlePasswordRevealerChange} />
|
|
||||||
}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name={'password'} />}
|
|
||||||
className={'form-group--password has-password-revealer'}
|
|
||||||
>
|
|
||||||
<InputGroup
|
|
||||||
lang={true}
|
|
||||||
type={passwordType}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
{...field}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FFormGroup>
|
||||||
)}
|
|
||||||
</Field>
|
|
||||||
|
|
||||||
<div className={'register-form__agreement-section'}>
|
<TermsConditionsText>
|
||||||
<p>
|
|
||||||
{intl.getHTML('signing_in_or_creating', {
|
{intl.getHTML('signing_in_or_creating', {
|
||||||
terms: (msg) => <Link>{msg}</Link>,
|
terms: (msg) => <Link>{msg}</Link>,
|
||||||
privacy: (msg) => <Link>{msg}</Link>,
|
privacy: (msg) => <Link>{msg}</Link>,
|
||||||
})}
|
})}
|
||||||
</p>
|
</TermsConditionsText>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={'authentication-page__submit-button-wrap'}>
|
<AuthSubmitButton
|
||||||
<Button
|
|
||||||
className={'btn-register'}
|
className={'btn-register'}
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
type="submit"
|
type="submit"
|
||||||
fill={true}
|
fill={true}
|
||||||
|
large={true}
|
||||||
loading={isSubmitting}
|
loading={isSubmitting}
|
||||||
>
|
>
|
||||||
<T id={'register'} />
|
<T id={'register'} />
|
||||||
</Button>
|
</AuthSubmitButton>
|
||||||
</div>
|
|
||||||
|
|
||||||
<If condition={isSubmitting}>
|
{isSubmitting && <AuthenticationLoadingOverlay />}
|
||||||
<div class="authentication-page__loading-overlay">
|
|
||||||
<Spinner size={50} />
|
|
||||||
</div>
|
|
||||||
</If>
|
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TermsConditionsText = styled.p`
|
||||||
|
opacity: 0.8;
|
||||||
|
margin-bottom: 1.4rem;
|
||||||
|
`;
|
||||||
|
|||||||
@@ -4,14 +4,23 @@ import intl from 'react-intl-universal';
|
|||||||
import { Formik } from 'formik';
|
import { Formik } from 'formik';
|
||||||
import { Intent, Position } from '@blueprintjs/core';
|
import { Intent, Position } from '@blueprintjs/core';
|
||||||
import { Link, useParams, useHistory } from 'react-router-dom';
|
import { Link, useParams, useHistory } from 'react-router-dom';
|
||||||
import { AppToaster, FormattedMessage as T } from '@/components';
|
|
||||||
|
|
||||||
|
import { AppToaster } from '@/components';
|
||||||
import { useAuthResetPassword } from '@/hooks/query';
|
import { useAuthResetPassword } from '@/hooks/query';
|
||||||
|
|
||||||
import AuthInsider from '@/containers/Authentication/AuthInsider';
|
import AuthInsider from '@/containers/Authentication/AuthInsider';
|
||||||
|
|
||||||
|
import {
|
||||||
|
AuthFooterLink,
|
||||||
|
AuthFooterLinks,
|
||||||
|
AuthInsiderCard,
|
||||||
|
} from './_components';
|
||||||
import ResetPasswordForm from './ResetPasswordForm';
|
import ResetPasswordForm from './ResetPasswordForm';
|
||||||
import { ResetPasswordSchema } from './utils';
|
import { ResetPasswordSchema } from './utils';
|
||||||
|
|
||||||
|
const initialValues = {
|
||||||
|
password: '',
|
||||||
|
confirm_password: '',
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* Reset password page.
|
* Reset password page.
|
||||||
*/
|
*/
|
||||||
@@ -22,15 +31,6 @@ export default function ResetPassword() {
|
|||||||
// Authentication reset password.
|
// Authentication reset password.
|
||||||
const { mutateAsync: authResetPasswordMutate } = useAuthResetPassword();
|
const { mutateAsync: authResetPasswordMutate } = useAuthResetPassword();
|
||||||
|
|
||||||
// Initial values of the form.
|
|
||||||
const initialValues = useMemo(
|
|
||||||
() => ({
|
|
||||||
password: '',
|
|
||||||
confirm_password: '',
|
|
||||||
}),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
// Handle the form submitting.
|
// Handle the form submitting.
|
||||||
const handleSubmit = (values, { setSubmitting }) => {
|
const handleSubmit = (values, { setSubmitting }) => {
|
||||||
authResetPasswordMutate([token, values])
|
authResetPasswordMutate([token, values])
|
||||||
@@ -64,24 +64,30 @@ export default function ResetPassword() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<AuthInsider>
|
<AuthInsider>
|
||||||
<div className={'submit-np-form'}>
|
<AuthInsiderCard>
|
||||||
<div className={'authentication-page__label-section'}>
|
|
||||||
<h3>
|
|
||||||
<T id={'choose_a_new_password'} />
|
|
||||||
</h3>
|
|
||||||
<T id={'you_remembered_your_password'} />{' '}
|
|
||||||
<Link to="/auth/login">
|
|
||||||
<T id={'login'} />
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
validationSchema={ResetPasswordSchema}
|
validationSchema={ResetPasswordSchema}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
component={ResetPasswordForm}
|
component={ResetPasswordForm}
|
||||||
/>
|
/>
|
||||||
</div>
|
</AuthInsiderCard>
|
||||||
|
|
||||||
|
<ResetPasswordFooterLinks />
|
||||||
</AuthInsider>
|
</AuthInsider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ResetPasswordFooterLinks() {
|
||||||
|
return (
|
||||||
|
<AuthFooterLinks>
|
||||||
|
<AuthFooterLink>
|
||||||
|
Don't have an account? <Link to={'/auth/register'}>Sign up</Link>
|
||||||
|
</AuthFooterLink>
|
||||||
|
|
||||||
|
<AuthFooterLink>
|
||||||
|
Return to <Link to={'/auth/login'}>Sign In</Link>
|
||||||
|
</AuthFooterLink>
|
||||||
|
</AuthFooterLinks>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Button, InputGroup, Intent, FormGroup } from '@blueprintjs/core';
|
import { Intent } from '@blueprintjs/core';
|
||||||
import { Form, ErrorMessage, FastField } from 'formik';
|
import { Form } from 'formik';
|
||||||
import { FormattedMessage as T } from '@/components';
|
import { FFormGroup, FInputGroup, FormattedMessage as T } from '@/components';
|
||||||
import { inputIntent } from '@/utils';
|
import { AuthSubmitButton } from './_components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset password form.
|
* Reset password form.
|
||||||
@@ -11,54 +11,23 @@ import { inputIntent } from '@/utils';
|
|||||||
export default function ResetPasswordForm({ isSubmitting }) {
|
export default function ResetPasswordForm({ isSubmitting }) {
|
||||||
return (
|
return (
|
||||||
<Form>
|
<Form>
|
||||||
<FastField name={'password'}>
|
<FFormGroup name={'password'} label={<T id={'new_password'} />}>
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
<FInputGroup name={'password'} type={'password'} large={true} />
|
||||||
<FormGroup
|
</FFormGroup>
|
||||||
label={<T id={'new_password'} />}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name={'password'} />}
|
|
||||||
className={'form-group--password'}
|
|
||||||
>
|
|
||||||
<InputGroup
|
|
||||||
lang={true}
|
|
||||||
type={'password'}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
|
|
||||||
<FastField name={'confirm_password'}>
|
<FFormGroup name={'confirm_password'} label={<T id={'new_password'} />}>
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
<FInputGroup name={'confirm_password'} type={'password'} large={true} />
|
||||||
<FormGroup
|
</FFormGroup>
|
||||||
label={<T id={'new_password'} />}
|
|
||||||
labelInfo={'(again):'}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name={'confirm_password'} />}
|
|
||||||
className={'form-group--confirm-password'}
|
|
||||||
>
|
|
||||||
<InputGroup
|
|
||||||
lang={true}
|
|
||||||
type={'password'}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
|
|
||||||
<div className={'authentication-page__submit-button-wrap'}>
|
<AuthSubmitButton
|
||||||
<Button
|
|
||||||
fill={true}
|
fill={true}
|
||||||
className={'btn-new'}
|
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
type="submit"
|
type="submit"
|
||||||
loading={isSubmitting}
|
loading={isSubmitting}
|
||||||
|
large={true}
|
||||||
>
|
>
|
||||||
<T id={'submit'} />
|
<T id={'submit'} />
|
||||||
</Button>
|
</AuthSubmitButton>
|
||||||
</div>
|
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,33 +5,32 @@ import { Formik } from 'formik';
|
|||||||
import { Link, useHistory } from 'react-router-dom';
|
import { Link, useHistory } from 'react-router-dom';
|
||||||
import { Intent } from '@blueprintjs/core';
|
import { Intent } from '@blueprintjs/core';
|
||||||
|
|
||||||
import { AppToaster, FormattedMessage as T } from '@/components';
|
import { AppToaster } from '@/components';
|
||||||
import { useAuthSendResetPassword } from '@/hooks/query';
|
import { useAuthSendResetPassword } from '@/hooks/query';
|
||||||
|
|
||||||
import SendResetPasswordForm from './SendResetPasswordForm';
|
import SendResetPasswordForm from './SendResetPasswordForm';
|
||||||
|
import {
|
||||||
|
AuthFooterLink,
|
||||||
|
AuthFooterLinks,
|
||||||
|
AuthInsiderCard,
|
||||||
|
} from './_components';
|
||||||
import {
|
import {
|
||||||
SendResetPasswordSchema,
|
SendResetPasswordSchema,
|
||||||
transformSendResetPassErrorsToToasts,
|
transformSendResetPassErrorsToToasts,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
|
||||||
import AuthInsider from '@/containers/Authentication/AuthInsider';
|
import AuthInsider from '@/containers/Authentication/AuthInsider';
|
||||||
|
|
||||||
|
const initialValues = {
|
||||||
|
crediential: '',
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send reset password page.
|
* Send reset password page.
|
||||||
*/
|
*/
|
||||||
export default function SendResetPassword({ requestSendResetPassword }) {
|
export default function SendResetPassword({ requestSendResetPassword }) {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
const { mutateAsync: sendResetPasswordMutate } = useAuthSendResetPassword();
|
const { mutateAsync: sendResetPasswordMutate } = useAuthSendResetPassword();
|
||||||
|
|
||||||
// Initial values.
|
|
||||||
const initialValues = useMemo(
|
|
||||||
() => ({
|
|
||||||
crediential: '',
|
|
||||||
}),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
// Handle form submitting.
|
// Handle form submitting.
|
||||||
const handleSubmit = (values, { setSubmitting }) => {
|
const handleSubmit = (values, { setSubmitting }) => {
|
||||||
sendResetPasswordMutate({ email: values.crediential })
|
sendResetPasswordMutate({ email: values.crediential })
|
||||||
@@ -61,28 +60,30 @@ export default function SendResetPassword({ requestSendResetPassword }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<AuthInsider>
|
<AuthInsider>
|
||||||
<div className="reset-form">
|
<AuthInsiderCard>
|
||||||
<div className={'authentication-page__label-section'}>
|
|
||||||
<h3>
|
|
||||||
<T id={'you_can_t_login'} />
|
|
||||||
</h3>
|
|
||||||
<p>
|
|
||||||
<T id={'we_ll_send_a_recovery_link_to_your_email'} />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
validationSchema={SendResetPasswordSchema}
|
validationSchema={SendResetPasswordSchema}
|
||||||
component={SendResetPasswordForm}
|
component={SendResetPasswordForm}
|
||||||
/>
|
/>
|
||||||
<div class="authentication-page__footer-links">
|
</AuthInsiderCard>
|
||||||
<Link to="/auth/login">
|
|
||||||
<T id={'return_to_log_in'} />
|
<SendResetPasswordFooterLinks />
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</AuthInsider>
|
</AuthInsider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function SendResetPasswordFooterLinks() {
|
||||||
|
return (
|
||||||
|
<AuthFooterLinks>
|
||||||
|
<AuthFooterLink>
|
||||||
|
Don't have an account? <Link to={'/auth/register'}>Sign up</Link>
|
||||||
|
</AuthFooterLink>
|
||||||
|
|
||||||
|
<AuthFooterLink>
|
||||||
|
Return to <Link to={'/auth/login'}>Sign In</Link>
|
||||||
|
</AuthFooterLink>
|
||||||
|
</AuthFooterLinks>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,43 +1,44 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Button, InputGroup, Intent, FormGroup } from '@blueprintjs/core';
|
import { Intent } from '@blueprintjs/core';
|
||||||
import { Form, ErrorMessage, FastField } from 'formik';
|
import { Form } from 'formik';
|
||||||
import { FormattedMessage as T } from '@/components';
|
import styled from 'styled-components';
|
||||||
import { inputIntent } from '@/utils';
|
|
||||||
|
import { FInputGroup, FFormGroup, FormattedMessage as T } from '@/components';
|
||||||
|
import { AuthSubmitButton } from './_components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send reset password form.
|
* Send reset password form.
|
||||||
*/
|
*/
|
||||||
export default function SendResetPasswordForm({ isSubmitting }) {
|
export default function SendResetPasswordForm({ isSubmitting }) {
|
||||||
return (
|
return (
|
||||||
<Form className={'send-reset-password'}>
|
<Form>
|
||||||
<FastField name={'crediential'}>
|
<TopParagraph>
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
Enter the email address associated with your account and we'll send you
|
||||||
<FormGroup
|
a link to reset your password.
|
||||||
label={<T id={'email_or_phone_number'} />}
|
</TopParagraph>
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name={'crediential'} />}
|
|
||||||
className={'form-group--crediential'}
|
|
||||||
>
|
|
||||||
<InputGroup
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
large={true}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
|
|
||||||
<div className={'authentication-page__submit-button-wrap'}>
|
<FFormGroup
|
||||||
<Button
|
name={'crediential'}
|
||||||
|
label={<T id={'email_or_phone_number'} />}
|
||||||
|
>
|
||||||
|
<FInputGroup name={'crediential'} large={true} />
|
||||||
|
</FFormGroup>
|
||||||
|
|
||||||
|
<AuthSubmitButton
|
||||||
type={'submit'}
|
type={'submit'}
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
fill={true}
|
fill={true}
|
||||||
|
large={true}
|
||||||
loading={isSubmitting}
|
loading={isSubmitting}
|
||||||
>
|
>
|
||||||
<T id={'send_reset_password_mail'} />
|
Reset Password
|
||||||
</Button>
|
</AuthSubmitButton>
|
||||||
</div>
|
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TopParagraph = styled.p`
|
||||||
|
margin-bottom: 1.6rem;
|
||||||
|
opacity: 0.8;
|
||||||
|
`;
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { Spinner } from '@blueprintjs/core';
|
||||||
|
import { Button } from '@blueprintjs/core';
|
||||||
|
|
||||||
|
export function AuthenticationLoadingOverlay() {
|
||||||
|
return (
|
||||||
|
<AuthOverlayRoot>
|
||||||
|
<Spinner size={50} />
|
||||||
|
</AuthOverlayRoot>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const AuthOverlayRoot = styled.div`
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
background: rgba(252, 253, 255, 0.5);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const AuthInsiderContent = styled.div`
|
||||||
|
position: relative;
|
||||||
|
`;
|
||||||
|
export const AuthInsiderCard = styled.div`
|
||||||
|
border: 1px solid #d5d5d5;
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
|
||||||
|
padding: 26px 22px;
|
||||||
|
background: #ffff;
|
||||||
|
border-radius: 3px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const AuthInsiderCopyright = styled.div`
|
||||||
|
text-align: center;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
margin-top: 1.2rem;
|
||||||
|
|
||||||
|
.bp3-icon-bigcapital {
|
||||||
|
svg {
|
||||||
|
path {
|
||||||
|
fill: #a3a3a3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const AuthFooterLinks = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
padding-left: 1.2rem;
|
||||||
|
padding-right: 1.2rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const AuthFooterLink = styled.p`
|
||||||
|
color: #666;
|
||||||
|
margin: 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const AuthSubmitButton = styled(Button)`
|
||||||
|
background-color: #0052cc;
|
||||||
|
min-height: 45px;
|
||||||
|
margin-top: 20px;
|
||||||
|
`;
|
||||||
@@ -16,15 +16,9 @@ export function PasswordRevealer({ defaultShown = false, onChange }) {
|
|||||||
<span class="password-revealer" onClick={handleClick}>
|
<span class="password-revealer" onClick={handleClick}>
|
||||||
<If condition={shown}>
|
<If condition={shown}>
|
||||||
<Icon icon="eye-slash" />{' '}
|
<Icon icon="eye-slash" />{' '}
|
||||||
<span class="text">
|
|
||||||
<T id={'hide'} />
|
|
||||||
</span>
|
|
||||||
</If>
|
</If>
|
||||||
<If condition={!shown}>
|
<If condition={!shown}>
|
||||||
<Icon icon="eye" />{' '}
|
<Icon icon="eye" />{' '}
|
||||||
<span class="text">
|
|
||||||
<T id={'show'} />
|
|
||||||
</span>
|
|
||||||
</If>
|
</If>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
"phone_number": "Phone Number",
|
"phone_number": "Phone Number",
|
||||||
"you_email_address_is": "You email address is",
|
"you_email_address_is": "You email address is",
|
||||||
"you_will_use_this_address_to_sign_in_to_bigcapital": "You will use this address to sign in to Bigcapital.",
|
"you_will_use_this_address_to_sign_in_to_bigcapital": "You will use this address to sign in to Bigcapital.",
|
||||||
"signing_in_or_creating": "By signing in or creating an account, you agree with our <br/> <a>Terms & Conditions </a> and <a> Privacy Statement </a> ",
|
"signing_in_or_creating": "By signing in or creating an account, you agree with our <a>Terms & Conditions </a> and <a> Privacy Statement </a> ",
|
||||||
"and": "And",
|
"and": "And",
|
||||||
"create_account": "Create Account",
|
"create_account": "Create Account",
|
||||||
"success": "Success",
|
"success": "Success",
|
||||||
|
|||||||
@@ -1,45 +1,8 @@
|
|||||||
|
|
||||||
body.authentication {
|
body.authentication {
|
||||||
background-color: #fcfdff;
|
background-color: #fcfdff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.authentication-insider {
|
.authTransition {
|
||||||
width: 384px;
|
|
||||||
margin: 0 auto;
|
|
||||||
margin-bottom: 40px;
|
|
||||||
padding-top: 80px;
|
|
||||||
|
|
||||||
&__logo-section {
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__content {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__footer {
|
|
||||||
.auth-copyright {
|
|
||||||
text-align: center;
|
|
||||||
font-size: 12px;
|
|
||||||
color: #666;
|
|
||||||
|
|
||||||
.bp3-icon-bigcapital {
|
|
||||||
margin-top: 9px;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
path {
|
|
||||||
fill: #a3a3a3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.authTransition{
|
|
||||||
|
|
||||||
&-enter {
|
&-enter {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
@@ -61,164 +24,9 @@ body.authentication {
|
|||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
transition: opacity 250ms ease-in-out;
|
transition: opacity 250ms ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-exit-active {
|
&-exit-active {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.authentication-page {
|
|
||||||
&__goto-bigcapital {
|
|
||||||
position: fixed;
|
|
||||||
margin-top: 30px;
|
|
||||||
margin-left: 30px;
|
|
||||||
color: #777;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bp3-input {
|
|
||||||
min-height: 40px;
|
|
||||||
}
|
|
||||||
.bp3-form-group {
|
|
||||||
margin-bottom: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bp3-form-group.has-password-revealer {
|
|
||||||
.bp3-label {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.password-revealer {
|
|
||||||
.text {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.bp3-button.bp3-fill.bp3-intent-primary {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__label-section {
|
|
||||||
margin-bottom: 30px;
|
|
||||||
color: #555;
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 22px;
|
|
||||||
color: #2d2b43;
|
|
||||||
margin: 0 0 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
text-decoration: underline;
|
|
||||||
color: #0040bd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__form-wrapper {
|
|
||||||
width: 100%;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__footer-links {
|
|
||||||
padding: 9px;
|
|
||||||
border-top: 1px solid #ddd;
|
|
||||||
border-bottom: 1px solid #ddd;
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 1.2rem;
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #0052cc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__loading-overlay {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
background: rgba(252, 253, 255, 0.5);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__submit-button-wrap {
|
|
||||||
margin: 0px 0px 24px 0px;
|
|
||||||
|
|
||||||
.bp3-button {
|
|
||||||
background-color: #0052cc;
|
|
||||||
min-height: 45px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Login Form
|
|
||||||
// ------------------------------
|
|
||||||
.login-form {
|
|
||||||
// width: 690px;
|
|
||||||
// margin: 0px auto;
|
|
||||||
// padding: 85px 50px;
|
|
||||||
|
|
||||||
.checkbox {
|
|
||||||
&--remember-me {
|
|
||||||
margin: -6px 0 26px 0px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register form
|
|
||||||
// ----------------------------
|
|
||||||
.register-form {
|
|
||||||
|
|
||||||
&__agreement-section {
|
|
||||||
margin-top: -10px;
|
|
||||||
|
|
||||||
p {
|
|
||||||
font-size: 13px;
|
|
||||||
margin-top: -10px;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
line-height: 1.65;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__submit-button-wrap {
|
|
||||||
margin: 25px 0px 25px 0px;
|
|
||||||
|
|
||||||
.bp3-button {
|
|
||||||
min-height: 45px;
|
|
||||||
background-color: #0052cc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send reset password
|
|
||||||
// ----------------------------
|
|
||||||
.send-reset-password {
|
|
||||||
.form-group--crediential {
|
|
||||||
margin-bottom: 36px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invite form.
|
|
||||||
// ----------------
|
|
||||||
.invite-form {
|
|
||||||
|
|
||||||
&__statement-section {
|
|
||||||
margin-top: -10px;
|
|
||||||
|
|
||||||
p {
|
|
||||||
font-size: 14px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
line-height: 1.65;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.authentication-page__loading-overlay {
|
|
||||||
background: rgba(252, 253, 255, 0.9);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user