sms verification: use Mobx store
This commit is contained in:
parent
bfcc8d33d6
commit
3e879aac35
@ -15,14 +15,20 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
import ActionDoneAll from 'material-ui/svg-icons/action/done-all';
|
||||
import ContentClear from 'material-ui/svg-icons/content/clear';
|
||||
|
||||
import { Button, IdentityIcon, Modal } from '../../ui';
|
||||
|
||||
import ABI from '../../contracts/abi/sms-verification.json';
|
||||
// TODO: move this to a better place
|
||||
const contract = '0xcE381B876A85A72303f7cA7b3a012f58F4CEEEeB';
|
||||
import VerificationStore from './store';
|
||||
const {
|
||||
GATHERING_DATA, GATHERED_DATA,
|
||||
POSTING_REQUEST, POSTED_REQUEST,
|
||||
REQUESTING_SMS, REQUESTED_SMS,
|
||||
POSTING_CONFIRMATION, POSTED_CONFIRMATION,
|
||||
DONE
|
||||
} = VerificationStore;
|
||||
|
||||
import GatherData from './GatherData';
|
||||
import SendRequest from './SendRequest';
|
||||
@ -30,6 +36,7 @@ import QueryCode from './QueryCode';
|
||||
import SendConfirmation from './SendConfirmation';
|
||||
import Done from './Done';
|
||||
|
||||
@observer
|
||||
export default class SMSVerification extends Component {
|
||||
static contextTypes = {
|
||||
api: PropTypes.object.isRequired
|
||||
@ -40,41 +47,51 @@ export default class SMSVerification extends Component {
|
||||
onClose: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
static uiSteps = { // mapping (store steps -> steps)
|
||||
[GATHERING_DATA]: 0, [GATHERED_DATA]: 0,
|
||||
[POSTING_REQUEST]: 1, [POSTED_REQUEST]: 1, [REQUESTING_SMS]: 1,
|
||||
[REQUESTED_SMS]: 2,
|
||||
[POSTING_CONFIRMATION]: 3, [POSTED_CONFIRMATION]: 3,
|
||||
[DONE]: 4
|
||||
}
|
||||
|
||||
state = {
|
||||
contract: null,
|
||||
step: 0,
|
||||
stepIsValid: false,
|
||||
data: {}
|
||||
store: null
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
const { api } = this.context;
|
||||
const { account } = this.props;
|
||||
|
||||
this.setState({
|
||||
contract: api.newContract(ABI, contract)
|
||||
const store = new VerificationStore(api, account);
|
||||
this.setState({ store }, () => {
|
||||
store.gatherData();
|
||||
});
|
||||
}
|
||||
|
||||
render () {
|
||||
const { step } = this.state;
|
||||
const { store } = this.state;
|
||||
if (!store) return null;
|
||||
const step = SMSVerification.uiSteps[store.step];
|
||||
const { error, isStepValid } = store;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
actions={ this.renderDialogActions() }
|
||||
actions={ this.renderDialogActions(step, error, isStepValid) }
|
||||
title='verify your account via SMS'
|
||||
visible scroll
|
||||
current={ step }
|
||||
steps={ ['Enter Data', 'Request', 'Enter Code', 'Confirm', 'Done!'] }
|
||||
waiting={ [ 1, 3 ] }
|
||||
>
|
||||
{ this.renderStep() }
|
||||
{ this.renderStep(step, error) }
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
renderDialogActions () {
|
||||
renderDialogActions (step, error, isStepValid) {
|
||||
const { onClose, account } = this.props;
|
||||
const { step, stepIsValid } = this.state;
|
||||
const { store } = this.state;
|
||||
|
||||
const cancel = (
|
||||
<Button
|
||||
@ -83,6 +100,7 @@ export default class SMSVerification extends Component {
|
||||
onClick={ onClose }
|
||||
/>
|
||||
);
|
||||
if (error) return (<div>{ cancel }</div>);
|
||||
|
||||
if (step === 4) {
|
||||
return (
|
||||
@ -90,7 +108,7 @@ export default class SMSVerification extends Component {
|
||||
{ cancel }
|
||||
<Button
|
||||
key='done' label='Done'
|
||||
disabled={ !stepIsValid }
|
||||
disabled={ !isStepValid }
|
||||
icon={ <ActionDoneAll /> }
|
||||
onClick={ onClose }
|
||||
/>
|
||||
@ -98,116 +116,62 @@ export default class SMSVerification extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
let action;
|
||||
if (step === 3) {
|
||||
action = store.done;
|
||||
} else if (step === 2) {
|
||||
action = store.sendConfirmation;
|
||||
} else if (step === 1) {
|
||||
action = store.queryCode;
|
||||
} else if (step === 0) {
|
||||
action = store.sendRequest;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{ cancel }
|
||||
<Button
|
||||
key='next' label='Next'
|
||||
disabled={ !stepIsValid }
|
||||
disabled={ !isStepValid }
|
||||
icon={ <IdentityIcon address={ account } button /> }
|
||||
onClick={ this.next }
|
||||
onClick={ action }
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderStep () {
|
||||
const { contract } = this.state;
|
||||
if (!contract) {
|
||||
return null;
|
||||
}
|
||||
renderStep (step, error) {
|
||||
if (error) return (<p>{ error }</p>);
|
||||
|
||||
const {
|
||||
fee, isNumberValid, isVerified, hasRequested,
|
||||
requestTx, isCodeValid, confirmationTx,
|
||||
setNumber, setConsentGiven, setCode
|
||||
} = this.state.store;
|
||||
|
||||
const { step } = this.state;
|
||||
if (step === 4) {
|
||||
return this.renderFifthStep();
|
||||
} else if (step === 3) {
|
||||
return this.renderFourthStep();
|
||||
} else if (step === 2) {
|
||||
return this.renderThirdStep();
|
||||
} else if (step === 1) {
|
||||
return this.renderSecondStep();
|
||||
} else {
|
||||
return this.renderFirstStep();
|
||||
return (<Done />);
|
||||
}
|
||||
}
|
||||
|
||||
onDataIsValid = () => {
|
||||
this.setState({ stepIsValid: true });
|
||||
}
|
||||
onDataIsInvalid = () => {
|
||||
this.setState({ stepIsValid: false });
|
||||
}
|
||||
onData = (data) => {
|
||||
this.setState({
|
||||
data: Object.assign({}, this.state.data, data)
|
||||
});
|
||||
}
|
||||
|
||||
next = () => {
|
||||
const { stepIsValid } = this.state;
|
||||
if (stepIsValid) {
|
||||
this.setState({ step: this.state.step + 1, stepIsValid: false });
|
||||
if (step === 3) {
|
||||
return (<SendConfirmation step={ step } tx={ confirmationTx } />);
|
||||
}
|
||||
if (step === 2) {
|
||||
return (<QueryCode fee={ fee } isCodeValid={ isCodeValid } setCode={ setCode } />);
|
||||
}
|
||||
if (step === 1) {
|
||||
return (<SendRequest step={ step } tx={ requestTx } />);
|
||||
}
|
||||
if (step === 0) {
|
||||
const { setNumber, setConsentGiven } = this.state.store;
|
||||
return (
|
||||
<GatherData
|
||||
fee={ fee } isNumberValid={ isNumberValid }
|
||||
isVerified={ isVerified } hasRequested={ hasRequested }
|
||||
setNumber={ setNumber } setConsentGiven={ setConsentGiven }
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
renderFirstStep () {
|
||||
const { account } = this.props;
|
||||
const { contract, data } = this.state;
|
||||
|
||||
return (
|
||||
<GatherData
|
||||
account={ account } contract={ contract } data={ data }
|
||||
onData={ this.onData }
|
||||
onDataIsValid={ this.onDataIsValid }
|
||||
onDataIsInvalid={ this.onDataIsInvalid }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
renderSecondStep () {
|
||||
const { account } = this.props;
|
||||
const { contract, data } = this.state;
|
||||
|
||||
return (
|
||||
<SendRequest
|
||||
account={ account } contract={ contract } data={ data }
|
||||
onData={ this.onData }
|
||||
onSuccess={ this.onDataIsValid }
|
||||
onError={ this.onDataIsInvalid }
|
||||
nextStep={ this.next }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
renderThirdStep () {
|
||||
const { data } = this.state;
|
||||
|
||||
return (
|
||||
<QueryCode
|
||||
data={ data }
|
||||
onData={ this.onData }
|
||||
onDataIsValid={ this.onDataIsValid }
|
||||
onDataIsInvalid={ this.onDataIsInvalid }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
renderFourthStep () {
|
||||
const { account } = this.props;
|
||||
const { contract, data } = this.state;
|
||||
|
||||
return (
|
||||
<SendConfirmation
|
||||
account={ account } contract={ contract } data={ data }
|
||||
onData={ this.onData }
|
||||
onSuccess={ this.onDataIsValid }
|
||||
onError={ this.onDataIsInvalid }
|
||||
nextStep={ this.next }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
renderFifthStep () {
|
||||
return (<Done onSuccess={ this.onDataIsValid } />);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +60,39 @@ export default class VerificationStore {
|
||||
return phone.isValidNumber(this.number);
|
||||
}
|
||||
|
||||
@computed get isStepValid () {
|
||||
if (this.step === VerificationStore.DONE) {
|
||||
return true;
|
||||
}
|
||||
if (this.error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.step === VerificationStore.GATHERED_DATA) {
|
||||
return this.fee && this.isVerified === false && this.isNumberValid && this.consentGiven;
|
||||
}
|
||||
if (this.step === VerificationStore.REQUESTED_SMS) {
|
||||
return this.requestTx;
|
||||
}
|
||||
if (this.step === VerificationStore.QUERY_CODE) {
|
||||
return this.isCodeValid;
|
||||
}
|
||||
if (this.step === VerificationStore.POSTED_CONFIRMATION) {
|
||||
return this.confirmationTx;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@action setNumber = (number) => {
|
||||
this.number = number;
|
||||
}
|
||||
@action setConsentGiven = (consentGiven) => {
|
||||
this.consentGiven = consentGiven;
|
||||
}
|
||||
@action setCode = (code) => {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
constructor (api, account) {
|
||||
this.api = api;
|
||||
this.account = account;
|
||||
@ -106,14 +139,6 @@ export default class VerificationStore {
|
||||
});
|
||||
}
|
||||
|
||||
@action setNumber = (number) => {
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
@action setConsentGiven = (consentGiven) => {
|
||||
this.consentGiven = consentGiven;
|
||||
}
|
||||
|
||||
@action sendRequest = () => {
|
||||
const { api, account, contract, fee, number, hasRequested } = this;
|
||||
|
||||
@ -153,8 +178,8 @@ export default class VerificationStore {
|
||||
});
|
||||
}
|
||||
|
||||
@action setCode = (code) => {
|
||||
this.code = code;
|
||||
@action queryCode = () => {
|
||||
this.step = VerificationStore.QUERY_CODE;
|
||||
}
|
||||
|
||||
@action sendConfirmation = () => {
|
||||
@ -188,4 +213,8 @@ export default class VerificationStore {
|
||||
this.error = 'Failed to send the verification code: ' + err.message;
|
||||
});
|
||||
}
|
||||
|
||||
@action done = () => {
|
||||
this.step = VerificationStore.DONE;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user