feat: resend otp

This commit is contained in:
Hasta Ragil Saputra 2019-02-01 17:50:49 +07:00
parent 40921c6af5
commit 534d1dfa96
6 changed files with 387 additions and 9 deletions

View File

@ -77,10 +77,11 @@ class BTNLoginPage extends React.Component{
// res.message // res.message
} }
}) })
} else {
//redirect register
this.props.history.replace(LINKS.REGISTER);
} }
//redirect register
this.props.history.replace(LINKS.REGISTER);
} }
handleChange = name => event => { handleChange = name => event => {

View File

@ -82,9 +82,19 @@ class OtpPage extends React.Component{
resendCode = () => { resendCode = () => {
this.setState({isResending:true}); this.setState({isResending:true});
setTimeout(()=>{
this.setState({isResending:false}); return this.props.appstate.http.post('authentication/resend_otp_by_login_request', {
},3000); login_request_id: this.state.otpData.login_request_id
}).then(res => {
this.setState({
otpData:{
login_request_id : res.login_request_id,
expired_at : res.expired_at
}
});
message.info('Kirim ulang sukses');
this.setState({isResending:false});
});
}; };
login = () => { login = () => {
@ -160,9 +170,9 @@ class OtpPage extends React.Component{
<Typography variant="h6" gutterBottom> <Typography variant="h6" gutterBottom>
Masukkan Kode OTP Anda Masukkan Kode OTP Anda
</Typography> </Typography>
{/*<Typography variant="subtitle2" gutterBottom>*/} <Typography variant="subtitle2" gutterBottom>
{/*Still not received OTP Code? <a onClick={()=>this.resendCode()}>Resend Code</a>*/} Belum menerima OTP? <a onClick={()=>this.resendCode()}>Kirim Ulang</a>
{/*</Typography>*/} </Typography>
<Grid container justify="center" spacing={8}> <Grid container justify="center" spacing={8}>
{[0, 1, 2, 3, 4, 5].map(x => ( {[0, 1, 2, 3, 4, 5].map(x => (
<Grid item xs={1}> <Grid item xs={1}>

View File

@ -545,7 +545,7 @@ class RegisterPage extends React.Component {
<div style={{ padding: 5, marginTop: 20 }}> <div style={{ padding: 5, marginTop: 20 }}>
<Button <Button
fullWidth fullWidth
variant="contained" style={{ backgroundColor: '#ffeb3b' }} onClick={this.register}> variant="contained" style={{ backgroundColor: '#ffeb3b',marginBottom: 16 }} onClick={this.register}>
{this.state.isLoading ? <CircularProgress className={classes.progress} /> : "Daftar"} {this.state.isLoading ? <CircularProgress className={classes.progress} /> : "Daftar"}
</Button> </Button>

View File

@ -0,0 +1,326 @@
import React from 'react';
import withStyles from "@material-ui/core/styles/withStyles";
import { styles } from './styles';
import Grid from '@material-ui/core/Grid';
import Paper from '@material-ui/core/Paper';
import Typography from '@material-ui/core/Typography';
import TextField from '@material-ui/core/TextField';
import Visibility from '@material-ui/icons/Visibility';
import VisibilityOff from '@material-ui/icons/VisibilityOff';
import Button from '@material-ui/core/Button';
import Hidden from '@material-ui/core/Hidden';
import InputAdornment from '@material-ui/core/InputAdornment';
import IconButton from '@material-ui/core/IconButton';
import CircularProgress from '@material-ui/core/CircularProgress';
import Snackbar from '@material-ui/core/Snackbar';
import { Link } from 'react-router-dom'
import { inject, observer } from "mobx-react";
import schema from 'async-validator'
import { startCase } from 'lodash';
import { Upload, Icon, message } from 'antd';
import AutoComplete from './../../components/AutoComplete';
import {appConfig} from "../../config/app";
import {LINKS} from "../../routes";
// const province = require("./../../../../assets/data/province.json");
// const city = require("./../../../../assets/data/city.json");
// const district = require("./../../../../assets/data/district.json");
// const subdistrict = require("./../../../../assets/data/subdistrict.json");
@withStyles(styles)
@inject('appstate')
@observer
export class ResendOtp extends React.Component {
state = {
showPassword: false,
showConfirmPassword: false,
openDialog: false,
isLoading: false,
fileList_ktp: [],
fileList_photo: [],
query: {},
// form
confirmPassword: "",
phone_number: "",
email: "",
password: "",
full_name: "",
no_ktp: '',
upload_ktp: '',
upload_photo: '',
address: '',
province: '',
city: '',
district: '',
sub_district: '',
zip_code: '',
};
constructor(props) {
super(props);
this.authStore = props.appstate.auth;
this.http = props.appstate.http;
this.place = props.appstate.places;
}
componentDidMount() {
let {location:{search}} = this.props;
search = search.substr(1);
const query = search.split("&")
.map(q => q.split('='))
.reduce((all, q) => {
all[q[0]] = q[1];
return all;
}, {});
this.setState({query});
this.place.getAllProvince();
}
onChangeProvince = (value) => {
this.setState({
province: value
});
this.place.getCitiesByProvince(value);
};
onChangeCity = (value) => {
this.setState({
city: value
});
this.place.getDistrictByCity(value);
};
onChangeDistrict = (value) => {
this.setState({
district: value
});
this.place.getSubdistrictByDistrict(value);
};
onChangeSubdistrict = (value) => {
this.setState({
subdistrict: value
});
};
handleChange = name => event => {
this.setState({
[name]: event.target.value,
});
};
viewPassword = () => {
this.setState({
showPassword: !this.state.showPassword
})
};
viewConfirmPassword = () => {
this.setState({
showConfirmPassword: !this.state.showConfirmPassword
})
};
resendOtp = () => {
return this.props.appstate.http.post('authentication/resend_otp', {
phone_number: this.state.phone_number
}).then(res => {
//message.success("Please check your email to confirm your account");this.props.history.push(LINKS.LOGIN);
setTimeout(() => {
this.setState({ isLoading: false });
this.props.history.push({
pathname:LINKS.OTP,
search:'?login_request_id='+res.login_request_id+'&expired_at='+res.expired_at
});
// this.props.history.push(LINKS.LOGIN);
}, 250);
}).catch(err => {
if (err.type === 'BodyValidationError') {
message.error(err.detail[0].message);
} else {
message.error(err.message);
}
});
};
handleChangeUploadKtp = (info) => {
if (info.file.status === 'uploading') {
this.setState({ loading: true });
return;
}
if (info.file.status === 'done') {
// Get this url from response in real world.
getBase64(info.file.originFileObj, imageUrl => this.setState({
upload_ktp,
loading: false,
}));
}
};
handleChangeUploadPhoto = (info) => {
if (info.file.status === 'uploading') {
this.setState({ loading: true });
return;
}
if (info.file.status === 'done') {
// Get this url from response in real world.
getBase64(info.file.originFileObj, imageUrl => this.setState({
upload_photo,
loading: false,
}));
}
};
uploadOnChange = (key, info) => {
let fileList = info.fileList;
this.setState({
[`fileList_${key}`]: fileList
})
};
createUploadProps = (key) => {
return {
name: 'file',
multiple: false,
action: appConfig.apiUrl + 'upload',
customRequest: ({file, onProgress, onSuccess}) => {
this.setState({
uploading: true
});
this.http.upload(file)
.then(res => {
this.setState({
[`upload_${key}`]: appConfig.apiUrl + res.path.slice(1,res.path.length)
});
return res;
})
.then(res => {
message.success(`${file.name} file uploaded successfully.`);
const fileList = this.state[`fileList_${key}`];
console.log(key, fileList, this.state);
const selectedIndex = fileList.findIndex(f => f.name === file.name);
fileList[selectedIndex].status = "done";
fileList[selectedIndex].path = res.path;
onSuccess(fileList[selectedIndex]);
// form.setFieldsValue({path: res.path});
this.setState({
uploading: false,
// fileList: []
[`fileList_${key}`]: [fileList[selectedIndex]]
});
});
return {
abort: () => {}
}
},
fileList: this.state[`fileList_${key}`],
onChange: (info) => this.uploadOnChange(key, info),
onRemove: file => true
};
};
render() {
const { classes } = this.props;
const uploadButtonKtp = (
<div>
<Icon type={this.state.loading ? 'loading' : 'plus'} />
<div className="ant-upload-text">Upload KTP</div>
</div>
);
const uploadButtonPhoto = (
<div>
<Icon type={this.state.loading ? 'loading' : 'plus'} />
<div className="ant-upload-text">Upload Photo</div>
</div>
);
const upload_ktp = this.state.upload_ktp;
const upload_photo = this.state.upload_photo;
return (
<div className={classes.container}>
{/*<AlertSuccess open={appStore.global_ui.openSuccess} onClose={()=>appStore.global_ui.closeAlertSuccess()}/>*/}
<Grid container spacing={0} className={classes.gridContainer}>
<Grid item cols={12} className={classes.logoContainer}>
<img src={require('../../../../assets/images/logo_new.png')} className={classes.logo} />
</Grid>
<Grid item xs={12} sm={12} md={10} lg={10} className={classes.registerContainer} style={{
alignSelf: 'center'
}}>
<Grid container spacing={24} className={classes.registerPaper}>
<Hidden smDown>
<Grid item xs={5}>
<img src={require('../../../../assets/images/register_image_2.png')} width={"80%"} />
<Typography style={{ color: '#FFF' }} variant={"h6"}>
Tukarkan point!
</Typography>
<Typography style={{ color: '#FFF' }} variant={"subtitle2"}>
Dapatkan promo dan keuntungan dengan BTN
</Typography>
</Grid>
</Hidden>
<Grid item xs={12} sm={12} md={7} style={{ paddingLeft: 50, paddingRight: 50 }}>
<Paper className={classes.formRegister}>
<Typography variant="h6" gutterBottom>
Daftar Sekarang
</Typography>
{/*<Typography variant="subtitle2" gutterBottom>*/}
{/*Already have an account? <Link to={"/login"} replace>Back to Login</Link>*/}
{/*</Typography>*/}
<div style={{
display: 'flex',
flexDirection: 'row'
}}>
<Grid item xs={12} sm={12} md={12} style={{ paddingLeft: 5, paddingRight: 5 }}>
<TextField
id="phone"
label="Nomer Telfon"
value={this.state.phone_number}
onChange={this.handleChange('phone_number')}
margin="normal"
type={"number"}
variant="outlined"
fullWidth
/>
</Grid>
</div>
<div style={{ padding: 5, marginTop: 20 }}>
<Button
fullWidth
variant="contained" style={{ backgroundColor: '#ffeb3b' }} onClick={this.resendOtp}>
{this.state.isLoading ? <CircularProgress className={classes.progress} /> : "Kirim ulang OTP"}
</Button>
</div>
</Paper>
</Grid>
</Grid>
</Grid>
</Grid>
</div>
)
}
}

View File

@ -0,0 +1,38 @@
import yellow from '@material-ui/core/colors/yellow';
export const styles = theme => ({
container : {
flex :1,
flexGrow : 1,
height : '100%',
backgroundColor:'#024f8e',
marginTop: '-56px',
paddingBottom:50
},
gridContainer : {
flex :1,
justifyContent: 'center',
flexDirection: 'column'
},
registerContainer: {
marginTop : 50
},
formRegister : {
padding : 20,
display : 'flex',
flexDirection: 'column',
textAlign : 'center'
},
registerPaper : {
flex :1,
flexDirection : 'row',
justifyContent:'center'
},
logo : {
width : '200px'
},
logoContainer : {
textAlign : 'center',
background : yellow['500'],
padding : 20
},
});

View File

@ -14,6 +14,7 @@ import OtpPage from "./pages/Otp";
import RegisterCompletedComponent from "./pages/RegisterCompleted"; import RegisterCompletedComponent from "./pages/RegisterCompleted";
import ResendEmail from "./pages/ResendEmail"; import ResendEmail from "./pages/ResendEmail";
import ConfirmationCompletedComponent from "./pages/ConfirmationCompleted"; import ConfirmationCompletedComponent from "./pages/ConfirmationCompleted";
import {ResendOtp} from "./pages/ResendOtp";
export const LINKS = { export const LINKS = {
ROOT: '/', ROOT: '/',
@ -82,6 +83,7 @@ export const LINKS = {
ORDER_DETAIL_AIRLINES_WO_ID: '/app/order_detail_airline', ORDER_DETAIL_AIRLINES_WO_ID: '/app/order_detail_airline',
REGISTER: '/register', REGISTER: '/register',
RESEND_EMAIL: '/resend_email', RESEND_EMAIL: '/resend_email',
RESEND_OTP: '/resend_otp',
REGISTER_COMPLETED: '/register_completed', REGISTER_COMPLETED: '/register_completed',
CONFIRMATION_COMPLETED: '/confirmation_completed', CONFIRMATION_COMPLETED: '/confirmation_completed',
LOGIN: '/login', LOGIN: '/login',
@ -166,6 +168,7 @@ export default class Routes extends React.Component {
}}/>)}/> }}/>)}/>
<Route exact path={LINKS.REGISTER} component={RegisterComponent}/> <Route exact path={LINKS.REGISTER} component={RegisterComponent}/>
<Route exact path={LINKS.RESEND_EMAIL} component={ResendEmail}/> <Route exact path={LINKS.RESEND_EMAIL} component={ResendEmail}/>
<Route exact path={LINKS.RESEND_OTP} component={ResendOtp}/>
<Route exact path={LINKS.REGISTER_COMPLETED} component={RegisterCompletedComponent}/> <Route exact path={LINKS.REGISTER_COMPLETED} component={RegisterCompletedComponent}/>
<Route exact path={LINKS.CONFIRMATION_COMPLETED} component={ConfirmationCompletedComponent}/> <Route exact path={LINKS.CONFIRMATION_COMPLETED} component={ConfirmationCompletedComponent}/>
<Route exact path={LINKS.LOGIN} component={LoginBTNComponent}/> <Route exact path={LINKS.LOGIN} component={LoginBTNComponent}/>