re-structure to monorepo.

This commit is contained in:
a.bouhuolia
2023-02-03 01:02:31 +02:00
parent 8242ec64ba
commit 7a0a13f9d5
10400 changed files with 46966 additions and 17223 deletions

View File

@@ -0,0 +1,20 @@
// @ts-nocheck
import React from 'react';
import moment from 'moment';
import intl from 'react-intl-universal';
import { Icon } from '@/components/Icon';
export default function AuthCopyright() {
return (
<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>
);
}

View File

@@ -0,0 +1,24 @@
// @ts-nocheck
import React from 'react';
import AuthCopyright from './AuthCopyright';
/**
* Authentication insider page.
*/
export default function AuthInsider({
logo = true,
copyright = true,
children,
}) {
return (
<div class="authentication-insider__content">
<div class="authentication-insider__form">
{ children }
</div>
<div class="authentication-insider__footer">
<AuthCopyright />
</div>
</div>
);
}

View File

@@ -0,0 +1,21 @@
// @ts-nocheck
import React from 'react';
import { useParams } from 'react-router-dom';
import InviteAcceptForm from './InviteAcceptForm';
import AuthInsider from '@/containers/Authentication/AuthInsider';
import { InviteAcceptProvider } from './InviteAcceptProvider';
/**
* Authentication invite page.
*/
export default function Invite() {
const { token } = useParams();
return (
<AuthInsider>
<InviteAcceptProvider token={token}>
<InviteAcceptForm />
</InviteAcceptProvider>
</AuthInsider>
);
}

View File

@@ -0,0 +1,102 @@
// @ts-nocheck
import React from 'react';
import intl from 'react-intl-universal';
import { Formik } from 'formik';
import { useHistory } from 'react-router-dom';
import { Intent, Position } from '@blueprintjs/core';
import { FormattedMessage as T } from '@/components';
import { isEmpty } from 'lodash';
import { useInviteAcceptContext } from './InviteAcceptProvider';
import { AppToaster } from '@/components';
import { InviteAcceptSchema } from './utils';
import InviteAcceptFormContent from './InviteAcceptFormContent';
export default function InviteAcceptForm() {
const history = useHistory();
// Invite accept context.
const { inviteAcceptMutate, inviteMeta, token } = useInviteAcceptContext();
// Invite value.
const inviteValue = {
organization_name: '',
invited_email: '',
...(!isEmpty(inviteMeta)
? {
invited_email: inviteMeta.email,
organization_name: inviteMeta.organizationName,
}
: {}),
};
// Handle form submitting.
const handleSubmit = (values, { setSubmitting, setErrors }) => {
inviteAcceptMutate([values, token])
.then((response) => {
AppToaster.show({
message: intl.getHTML(
'congrats_your_account_has_been_created_and_invited',
{
organization_name: inviteValue.organization_name,
},
),
intent: Intent.SUCCESS,
});
history.push('/auth/login');
setSubmitting(false);
})
.catch(
({
response: {
data: { errors },
},
}) => {
if (errors.find((e) => e.type === 'INVITE.TOKEN.NOT.FOUND')) {
AppToaster.show({
message: intl.get('an_unexpected_error_occurred'),
intent: Intent.DANGER,
position: Position.BOTTOM,
});
history.push('/auth/login');
}
if (errors.find((e) => e.type === 'PHONE_MUMNER.ALREADY.EXISTS')) {
setErrors({
phone_number: 'This phone number is used in another account.',
});
}
if (errors.find((e) => e.type === 'INVITE.TOKEN.NOT.FOUND')) {
AppToaster.show({
message: intl.get('an_unexpected_error_occurred'),
intent: Intent.DANGER,
position: Position.BOTTOM,
});
history.push('/auth/login');
}
setSubmitting(false);
},
);
};
return (
<div className={'invite-form'}>
<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
validationSchema={InviteAcceptSchema}
initialValues={inviteValue}
onSubmit={handleSubmit}
component={InviteAcceptFormContent}
/>
</div>
);
}

View File

@@ -0,0 +1,132 @@
// @ts-nocheck
import React from 'react';
import intl from 'react-intl-universal';
import { Button, InputGroup, Intent, FormGroup } from '@blueprintjs/core';
import { Form, ErrorMessage, FastField, useFormikContext } from 'formik';
import { Link } from 'react-router-dom';
import { Col, Row, FormattedMessage as T } from '@/components';
import { inputIntent } from '@/utils';
import { useInviteAcceptContext } from './InviteAcceptProvider';
import { PasswordRevealer } from './components';
/**
* Invite user form.
*/
export default function InviteUserFormContent() {
// Invite accept context.
const { inviteMeta } = useInviteAcceptContext();
// Formik context.
const { isSubmitting } = useFormikContext();
const [passwordType, setPasswordType] = React.useState('password');
// Handle password revealer changing.
const handlePasswordRevealerChange = React.useCallback(
(shown) => {
const type = shown ? 'text' : 'password';
setPasswordType(type);
},
[setPasswordType],
);
return (
<Form>
<Row>
<Col md={6}>
<FastField name={'first_name'}>
{({ form, field, meta: { error, touched } }) => (
<FormGroup
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 md={6}>
<FastField name={'last_name'}>
{({ form, field, meta: { error, touched } }) => (
<FormGroup
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>
</Row>
<FastField name={'phone_number'}>
{({ form, field, meta: { error, touched } }) => (
<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'} />}
labelInfo={
<PasswordRevealer onChange={handlePasswordRevealerChange} />
}
className={'form-group--password has-password-revealer'}
intent={inputIntent({ error, touched })}
helperText={<ErrorMessage name={'password'} />}
>
<InputGroup
lang={true}
type={passwordType}
intent={inputIntent({ error, touched })}
{...field}
/>
</FormGroup>
)}
</FastField>
<div className={'invite-form__statement-section'}>
<p>
<T id={'you_email_address_is'} /> <b>{inviteMeta.email},</b> <br />
<T id={'you_will_use_this_address_to_sign_in_to_bigcapital'} />
</p>
<p>
{intl.getHTML('signing_in_or_creating', {
terms: (msg) => <Link>{msg}</Link>,
privacy: (msg) => <Link>{msg}</Link>,
})}
</p>
</div>
<div className={'authentication-page__submit-button-wrap'}>
<Button
intent={Intent.PRIMARY}
type="submit"
fill={true}
loading={isSubmitting}
>
<T id={'create_account'} />
</Button>
</div>
</Form>
);
}

View File

@@ -0,0 +1,57 @@
// @ts-nocheck
import React, { createContext, useContext } from 'react';
import { useInviteMetaByToken, useAuthInviteAccept } from '@/hooks/query';
import { InviteAcceptLoading } from './components';
import { useHistory } from 'react-router-dom';
const InviteAcceptContext = createContext();
/**
* Invite accept provider.
*/
function InviteAcceptProvider({ token, ...props }) {
// Invite meta by token.
const {
data: inviteMeta,
error: inviteMetaError,
isError: isInviteMetaError,
isFetching: isInviteMetaLoading,
} = useInviteMetaByToken(token, { retry: false });
// Invite accept mutate.
const { mutateAsync: inviteAcceptMutate } = useAuthInviteAccept({
retry: false,
});
// History context.
const history = useHistory();
React.useEffect(() => {
if (inviteMetaError) { history.push('/auth/login'); }
}, [history, inviteMetaError]);
// Provider payload.
const provider = {
token,
inviteMeta,
inviteMetaError,
isInviteMetaError,
isInviteMetaLoading,
inviteAcceptMutate
};
if (inviteMetaError) {
return null;
}
return (
<InviteAcceptLoading isLoading={isInviteMetaLoading}>
{ isInviteMetaError }
<InviteAcceptContext.Provider value={provider} {...props} />
</InviteAcceptLoading>
);
}
const useInviteAcceptContext = () => useContext(InviteAcceptContext);
export { InviteAcceptProvider, useInviteAcceptContext };

View File

@@ -0,0 +1,71 @@
// @ts-nocheck
import React from 'react';
import { Link } from 'react-router-dom';
import { Formik } from 'formik';
import { AppToaster as Toaster, FormattedMessage as T } from '@/components';
import AuthInsider from '@/containers/Authentication/AuthInsider';
import { useAuthLogin } from '@/hooks/query';
import LoginForm from './LoginForm';
import { LoginSchema, transformLoginErrorsToToasts } from './utils';
/**
* Login page.
*/
export default function Login() {
const { mutateAsync: loginMutate } = useAuthLogin();
const handleSubmit = (values, { setSubmitting }) => {
loginMutate({
crediential: values.crediential,
password: values.password,
}).catch(
({
response: {
data: { errors },
},
}) => {
const toastBuilders = transformLoginErrorsToToasts(errors);
toastBuilders.forEach((builder) => {
Toaster.show(builder);
});
setSubmitting(false);
},
);
};
return (
<AuthInsider>
<div className="login-form">
<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
initialValues={{
crediential: '',
password: '',
}}
validationSchema={LoginSchema}
onSubmit={handleSubmit}
component={LoginForm}
/>
<div class="authentication-page__footer-links">
<Link to={'/auth/send_reset_password'}>
<T id={'forget_my_password'} />
</Link>
</div>
</div>
</AuthInsider>
);
}

View File

@@ -0,0 +1,89 @@
// @ts-nocheck
import React from 'react';
import {
Button,
InputGroup,
Intent,
FormGroup,
Checkbox,
} from '@blueprintjs/core';
import { Form, ErrorMessage, Field } from 'formik';
import { T } from '@/components';
import { inputIntent } from '@/utils';
import { PasswordRevealer } from './components';
/**
* Login form.
*/
export default function LoginForm({ isSubmitting }) {
const [passwordType, setPasswordType] = React.useState('password');
// Handle password revealer changing.
const handlePasswordRevealerChange = React.useCallback(
(shown) => {
const type = shown ? 'text' : 'password';
setPasswordType(type);
},
[setPasswordType],
);
return (
<Form className={'authentication-page__form'}>
<Field name={'crediential'}>
{({ form, field, meta: { error, touched } }) => (
<FormGroup
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'}>
{({ 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
large={true}
intent={inputIntent({ error, touched })}
type={passwordType}
{...field}
/>
</FormGroup>
)}
</Field>
<div className={'login-form__checkbox-section'}>
<Checkbox large={true} className={'checkbox--remember-me'}>
<T id={'keep_me_logged_in'} />
</Checkbox>
</div>
<div className={'authentication-page__submit-button-wrap'}>
<Button
type={'submit'}
intent={Intent.PRIMARY}
fill={true}
lang={true}
loading={isSubmitting}
>
<T id={'log_in'} />
</Button>
</div>
</Form>
);
}

View File

@@ -0,0 +1,89 @@
// @ts-nocheck
import React, { useMemo } from 'react';
import intl from 'react-intl-universal';
import { Formik } from 'formik';
import { Link } from 'react-router-dom';
import { Intent } from '@blueprintjs/core';
import { AppToaster, FormattedMessage as T } from '@/components';
import AuthInsider from '@/containers/Authentication/AuthInsider';
import { useAuthLogin, useAuthRegister } from '@/hooks/query/authentication';
import RegisterForm from './RegisterForm';
import { RegisterSchema, transformRegisterErrorsToForm } from './utils';
/**
* Register form.
*/
export default function RegisterUserForm() {
const { mutateAsync: authLoginMutate } = useAuthLogin();
const { mutateAsync: authRegisterMutate } = useAuthRegister();
const initialValues = useMemo(
() => ({
first_name: '',
last_name: '',
email: '',
phone_number: '',
password: '',
country: 'LY',
}),
[],
);
const handleSubmit = (values, { setSubmitting, setErrors }) => {
authRegisterMutate(values)
.then((response) => {
authLoginMutate({
crediential: values.email,
password: values.password,
}).catch(
({
response: {
data: { errors },
},
}) => {
AppToaster.show({
message: intl.get('something_wentwrong'),
intent: Intent.SUCCESS,
});
},
);
})
.catch(
({
response: {
data: { errors },
},
}) => {
const formErrors = transformRegisterErrorsToForm(errors);
setErrors(formErrors);
setSubmitting(false);
},
);
};
return (
<AuthInsider>
<div className={'register-form'}>
<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
initialValues={initialValues}
validationSchema={RegisterSchema}
onSubmit={handleSubmit}
component={RegisterForm}
/>
</div>
</AuthInsider>
);
}

View File

@@ -0,0 +1,148 @@
// @ts-nocheck
import React from 'react';
import intl from 'react-intl-universal';
import {
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 { Row, Col, If } from '@/components';
import { PasswordRevealer } from './components';
import { inputIntent } from '@/utils';
/**
* Register form.
*/
export default function RegisterForm({ isSubmitting }) {
const [passwordType, setPasswordType] = React.useState('password');
// Handle password revealer changing.
const handlePasswordRevealerChange = React.useCallback(
(shown) => {
const type = shown ? 'text' : 'password';
setPasswordType(type);
},
[setPasswordType],
);
return (
<Form className={'authentication-page__form'}>
<Row className={'name-section'}>
<Col md={6}>
<Field name={'first_name'}>
{({ form, field, meta: { error, touched } }) => (
<FormGroup
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 md={6}>
<Field name={'last_name'}>
{({ form, field, meta: { error, touched } }) => (
<FormGroup
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>
</Row>
<Field name={'phone_number'}>
{({ form, field, meta: { error, touched } }) => (
<FormGroup
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'}>
{({ form, field, meta: { error, touched } }) => (
<FormGroup
label={<T id={'email'} />}
intent={inputIntent({ error, touched })}
helperText={<ErrorMessage name={'email'} />}
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>
)}
</Field>
<div className={'register-form__agreement-section'}>
<p>
{intl.getHTML('signing_in_or_creating', {
terms: (msg) => <Link>{msg}</Link>,
privacy: (msg) => <Link>{msg}</Link>,
})}
</p>
</div>
<div className={'authentication-page__submit-button-wrap'}>
<Button
className={'btn-register'}
intent={Intent.PRIMARY}
type="submit"
fill={true}
loading={isSubmitting}
>
<T id={'register'} />
</Button>
</div>
<If condition={isSubmitting}>
<div class="authentication-page__loading-overlay">
<Spinner size={50} />
</div>
</If>
</Form>
);
}

View File

@@ -0,0 +1,87 @@
// @ts-nocheck
import React, { useMemo } from 'react';
import intl from 'react-intl-universal';
import { Formik } from 'formik';
import { Intent, Position } from '@blueprintjs/core';
import { Link, useParams, useHistory } from 'react-router-dom';
import { AppToaster, FormattedMessage as T } from '@/components';
import { useAuthResetPassword } from '@/hooks/query';
import AuthInsider from '@/containers/Authentication/AuthInsider';
import ResetPasswordForm from './ResetPasswordForm';
import { ResetPasswordSchema } from './utils';
/**
* Reset password page.
*/
export default function ResetPassword() {
const { token } = useParams();
const history = useHistory();
// Authentication reset password.
const { mutateAsync: authResetPasswordMutate } = useAuthResetPassword();
// Initial values of the form.
const initialValues = useMemo(
() => ({
password: '',
confirm_password: '',
}),
[],
);
// Handle the form submitting.
const handleSubmit = (values, { setSubmitting }) => {
authResetPasswordMutate([token, values])
.then((response) => {
AppToaster.show({
message: intl.get('password_successfully_updated'),
intent: Intent.DANGER,
position: Position.BOTTOM,
});
history.push('/auth/login');
setSubmitting(false);
})
.catch(
({
response: {
data: { errors },
},
}) => {
if (errors.find((e) => e.type === 'TOKEN_INVALID')) {
AppToaster.show({
message: intl.get('an_unexpected_error_occurred'),
intent: Intent.DANGER,
position: Position.BOTTOM,
});
history.push('/auth/login');
}
setSubmitting(false);
},
);
};
return (
<AuthInsider>
<div className={'submit-np-form'}>
<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
initialValues={initialValues}
validationSchema={ResetPasswordSchema}
onSubmit={handleSubmit}
component={ResetPasswordForm}
/>
</div>
</AuthInsider>
);
}

View File

@@ -0,0 +1,64 @@
// @ts-nocheck
import React from 'react';
import { Button, InputGroup, Intent, FormGroup } from '@blueprintjs/core';
import { Form, ErrorMessage, FastField } from 'formik';
import { FormattedMessage as T } from '@/components';
import { inputIntent } from '@/utils';
/**
* Reset password form.
*/
export default function ResetPasswordForm({ isSubmitting }) {
return (
<Form>
<FastField name={'password'}>
{({ form, field, meta: { error, touched } }) => (
<FormGroup
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'}>
{({ form, field, meta: { error, touched } }) => (
<FormGroup
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'}>
<Button
fill={true}
className={'btn-new'}
intent={Intent.PRIMARY}
type="submit"
loading={isSubmitting}
>
<T id={'submit'} />
</Button>
</div>
</Form>
);
}

View File

@@ -0,0 +1,88 @@
// @ts-nocheck
import React, { useMemo } from 'react';
import intl from 'react-intl-universal';
import { Formik } from 'formik';
import { Link, useHistory } from 'react-router-dom';
import { Intent } from '@blueprintjs/core';
import { AppToaster, FormattedMessage as T } from '@/components';
import { useAuthSendResetPassword } from '@/hooks/query';
import SendResetPasswordForm from './SendResetPasswordForm';
import {
SendResetPasswordSchema,
transformSendResetPassErrorsToToasts,
} from './utils';
import AuthInsider from '@/containers/Authentication/AuthInsider';
/**
* Send reset password page.
*/
export default function SendResetPassword({ requestSendResetPassword }) {
const history = useHistory();
const { mutateAsync: sendResetPasswordMutate } = useAuthSendResetPassword();
// Initial values.
const initialValues = useMemo(
() => ({
crediential: '',
}),
[],
);
// Handle form submitting.
const handleSubmit = (values, { setSubmitting }) => {
sendResetPasswordMutate({ email: values.crediential })
.then((response) => {
AppToaster.show({
message: intl.get('check_your_email_for_a_link_to_reset'),
intent: Intent.SUCCESS,
});
history.push('/auth/login');
setSubmitting(false);
})
.catch(
({
response: {
data: { errors },
},
}) => {
const toastBuilders = transformSendResetPassErrorsToToasts(errors);
toastBuilders.forEach((builder) => {
AppToaster.show(builder);
});
setSubmitting(false);
},
);
};
return (
<AuthInsider>
<div className="reset-form">
<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
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={SendResetPasswordSchema}
component={SendResetPasswordForm}
/>
<div class="authentication-page__footer-links">
<Link to="/auth/login">
<T id={'return_to_log_in'} />
</Link>
</div>
</div>
</AuthInsider>
);
}

View File

@@ -0,0 +1,43 @@
// @ts-nocheck
import React from 'react';
import { Button, InputGroup, Intent, FormGroup } from '@blueprintjs/core';
import { Form, ErrorMessage, FastField } from 'formik';
import { FormattedMessage as T } from '@/components';
import { inputIntent } from '@/utils';
/**
* Send reset password form.
*/
export default function SendResetPasswordForm({ isSubmitting }) {
return (
<Form className={'send-reset-password'}>
<FastField name={'crediential'}>
{({ form, field, meta: { error, touched } }) => (
<FormGroup
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>
)}
</FastField>
<div className={'authentication-page__submit-button-wrap'}>
<Button
type={'submit'}
intent={Intent.PRIMARY}
fill={true}
loading={isSubmitting}
>
<T id={'send_reset_password_mail'} />
</Button>
</div>
</Form>
);
}

View File

@@ -0,0 +1,57 @@
// @ts-nocheck
import React from 'react';
import ContentLoader from 'react-content-loader';
import { If, Icon, FormattedMessage as T } from '@/components';
import { saveInvoke } from '@/utils';
export function PasswordRevealer({ defaultShown = false, onChange }) {
const [shown, setShown] = React.useState(defaultShown);
const handleClick = () => {
setShown(!shown);
saveInvoke(onChange, !shown);
};
return (
<span class="password-revealer" onClick={handleClick}>
<If condition={shown}>
<Icon icon="eye-slash" />{' '}
<span class="text">
<T id={'hide'} />
</span>
</If>
<If condition={!shown}>
<Icon icon="eye" />{' '}
<span class="text">
<T id={'show'} />
</span>
</If>
</span>
);
}
/**
* Invite accept loading space.
*/
export function InviteAcceptLoading({ isLoading, children, ...props }) {
return isLoading ? (
<ContentLoader
speed={2}
width={400}
height={280}
viewBox="0 0 400 280"
backgroundColor="#f3f3f3"
foregroundColor="#e6e6e6"
{...props}
>
<rect x="0" y="80" rx="2" ry="2" width="200" height="20" />
<rect x="0" y="0" rx="2" ry="2" width="250" height="30" />
<rect x="0" y="38" rx="2" ry="2" width="300" height="15" />
<rect x="0" y="175" rx="2" ry="2" width="200" height="20" />
<rect x="1" y="205" rx="2" ry="2" width="385" height="38" />
<rect x="0" y="110" rx="2" ry="2" width="385" height="38" />
</ContentLoader>
) : (
children
);
}

View File

@@ -0,0 +1,133 @@
// @ts-nocheck
import * as Yup from 'yup';
import intl from 'react-intl-universal';
import { Intent } from '@blueprintjs/core';
export const LOGIN_ERRORS = {
INVALID_DETAILS: 'INVALID_DETAILS',
USER_INACTIVE: 'USER_INACTIVE',
LOGIN_TO_MANY_ATTEMPTS: 'LOGIN_TO_MANY_ATTEMPTS',
};
const REGISTER_ERRORS = {
PHONE_NUMBER_EXISTS: 'PHONE_NUMBER_EXISTS',
EMAIL_EXISTS: 'EMAIL.EXISTS',
};
export const LoginSchema = Yup.object().shape({
crediential: Yup.string()
.required()
.email()
.label(intl.get('email')),
password: Yup.string()
.required()
.min(4)
.label(intl.get('password')),
});
export const RegisterSchema = Yup.object().shape({
first_name: Yup.string()
.required()
.label(intl.get('first_name_')),
last_name: Yup.string()
.required()
.label(intl.get('last_name_')),
email: Yup.string()
.email()
.required()
.label(intl.get('email')),
phone_number: Yup.string()
.matches()
.required()
.label(intl.get('phone_number_')),
password: Yup.string()
.min(4)
.required()
.label(intl.get('password')),
});
export const ResetPasswordSchema = Yup.object().shape({
password: Yup.string()
.min(4)
.required()
.label(intl.get('password')),
confirm_password: Yup.string()
.oneOf([Yup.ref('password'), null])
.required()
.label(intl.get('confirm_password')),
});
// Validation schema.
export const SendResetPasswordSchema = Yup.object().shape({
crediential: Yup.string()
.required()
.email()
.label(intl.get('email')),
});
export const InviteAcceptSchema = Yup.object().shape({
first_name: Yup.string()
.required()
.label(intl.get('first_name_')),
last_name: Yup.string()
.required()
.label(intl.get('last_name_')),
phone_number: Yup.string()
.matches()
.required()
.label(intl.get('phone_number')),
password: Yup.string()
.min(4)
.required()
.label(intl.get('password')),
});
export const transformSendResetPassErrorsToToasts = (errors) => {
const toastBuilders = [];
if (errors.find((e) => e.type === 'EMAIL.NOT.REGISTERED')) {
toastBuilders.push({
message: intl.get('we_couldn_t_find_your_account_with_that_email'),
intent: Intent.DANGER,
});
}
return toastBuilders;
}
export const transformLoginErrorsToToasts = (errors) => {
const toastBuilders = [];
if (errors.find((e) => e.type === LOGIN_ERRORS.INVALID_DETAILS)) {
toastBuilders.push({
message: intl.get('email_and_password_entered_did_not_match'),
intent: Intent.DANGER,
});
}
if (errors.find((e) => e.type === LOGIN_ERRORS.USER_INACTIVE)) {
toastBuilders.push({
message: intl.get('the_user_has_been_suspended_from_admin'),
intent: Intent.DANGER,
});
}
if (
errors.find((e) => e.type === LOGIN_ERRORS.LOGIN_TO_MANY_ATTEMPTS)
) {
toastBuilders.push({
message: intl.get('your_account_has_been_locked'),
intent: Intent.DANGER,
});
}
return toastBuilders;
}
export const transformRegisterErrorsToForm = (errors) => {
const formErrors = {};
if (errors.some((e) => e.type === REGISTER_ERRORS.PHONE_NUMBER_EXISTS)) {
formErrors.phone_number = intl.get('the_phone_number_already_used_in_another_account');
}
if (errors.some((e) => e.type === REGISTER_ERRORS.EMAIL_EXISTS)) {
formErrors.email = intl.get('the_email_already_used_in_another_account');
}
return formErrors;
}

View File

@@ -0,0 +1,16 @@
// @ts-nocheck
import { isAuthenticated } from '@/store/authentication/authentication.reducer';
import { connect } from 'react-redux';
export default (mapState) => {
const mapStateToProps = (state, props) => {
const mapped = {
isAuthorized: isAuthenticated(state),
authenticatedUserId: state.authentication.userId,
currentOrganizationId: state.authentication?.organizationId,
currentTenantId: state.authentication?.tenantId,
};
return mapState ? mapState(mapped, state, props) : mapped;
};
return connect(mapStateToProps);
};

View File

@@ -0,0 +1,14 @@
// @ts-nocheck
import { connect } from 'react-redux';
const mapDispatchToProps = (dispatch) => ({
// requestLogin: (form) => dispatch(login({ form })),
// requestLogout: () => dispatch({ type: t.LOGOUT }),
// requestRegister: (form) => dispatch(register({ form })),
// requestSendResetPassword: (email) => dispatch(sendResetPassword({ email })),
// requestResetPassword: (form, token) => dispatch(resetPassword({ form, token })),
// requestInviteAccept: (form, token) => dispatch(inviteAccept({ form, token })),
// requestInviteMetaByToken: (token) => dispatch(inviteMetaByToken({ token })),
});
export default connect(null, mapDispatchToProps);