mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Add form-field component and new account view (#11450)
* add generic form-field component * swap in new form-field component for advanced-gas-controls-row * add new create password view for redesigned onboarding flow * make text additions translatable
This commit is contained in:
parent
68ad9c619f
commit
b1e2005a73
@ -471,6 +471,9 @@
|
|||||||
"createAccount": {
|
"createAccount": {
|
||||||
"message": "Create Account"
|
"message": "Create Account"
|
||||||
},
|
},
|
||||||
|
"createNewWallet": {
|
||||||
|
"message": "Create a new wallet"
|
||||||
|
},
|
||||||
"createPassword": {
|
"createPassword": {
|
||||||
"message": "Create Password"
|
"message": "Create Password"
|
||||||
},
|
},
|
||||||
@ -1464,6 +1467,12 @@
|
|||||||
"passwordNotLongEnough": {
|
"passwordNotLongEnough": {
|
||||||
"message": "Password not long enough"
|
"message": "Password not long enough"
|
||||||
},
|
},
|
||||||
|
"passwordSetupDetails": {
|
||||||
|
"message": "This password will unlock your MetaMask wallet only on this device. MetaMask can not recover this password."
|
||||||
|
},
|
||||||
|
"passwordTermsWarning": {
|
||||||
|
"message": "I understand that MetaMask cannot recover this password for me. $1"
|
||||||
|
},
|
||||||
"passwordsDontMatch": {
|
"passwordsDontMatch": {
|
||||||
"message": "Passwords Don't Match"
|
"message": "Passwords Don't Match"
|
||||||
},
|
},
|
||||||
@ -1797,6 +1806,9 @@
|
|||||||
"settings": {
|
"settings": {
|
||||||
"message": "Settings"
|
"message": "Settings"
|
||||||
},
|
},
|
||||||
|
"show": {
|
||||||
|
"message": "Show"
|
||||||
|
},
|
||||||
"showAdvancedGasInline": {
|
"showAdvancedGasInline": {
|
||||||
"message": "Advanced gas controls"
|
"message": "Advanced gas controls"
|
||||||
},
|
},
|
||||||
|
@ -1,97 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
import Typography from '../../ui/typography/typography';
|
|
||||||
import {
|
|
||||||
COLORS,
|
|
||||||
TEXT_ALIGN,
|
|
||||||
DISPLAY,
|
|
||||||
TYPOGRAPHY,
|
|
||||||
FONT_WEIGHT,
|
|
||||||
} from '../../../helpers/constants/design-system';
|
|
||||||
|
|
||||||
import NumericInput from '../../ui/numeric-input/numeric-input.component';
|
|
||||||
import InfoTooltip from '../../ui/info-tooltip/info-tooltip';
|
|
||||||
|
|
||||||
export default function AdvancedGasControlsRow({
|
|
||||||
titleText,
|
|
||||||
titleUnit,
|
|
||||||
tooltipText,
|
|
||||||
titleDetailText,
|
|
||||||
error,
|
|
||||||
onChange,
|
|
||||||
value,
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={classNames('advanced-gas-controls__row', {
|
|
||||||
'advanced-gas-controls__row--error': error,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<label>
|
|
||||||
<div className="advanced-gas-controls__row-heading">
|
|
||||||
<div className="advanced-gas-controls__row-heading-title">
|
|
||||||
<Typography
|
|
||||||
tag={TYPOGRAPHY.H6}
|
|
||||||
fontWeight={FONT_WEIGHT.BOLD}
|
|
||||||
variant={TYPOGRAPHY.H6}
|
|
||||||
boxProps={{ display: DISPLAY.INLINE_BLOCK }}
|
|
||||||
>
|
|
||||||
{titleText}
|
|
||||||
</Typography>
|
|
||||||
<Typography
|
|
||||||
tag={TYPOGRAPHY.H6}
|
|
||||||
variant={TYPOGRAPHY.H6}
|
|
||||||
color={COLORS.UI4}
|
|
||||||
boxProps={{ display: DISPLAY.INLINE_BLOCK }}
|
|
||||||
>
|
|
||||||
{titleUnit}
|
|
||||||
</Typography>
|
|
||||||
<InfoTooltip position="top" contentText={tooltipText} />
|
|
||||||
</div>
|
|
||||||
{titleDetailText && (
|
|
||||||
<Typography
|
|
||||||
className="advanced-gas-controls__row-heading-detail"
|
|
||||||
align={TEXT_ALIGN.END}
|
|
||||||
color={COLORS.UI4}
|
|
||||||
variant={TYPOGRAPHY.H8}
|
|
||||||
>
|
|
||||||
{titleDetailText}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<NumericInput error={error} onChange={onChange} value={value} />
|
|
||||||
{error && (
|
|
||||||
<Typography
|
|
||||||
color={COLORS.ERROR1}
|
|
||||||
variant={TYPOGRAPHY.H7}
|
|
||||||
className="advanced-gas-controls__row-error"
|
|
||||||
>
|
|
||||||
{error}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
AdvancedGasControlsRow.propTypes = {
|
|
||||||
titleText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
||||||
titleUnit: PropTypes.string,
|
|
||||||
tooltipText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
||||||
titleDetailText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
||||||
error: PropTypes.string,
|
|
||||||
onChange: PropTypes.func,
|
|
||||||
value: PropTypes.number,
|
|
||||||
};
|
|
||||||
|
|
||||||
AdvancedGasControlsRow.defaultProps = {
|
|
||||||
titleText: '',
|
|
||||||
titleUnit: '',
|
|
||||||
tooltipText: '',
|
|
||||||
titleDetailText: '',
|
|
||||||
error: '',
|
|
||||||
onChange: undefined,
|
|
||||||
value: 0,
|
|
||||||
};
|
|
@ -7,7 +7,7 @@ import {
|
|||||||
TYPOGRAPHY,
|
TYPOGRAPHY,
|
||||||
COLORS,
|
COLORS,
|
||||||
} from '../../../helpers/constants/design-system';
|
} from '../../../helpers/constants/design-system';
|
||||||
import AdvancedGasControlsRow from './advanced-gas-controls-row.component';
|
import FormField from '../../ui/form-field';
|
||||||
|
|
||||||
export default function AdvancedGasControls() {
|
export default function AdvancedGasControls() {
|
||||||
const t = useContext(I18nContext);
|
const t = useContext(I18nContext);
|
||||||
@ -21,22 +21,23 @@ export default function AdvancedGasControls() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="advanced-gas-controls">
|
<div className="advanced-gas-controls">
|
||||||
<AdvancedGasControlsRow
|
<FormField
|
||||||
titleText={t('gasLimit')}
|
titleText={t('gasLimit')}
|
||||||
onChange={setGasLimit}
|
onChange={setGasLimit}
|
||||||
tooltipText=""
|
tooltipText=""
|
||||||
titleDetailText=""
|
|
||||||
value={gasLimit}
|
value={gasLimit}
|
||||||
|
numeric
|
||||||
/>
|
/>
|
||||||
{process.env.SHOW_EIP_1559_UI ? (
|
{process.env.SHOW_EIP_1559_UI ? (
|
||||||
<>
|
<>
|
||||||
<AdvancedGasControlsRow
|
<FormField
|
||||||
titleText={t('maxPriorityFee')}
|
titleText={t('maxPriorityFee')}
|
||||||
titleUnit="(GWEI)"
|
titleUnit="(GWEI)"
|
||||||
tooltipText=""
|
tooltipText=""
|
||||||
onChange={setMaxPriorityFee}
|
onChange={setMaxPriorityFee}
|
||||||
value={maxPriorityFee}
|
value={maxPriorityFee}
|
||||||
titleDetailText={
|
numeric
|
||||||
|
titleDetail={
|
||||||
<>
|
<>
|
||||||
<Typography
|
<Typography
|
||||||
tag="span"
|
tag="span"
|
||||||
@ -54,13 +55,14 @@ export default function AdvancedGasControls() {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<AdvancedGasControlsRow
|
<FormField
|
||||||
titleText={t('maxFee')}
|
titleText={t('maxFee')}
|
||||||
titleUnit="(GWEI)"
|
titleUnit="(GWEI)"
|
||||||
tooltipText=""
|
tooltipText=""
|
||||||
onChange={setMaxFee}
|
onChange={setMaxFee}
|
||||||
value={maxFee}
|
value={maxFee}
|
||||||
titleDetailText={
|
numeric
|
||||||
|
titleDetail={
|
||||||
<>
|
<>
|
||||||
<Typography
|
<Typography
|
||||||
tag="span"
|
tag="span"
|
||||||
@ -81,13 +83,13 @@ export default function AdvancedGasControls() {
|
|||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<AdvancedGasControlsRow
|
<FormField
|
||||||
titleText={t('gasPrice')}
|
titleText={t('gasPrice')}
|
||||||
titleUnit="(GWEI)"
|
titleUnit="(GWEI)"
|
||||||
onChange={setGasPrice}
|
onChange={setGasPrice}
|
||||||
tooltipText={t('editGasPriceTooltip')}
|
tooltipText={t('editGasPriceTooltip')}
|
||||||
titleDetailText=""
|
|
||||||
value={gasPrice}
|
value={gasPrice}
|
||||||
|
numeric
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
134
ui/components/ui/form-field/form-field.js
Normal file
134
ui/components/ui/form-field/form-field.js
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import Typography from '../typography/typography';
|
||||||
|
import Box from '../box/box';
|
||||||
|
import {
|
||||||
|
COLORS,
|
||||||
|
TEXT_ALIGN,
|
||||||
|
DISPLAY,
|
||||||
|
TYPOGRAPHY,
|
||||||
|
FONT_WEIGHT,
|
||||||
|
} from '../../../helpers/constants/design-system';
|
||||||
|
|
||||||
|
import NumericInput from '../numeric-input/numeric-input.component';
|
||||||
|
import InfoTooltip from '../info-tooltip/info-tooltip';
|
||||||
|
|
||||||
|
export default function FormField({
|
||||||
|
titleText,
|
||||||
|
titleUnit,
|
||||||
|
tooltipText,
|
||||||
|
titleDetail,
|
||||||
|
error,
|
||||||
|
onChange,
|
||||||
|
value,
|
||||||
|
numeric,
|
||||||
|
detailText,
|
||||||
|
autoFocus,
|
||||||
|
password,
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classNames('form-field', {
|
||||||
|
'form-field__row--error': error,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<label>
|
||||||
|
<div className="form-field__heading">
|
||||||
|
<div className="form-field__heading-title">
|
||||||
|
{titleText && (
|
||||||
|
<Typography
|
||||||
|
tag={TYPOGRAPHY.H6}
|
||||||
|
fontWeight={FONT_WEIGHT.BOLD}
|
||||||
|
variant={TYPOGRAPHY.H6}
|
||||||
|
boxProps={{ display: DISPLAY.INLINE_BLOCK }}
|
||||||
|
>
|
||||||
|
{titleText}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
{titleUnit && (
|
||||||
|
<Typography
|
||||||
|
tag={TYPOGRAPHY.H6}
|
||||||
|
variant={TYPOGRAPHY.H6}
|
||||||
|
color={COLORS.UI4}
|
||||||
|
boxProps={{ display: DISPLAY.INLINE_BLOCK }}
|
||||||
|
>
|
||||||
|
{titleUnit}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
{tooltipText && (
|
||||||
|
<InfoTooltip position="top" contentText={tooltipText} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{titleDetail && (
|
||||||
|
<Box
|
||||||
|
className="form-field__heading-detail"
|
||||||
|
textAlign={TEXT_ALIGN.END}
|
||||||
|
marginBottom={3}
|
||||||
|
marginRight={2}
|
||||||
|
>
|
||||||
|
{titleDetail}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{numeric ? (
|
||||||
|
<NumericInput
|
||||||
|
error={error}
|
||||||
|
onChange={onChange}
|
||||||
|
value={value}
|
||||||
|
detailText={detailText}
|
||||||
|
autoFocus={autoFocus}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<input
|
||||||
|
className={classNames('form-field__input', {
|
||||||
|
'form-field__input--error': error,
|
||||||
|
})}
|
||||||
|
onChange={(e) => onChange(e.target.value)}
|
||||||
|
value={value}
|
||||||
|
type={password ? 'password' : 'text'}
|
||||||
|
autoFocus={autoFocus}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{error && (
|
||||||
|
<Typography
|
||||||
|
color={COLORS.ERROR1}
|
||||||
|
variant={TYPOGRAPHY.H7}
|
||||||
|
className="form-field__error"
|
||||||
|
>
|
||||||
|
{error}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
FormField.propTypes = {
|
||||||
|
titleText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
||||||
|
titleUnit: PropTypes.string,
|
||||||
|
tooltipText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
||||||
|
titleDetail: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
||||||
|
error: PropTypes.string,
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
value: PropTypes.number,
|
||||||
|
detailText: PropTypes.string,
|
||||||
|
autoFocus: PropTypes.bool,
|
||||||
|
numeric: PropTypes.bool,
|
||||||
|
password: PropTypes.bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
FormField.defaultProps = {
|
||||||
|
titleText: '',
|
||||||
|
titleUnit: '',
|
||||||
|
tooltipText: '',
|
||||||
|
titleDetail: '',
|
||||||
|
error: '',
|
||||||
|
onChange: undefined,
|
||||||
|
value: 0,
|
||||||
|
detailText: '',
|
||||||
|
autoFocus: false,
|
||||||
|
numeric: false,
|
||||||
|
password: false,
|
||||||
|
};
|
55
ui/components/ui/form-field/form-field.stories.js
Normal file
55
ui/components/ui/form-field/form-field.stories.js
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/* eslint-disable react/prop-types */
|
||||||
|
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { select } from '@storybook/addon-knobs';
|
||||||
|
import FormField from '.';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'FormField',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Plain = ({ ...props }) => {
|
||||||
|
const options = { text: false, numeric: true };
|
||||||
|
const [value, setValue] = useState('');
|
||||||
|
return (
|
||||||
|
<div style={{ width: '600px' }}>
|
||||||
|
<FormField
|
||||||
|
onChange={setValue}
|
||||||
|
titleText="Title"
|
||||||
|
value={value}
|
||||||
|
numeric={select('text or numeric', options, options.text)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FormFieldWithTitleDetail = () => {
|
||||||
|
const [clicked, setClicked] = useState(false);
|
||||||
|
const detailOptions = {
|
||||||
|
text: <div style={{ fontSize: '12px' }}>Detail</div>,
|
||||||
|
button: (
|
||||||
|
<button
|
||||||
|
style={{ backgroundColor: clicked ? 'orange' : 'rgb(239, 239, 239)' }}
|
||||||
|
onClick={() => setClicked(!clicked)}
|
||||||
|
>
|
||||||
|
Click Me
|
||||||
|
</button>
|
||||||
|
),
|
||||||
|
checkmark: <i className="fas fa-check" />,
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Plain
|
||||||
|
titleText="Title"
|
||||||
|
titleDetail={
|
||||||
|
detailOptions[
|
||||||
|
select('detailType', ['text', 'button', 'checkmark'], 'text')
|
||||||
|
]
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FormFieldWithError = () => {
|
||||||
|
return <Plain titleText="Title" error="Incorrect Format" />;
|
||||||
|
};
|
1
ui/components/ui/form-field/index.js
Normal file
1
ui/components/ui/form-field/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './form-field';
|
48
ui/components/ui/form-field/index.scss
Normal file
48
ui/components/ui/form-field/index.scss
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
.form-field {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
&__heading {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-tooltip {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__heading-detail {
|
||||||
|
flex-grow: 1;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__error,
|
||||||
|
&__error h6 {
|
||||||
|
color: $error-1 !important;
|
||||||
|
padding-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h6 {
|
||||||
|
padding-bottom: 6px;
|
||||||
|
margin-inline-end: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: #dadada;
|
||||||
|
font-size: $font-size-h7;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__input {
|
||||||
|
width: 100%;
|
||||||
|
border: solid 1px $ui-3;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border: solid 2px $primary-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--error {
|
||||||
|
border-color: $error-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -35,6 +35,7 @@
|
|||||||
@import 'loading-screen/index';
|
@import 'loading-screen/index';
|
||||||
@import 'menu/menu';
|
@import 'menu/menu';
|
||||||
@import 'numeric-input/numeric-input';
|
@import 'numeric-input/numeric-input';
|
||||||
|
@import 'form-field/index';
|
||||||
@import 'page-container/index';
|
@import 'page-container/index';
|
||||||
@import 'popover/index';
|
@import 'popover/index';
|
||||||
@import 'pulse-loader/index';
|
@import 'pulse-loader/index';
|
||||||
|
34
ui/pages/onboarding-flow/new-account/index.scss
Normal file
34
ui/pages/onboarding-flow/new-account/index.scss
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
.new-account {
|
||||||
|
&__wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__link-text {
|
||||||
|
color: $primary-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__form {
|
||||||
|
padding: 0 24px;
|
||||||
|
|
||||||
|
&--password-button {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--submit-button {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--checkmark {
|
||||||
|
i {
|
||||||
|
color: $success-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-field__input {
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
184
ui/pages/onboarding-flow/new-account/new-account.js
Normal file
184
ui/pages/onboarding-flow/new-account/new-account.js
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
import React, { useState, useMemo } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useHistory } from 'react-router-dom';
|
||||||
|
import { useNewMetricEvent } from '../../../hooks/useMetricEvent';
|
||||||
|
import { useI18nContext } from '../../../hooks/useI18nContext';
|
||||||
|
import Button from '../../../components/ui/button';
|
||||||
|
import Typography from '../../../components/ui/typography';
|
||||||
|
import {
|
||||||
|
TEXT_ALIGN,
|
||||||
|
TYPOGRAPHY,
|
||||||
|
JUSTIFY_CONTENT,
|
||||||
|
FONT_WEIGHT,
|
||||||
|
ALIGN_ITEMS,
|
||||||
|
} from '../../../helpers/constants/design-system';
|
||||||
|
import { INITIALIZE_SEED_PHRASE_INTRO_ROUTE } from '../../../helpers/constants/routes';
|
||||||
|
import FormField from '../../../components/ui/form-field';
|
||||||
|
import Box from '../../../components/ui/box';
|
||||||
|
import CheckBox from '../../../components/ui/check-box';
|
||||||
|
|
||||||
|
export default function NewAccount({ onSubmit }) {
|
||||||
|
const t = useI18nContext();
|
||||||
|
const [confirmPassword, setConfirmPassword] = useState('');
|
||||||
|
const [password, setPassword] = useState('');
|
||||||
|
const [passwordError, setPasswordError] = useState('');
|
||||||
|
const [confirmPasswordError, setConfirmPasswordError] = useState('');
|
||||||
|
const [termsChecked, setTermsChecked] = useState(false);
|
||||||
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
|
const submitPasswordEvent = useNewMetricEvent({
|
||||||
|
event: 'Submit Password',
|
||||||
|
category: 'Onboarding',
|
||||||
|
});
|
||||||
|
|
||||||
|
const isValid = useMemo(() => {
|
||||||
|
if (!password || !confirmPassword || password !== confirmPassword) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (password.length < 8) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !passwordError && !confirmPasswordError;
|
||||||
|
}, [password, confirmPassword, passwordError, confirmPasswordError]);
|
||||||
|
|
||||||
|
const handlePasswordChange = (passwordInput) => {
|
||||||
|
let error = '';
|
||||||
|
let confirmError = '';
|
||||||
|
if (passwordInput && passwordInput.length < 8) {
|
||||||
|
error = t('passwordNotLongEnough');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (confirmPassword && passwordInput !== confirmPassword) {
|
||||||
|
confirmError = t('passwordsDontMatch');
|
||||||
|
}
|
||||||
|
|
||||||
|
setPassword(passwordInput);
|
||||||
|
setPasswordError(error);
|
||||||
|
setConfirmPasswordError(confirmError);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleConfirmPasswordChange = (confirmPasswordInput) => {
|
||||||
|
let error = '';
|
||||||
|
if (password !== confirmPasswordInput) {
|
||||||
|
error = t('passwordsDontMatch');
|
||||||
|
}
|
||||||
|
|
||||||
|
setConfirmPassword(confirmPasswordInput);
|
||||||
|
setConfirmPasswordError(error);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCreate = async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
if (!isValid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (onSubmit) {
|
||||||
|
await onSubmit(password);
|
||||||
|
}
|
||||||
|
submitPasswordEvent();
|
||||||
|
history.push(INITIALIZE_SEED_PHRASE_INTRO_ROUTE);
|
||||||
|
} catch (error) {
|
||||||
|
setPasswordError(error.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="new-account__wrapper">
|
||||||
|
<Typography variant={TYPOGRAPHY.H2} fontWeight={FONT_WEIGHT.BOLD}>
|
||||||
|
{t('createPassword')}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant={TYPOGRAPHY.H4}
|
||||||
|
align={TEXT_ALIGN.CENTER}
|
||||||
|
boxProps={{ margin: 5 }}
|
||||||
|
>
|
||||||
|
{t('passwordSetupDetails')}
|
||||||
|
</Typography>
|
||||||
|
<Box
|
||||||
|
justifyContent={JUSTIFY_CONTENT.CENTER}
|
||||||
|
marginTop={3}
|
||||||
|
padding={[0, 12]}
|
||||||
|
>
|
||||||
|
<form className="new-account__form" onSubmit={handleCreate}>
|
||||||
|
<FormField
|
||||||
|
autoFocus
|
||||||
|
error={passwordError}
|
||||||
|
onChange={handlePasswordChange}
|
||||||
|
password={!showPassword}
|
||||||
|
titleText={t('newPassword')}
|
||||||
|
value={password}
|
||||||
|
titleDetail={
|
||||||
|
<button
|
||||||
|
className="new-account__form--password-button"
|
||||||
|
type="button"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setShowPassword(!showPassword);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{showPassword ? t('hide') : t('show')}
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
onChange={handleConfirmPasswordChange}
|
||||||
|
password={!showPassword}
|
||||||
|
error={confirmPasswordError}
|
||||||
|
titleText={t('confirmPassword')}
|
||||||
|
value={confirmPassword}
|
||||||
|
titleDetail={
|
||||||
|
isValid && (
|
||||||
|
<div className="new-account__form--checkmark">
|
||||||
|
<i className="fas fa-check" />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Box
|
||||||
|
alignItems={ALIGN_ITEMS.CENTER}
|
||||||
|
justifyContent={JUSTIFY_CONTENT.SPACE_BETWEEN}
|
||||||
|
marginBottom={4}
|
||||||
|
>
|
||||||
|
<CheckBox
|
||||||
|
onClick={() => setTermsChecked(!termsChecked)}
|
||||||
|
checked={termsChecked}
|
||||||
|
/>
|
||||||
|
<Typography variant={TYPOGRAPHY.H5} boxProps={{ marginLeft: 3 }}>
|
||||||
|
{t('passwordTermsWarning', [
|
||||||
|
<a
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
key="new-account__link-text"
|
||||||
|
href="https://metamask.io/terms.html"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
<span className="new-account__link-text">
|
||||||
|
{t('learnMore')}
|
||||||
|
</span>
|
||||||
|
</a>,
|
||||||
|
])}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
className="new-account__form--submit-button"
|
||||||
|
disabled={!isValid || !termsChecked}
|
||||||
|
onClick={handleCreate}
|
||||||
|
rounded
|
||||||
|
>
|
||||||
|
{t('createNewWallet')}
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
</Box>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
NewAccount.propTypes = {
|
||||||
|
onSubmit: PropTypes.func,
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user