-
Notifications
You must be signed in to change notification settings - Fork 97
/
choose.js
179 lines (166 loc) · 6.8 KB
/
choose.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import React from 'react';
import TransitionWrapper from '../../../toolbox/transitionWrapper';
import Fees from '../../../../constants/fees';
import { fromRawLsk } from '../../../../utils/lsk';
import { PrimaryButton } from '../../../toolbox/buttons/button';
import ToolBoxInput from '../../../toolbox/inputs/toolBoxInput';
import { FontIcon } from '../../../fontIcon';
import Piwik from '../../../../utils/piwik';
import stepStyles from '../steps.css';
import styles from './choose.css';
class Choose extends React.Component {
constructor() {
super();
this.state = {
step: 'confirm',
delegateName: {
value: '',
error: '',
},
};
this.delegateNameRegEx = new RegExp(/[a-z0-9!@$&_.]+/g); // !@$&_.
this.delegateNameMaxChars = 20;
}
hasEnoughLSK() {
return (fromRawLsk(this.props.account.balance) * 1
>= fromRawLsk(Fees.registerDelegate) * 1);
}
checkSufficientFunds(evt) {
Piwik.trackingEvent('RegisterDelegate_Choose', 'button', 'Choose a name');
if (!this.hasEnoughLSK()) {
evt.preventDefault();
return;
}
this.setState({ step: 'choose' });
}
validateDelegateName(name, value) { // eslint-disable-line max-statements
let error;
const charsNotAllowedInName = value.replace(this.delegateNameRegEx, '');
if (charsNotAllowedInName.length > 0) {
error = this.props.t(`Characters not allowed: "${charsNotAllowedInName}"`);
}
if (!error && value.length > this.delegateNameMaxChars) {
error = this.props.t('Name too long');
}
this.setState({
[name]: {
value,
error: typeof error === 'string' ? error : undefined,
},
});
if (error || value === '') {
return;
}
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
if (value === this.state.delegateName.value) {
this.props.checkDelegateUsernameAvailable(this.state.delegateName.value);
}
}, 250);
}
onNextStep() {
Piwik.trackingEvent('RegisterDelegate_Choose', 'button', 'Next step');
this.props.nextStep({ delegateName: this.state.delegateName.value });
}
render() { // eslint-disable-line
const { t, account } = this.props;
const hasEnoughLSK = this.hasEnoughLSK();
const isDelegate = account.isDelegate;
const delegateNameHasError = (typeof this.state.delegateName.error === 'string' &&
this.state.delegateName.error !== '');
const delegateNameDuplicated = !delegateNameHasError
&& !this.props.delegate.delegateNameQueried &&
this.props.delegate.delegateNameInvalid;
const disableSubmitButton = delegateNameHasError ||
delegateNameDuplicated ||
this.state.delegateName.value === '';
const showCheckingAvailability = this.props.delegate.delegateNameQueried &&
!delegateNameDuplicated;
const showInfoNameAvailable = !delegateNameHasError &&
this.state.delegateName.value !== '' &&
!delegateNameDuplicated;
const showInfoValidation = !showInfoNameAvailable &&
!delegateNameHasError &&
!delegateNameDuplicated &&
!showCheckingAvailability;
return (
<section>
<TransitionWrapper current={this.state.step} step='confirm'>
<div className={stepStyles.container}>
<div className={stepStyles.firstContainer}>
<header>
<h5 className={stepStyles.heading}>
{t('Become a delegate')}
</h5>
</header>
<p className={stepStyles.description}>
{t('Delegates have great responsibility within the Lisk system for securing the blockchain. Becoming a delegate requires the registration of a name. The top 101 delegates are eligible to forge.')}
</p>
</div>
<div className={stepStyles.secondContainer}>
<form className={stepStyles.form} onSubmit={this.checkSufficientFunds.bind(this)}>
<PrimaryButton
disabled={!hasEnoughLSK || isDelegate}
label={t('Choose a name')}
className={`${stepStyles.chooseNameBtn} choose-name`}
onClick={this.checkSufficientFunds.bind(this)}
/>
{!hasEnoughLSK ? <p className={stepStyles.error}>
{t('Insufficient funds (Fee: {{fee}} LSK)', { fee: fromRawLsk(Fees.registerDelegate) })}
</p> : null }
{isDelegate ? <p className={stepStyles.error}>
{t('You have already registered as a delegate.')}
</p> : null }
</form>
</div>
</div>
</TransitionWrapper>
<TransitionWrapper current={this.state.step} step='choose'>
<div className={stepStyles.container}>
<div className={stepStyles.firstContainer}>
<header>
<h5 className={stepStyles.heading}>
{t('Choose your name')}
</h5>
</header>
</div>
<div className={`${stepStyles.secondContainer} ${stepStyles.containerWithBg}`}>
<form className={`${stepStyles.form}`}
onSubmit={this.validateDelegateName.bind(this, 'delegateName')}>
<ToolBoxInput
placeholder={this.props.t('Write to check availability')}
required={true}
shouldfocus="true"
className={`${styles.delegateNameInput} delegate-name`}
onChange={this.validateDelegateName.bind(this, 'delegateName')}
error={this.state.delegateName.error}
value={this.state.delegateName.value} />
{delegateNameDuplicated ? <p className={`${stepStyles.error} ${stepStyles.errorInline} error-name-duplicate`}>
{t('Name is already taken!')}
</p> : null }
{showCheckingAvailability ? <p className={`${stepStyles.info} info`}>
<FontIcon value='more' />
{t('checking availability')}
</p> : null }
{showInfoNameAvailable ? <p className={`${stepStyles.info} info`}>
<FontIcon value='checkmark' />
{t('Name is available')}
</p> : null }
{showInfoValidation ? <p className={stepStyles.info}>
{t('Max 20 characters, a-z and 0-1, no special characters except for “!@$&.”')}
</p> : null }
<PrimaryButton
disabled={disableSubmitButton}
label={t('Next')}
className={`${stepStyles.chooseNameBtn} submit-delegate-name`}
onClick={() => this.onNextStep()}
/>
</form>
</div>
</div>
</TransitionWrapper>
</section>
);
}
}
export default Choose;