pages navbar new

This commit is contained in:
enggar_ganteng 2019-01-29 19:16:57 +07:00
commit fbb2cc0a9b
19 changed files with 639 additions and 211 deletions

105
package-lock.json generated
View File

@ -4961,6 +4961,11 @@
}
}
},
"css-mediaquery": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/css-mediaquery/-/css-mediaquery-0.1.2.tgz",
"integrity": "sha1-aiw3NEkoYYYxxUvTPO3TAdoYvqA="
},
"css-select": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-2.0.2.tgz",
@ -7014,13 +7019,11 @@
},
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"optional": true
"bundled": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -7033,18 +7036,15 @@
},
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"optional": true
"bundled": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"optional": true
"bundled": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"optional": true
"bundled": true
},
"core-util-is": {
"version": "1.0.2",
@ -7147,8 +7147,7 @@
},
"inherits": {
"version": "2.0.3",
"bundled": true,
"optional": true
"bundled": true
},
"ini": {
"version": "1.3.5",
@ -7158,7 +7157,6 @@
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -7171,20 +7169,17 @@
"minimatch": {
"version": "3.0.4",
"bundled": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.8",
"bundled": true,
"optional": true
"bundled": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@ -7201,7 +7196,6 @@
"mkdirp": {
"version": "0.5.1",
"bundled": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -7274,8 +7268,7 @@
},
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"optional": true
"bundled": true
},
"object-assign": {
"version": "4.1.1",
@ -7285,7 +7278,6 @@
"once": {
"version": "1.4.0",
"bundled": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -7391,7 +7383,6 @@
"string-width": {
"version": "1.0.2",
"bundled": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@ -10740,6 +10731,14 @@
"resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.2.tgz",
"integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA=="
},
"matchmediaquery": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/matchmediaquery/-/matchmediaquery-0.3.0.tgz",
"integrity": "sha512-u0dlv+VENJ+3YepvwSPBieuvnA6DWfaYa/ctwysAR13y4XLJNyt7bEVKzNj/Nvjo+50d88Pj+xL9xaSo6JmX/w==",
"requires": {
"css-mediaquery": "^0.1.2"
}
},
"material-colors": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz",
@ -14837,6 +14836,60 @@
}
}
},
"react-html-parser": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/react-html-parser/-/react-html-parser-2.0.2.tgz",
"integrity": "sha512-XeerLwCVjTs3njZcgCOeDUqLgNIt/t+6Jgi5/qPsO/krUWl76kWKXMeVs2LhY2gwM6X378DkhLjur0zUQdpz0g==",
"requires": {
"htmlparser2": "^3.9.0"
},
"dependencies": {
"domelementtype": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
"integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
},
"domhandler": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
"integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
"requires": {
"domelementtype": "1"
}
},
"htmlparser2": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.0.tgz",
"integrity": "sha512-J1nEUGv+MkXS0weHNWVKJJ+UrLfePxRWpN3C9bEi9fLxL2+ggW94DQvgYVXsaT30PGwYRIZKNZXuyMhp3Di4bQ==",
"requires": {
"domelementtype": "^1.3.0",
"domhandler": "^2.3.0",
"domutils": "^1.5.1",
"entities": "^1.1.1",
"inherits": "^2.0.1",
"readable-stream": "^3.0.6"
}
},
"readable-stream": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz",
"integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==",
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
}
},
"string_decoder": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz",
"integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==",
"requires": {
"safe-buffer": "~5.1.0"
}
}
}
},
"react-images": {
"version": "0.5.19",
"resolved": "https://registry.npmjs.org/react-images/-/react-images-0.5.19.tgz",
@ -15119,6 +15172,16 @@
"resize-observer-polyfill": "^1.5.0"
}
},
"react-responsive": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-6.1.1.tgz",
"integrity": "sha512-Po6pOEz70Agp+2lUmTxAnhfdkk0zp0IFgo/6bGcxv/S4Pa1sz0YG06WzkrIcASbyKSQ8x6AkcggeozXW3zj3kA==",
"requires": {
"hyphenate-style-name": "^1.0.0",
"matchmediaquery": "^0.3.0",
"prop-types": "^15.6.1"
}
},
"react-responsive-carousel": {
"version": "3.1.46",
"resolved": "https://registry.npmjs.org/react-responsive-carousel/-/react-responsive-carousel-3.1.46.tgz",

View File

@ -17,7 +17,9 @@
"dev:parcel": "node scripts/dev-parcel.js",
"deploy": "rsync -chavzP -e \"ssh -p 2222\" --stats dist/ root@209.58.165.19:/home/apps/giift/giift-customer-btn",
"deploy:giift": "rsync -chavzP -e \"ssh -p 2222\" --stats dist/ root@209.58.165.19:/home/apps/giift/giift-customer",
"dev2:parcel": "node scripts/link-assets.js; parcel public/index.parcel.html --out-file index.html --global $"
"dev2:parcel": "node scripts/link-assets.js; parcel public/index.parcel.html --out-file index.html --global $",
"build2:parcel:prod": "node scripts/link-assets.js; parcel build public/index.parcel.html --out-file index.html --detailed-report --no-source-maps",
"build:deploy": "npm run build:parcel:prod && npm run deploy"
},
"author": "Asacreative",
"repository": {
@ -112,6 +114,7 @@
"react-handsontable": "^0.3.1",
"react-helmet": "^5.2.0",
"react-hot-loader": "^4.6.3",
"react-html-parser": "^2.0.2",
"react-images": "^0.5.13",
"react-infinite-scroller": "^1.2.4",
"react-intl": "^2.8.0",
@ -123,6 +126,7 @@
"react-native-vector-icons": "^5.0.0",
"react-number-format": "^3.0.3",
"react-prop-types": "^0.4.0",
"react-responsive": "^6.1.1",
"react-responsive-carousel": "^3.1.46",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",

View File

@ -480,7 +480,7 @@ class App extends React.Component {
.bind(this, '/app/dashboard')} to={LINKS.DASHBOARD}><MenuItem
className={(this.state.selectedMenu === '/app/dashboard') ? "menuAkunItem active" : 'menuAkunItem'}><span
className="menuAkun">Home</span></MenuItem></Link>
<Link onClick={this
{/* <Link onClick={this
.changeRoute
.bind(this, '/app/dashboard')} to={LINKS.DASHBOARD}><MenuItem
className={(this.state.selectedMenu === '/app/flight') ? "menuAkunItem active" : 'menuAkunItem'}><span
@ -510,7 +510,7 @@ class App extends React.Component {
to={LINKS.VOUCHERS}
><MenuItem
className={(this.state.selectedMenu === '/app/vouchers') ? "menuAkunItem active" : 'menuAkunItem'}><span
className="menuAkun">Vouchers</span></MenuItem></Link>
className="menuAkun">Vouchers</span></MenuItem></Link> */}
</List>
<Divider />
@ -865,9 +865,9 @@ class App extends React.Component {
style={{ padding: '0px 16px 0px', fontSize: 14 }}
disabled={true}
primaryText={<span
style={{ fontWeight: 500 }}>{this.authStore.userProfile.username || 'Username'}</span>}
style={{ fontWeight: 500 }}>{this.props.appstate.userData.email|| 'Username'}</span>}
secondaryText={<p
style={{ fontWeight: 400 }}>{_.capitalize(this.authStore.userProfile.role) || 'role'}</p>}
style={{ fontWeight: 400 }}>{_.capitalize(this.props.appstate.userData.role) || 'role'}</p>}
/>
</List>
<Divider />

View File

@ -1,6 +1,7 @@
import React from 'react';
import withStyles from "@material-ui/core/styles/withStyles";
import {styles} from '../Register/registerStyle';
import {notification} from 'antd';
import Grid from '@material-ui/core/Grid';
import Paper from '@material-ui/core/Paper';
@ -43,7 +44,43 @@ class BTNLoginPage extends React.Component{
this.authStore = props.appstate.auth;
}
handleChange = name => event => {
componentDidMount() {
const urlParams = new URLSearchParams(window.location.search);
if(urlParams.has('key')) {
this.setState({
isLoading: true
});
this.authStore.verifyEmail(urlParams.get('key')).then((res) => {
if(res.login_request_id) {
notification.open({
message: 'Email Verification',
description: 'Email verification success'
});
this.setState({
isLoading: false
});
this.props.history.push({
pathname:LINKS.OTP,
search:'?login_request_id='+res.login_request_id+'&expired_at='+res.expired_at
});
//redirect to otp page
} else {
notification.open({
message: 'Email Verification',
description: res.message
});
this.setState({
isLoading: false
});
// res.message
}
})
}
}
handleChange = name => event => {
this.setState({
[name]: event.target.value,
});
@ -74,6 +111,16 @@ class BTNLoginPage extends React.Component{
else if(res.state == "email_verification"){
this.setState({isNeedEmailVerification:true,isLoading:false});
}
else if(res.state == "phone_verification"){
this.authStore.otpData = res;
setTimeout(()=>{
this.props.history.push({
pathname:LINKS.OTP,
search:'?login_request_id='+res.login_request_id+'&expired_at='+res.expired_at
});
this.setState({isLoading:false});
},1000);
}
}).catch(err => {
console.log("err login",err);
this.setState({loginFailed:true,isLoading:false});
@ -131,15 +178,15 @@ class BTNLoginPage extends React.Component{
</Hidden>
<Grid item xs={12} sm={12} md={6} style={{paddingLeft : 50,paddingRight : 50}}>
{
this.state.isNeedEmailVerification &&
this.state.isNeedEmailVerification &&
<Paper className={classes.formRegister}>
<Typography variant="h6" gutterBottom>
Your account still need email verification
</Typography>
<Typography variant="subtitle2" gutterBottom>
Still not received any email? <Link to={"/register"}>Resend email</Link>
Still not received any email? <a onClick={()=>this.authStore.resendEmail(this.state.email)}>Resend email</a>
</Typography>
<div style={{padding : 5,marginTop : 20}}>
<Button onClick={() => this.setState({isNeedEmailVerification : false})} fullWidth variant="contained" style={{background:'#ffeb3b'}}>
Back to Login
@ -149,7 +196,7 @@ class BTNLoginPage extends React.Component{
}
{
!this.state.isNeedEmailVerification &&
!this.state.isNeedEmailVerification &&
<Paper className={classes.formRegister}>
<Typography variant="h6" gutterBottom>
Login to BTN Point
@ -195,7 +242,7 @@ class BTNLoginPage extends React.Component{
</div>
</Paper>
}
</Grid>
</Grid>
</Grid>
@ -205,4 +252,4 @@ class BTNLoginPage extends React.Component{
}
}
export default withStyles(styles)(BTNLoginPage);
export default withStyles(styles)(BTNLoginPage);

View File

@ -19,9 +19,9 @@ 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 Text from 'material-ui/TextField';
import moment from 'moment';
import { Link } from 'react-router-dom';
import {inject, observer} from 'mobx-react';
import {LINKS} from "../../routes";
@ -30,6 +30,8 @@ import {LINKS} from "../../routes";
@observer
class OtpPage extends React.Component{
otp = [];
urlParams = new URLSearchParams(window.location.search);
constructor(props) {
super(props);
this.props = props;
@ -42,7 +44,10 @@ class OtpPage extends React.Component{
isNeedEmailVerification: false,
otp: [],
otpText : "",
isResending: false
otpData : {},
isResending: false,
isOtpExpired : false,
isOtpWrong: false,
};
this.defaultState = Object.assign({}, this.state);
this.authStore = props.appstate.auth;
@ -50,7 +55,27 @@ class OtpPage extends React.Component{
componentDidMount(){
this.otp[0].focus();
console.log("otp",this.otp);
if(this.urlParams.has('login_request_id') && this.urlParams.has('expired_at')) {
console.log(this.urlParams);
this.setState({
otpData:{
login_request_id : this.urlParams.get('login_request_id'),
expired_at : this.urlParams.get('expired_at')
}
});
}
else{
this.setState({otpData:this.authStore.otpData});
}
}
checkIsExpired(){
console.log(Date.parse(Date().toISOString()),this.state.otpData.expired_at);
if(Date.parse(Date().toISOString()) < Date.parse(this.state.otpData.expired_at)){
return false;
}else{
return true
}
}
handleChange = name => event => {
@ -67,31 +92,58 @@ class OtpPage extends React.Component{
}
login = () => {
console.log("otpText",this.state.otpText);
let data = {
code : this.state.otpText,
login_request_id : this.state.otpData.login_request_id
}
console.log("data",data);
this.setState({isLoading:true});
setTimeout(()=>{
this.setState({isLoading:false});
},1000);
// this.authStore.login(data).then(res => {
// if(!res.need_email_verification){
// setTimeout(()=>{
// this.props.history.push(LINKS.DASHBOARD);
// this.setState({isLoading:false});
// },1000);
// }
// else{
// this.setState({isNeedEmailVerification:true});
// }
// }).catch(err => {
// this.setState({loginFailed:true,isLoading:false});
// setTimeout(()=>this.setState({loginFailed:false}),3000);
// });
};
// if(this.checkIsExpired){
// this.setState({isOtpExpired:true});
// setTimeout(()=>{
// this.setState({isOtpExpired:false});
// },2000);
// }
// else{
this.authStore.validateOtp(data).then(res=>{
setTimeout(()=>{
this.props.history.push(LINKS.DASHBOARD);
this.setState({isLoading:false});
},1000);
}).catch(err=>{
setTimeout(()=>{
this.setState({isLoading:false,isOtpWrong:true});
},2000);
setTimeout(()=>{
this.setState({isOtpWrong:false});
},4000)
});
// }
};
render(){
const { classes } = this.props;
return (
<div className={classes.container}>
<Snackbar
anchorOrigin={{ vertical : 'top', horizontal: 'center' }}
open={this.state.isOtpWrong}
onClose={()=>this.setState({isOtpWrong:false})}
ContentProps={{
'aria-describedby': 'message-id',
}}
message={<span id="message-id">Wrong OTP code</span>}
/>
<Snackbar
anchorOrigin={{ vertical : 'top', horizontal: 'center' }}
open={this.state.isOtpExpired}
onClose={()=>this.setState({isOtpExpired:false})}
ContentProps={{
'aria-describedby': 'message-id',
}}
message={<span id="message-id">Your OTP code has expired</span>}
/>
<Snackbar
anchorOrigin={{ vertical : 'top', horizontal: 'center' }}
open={this.state.isResending}
@ -129,7 +181,7 @@ class OtpPage extends React.Component{
<Grid container justify="center" spacing={8}>
{[0, 1, 2, 3, 4, 5].map(x => (
<Grid item xs={1}>
<Text onChange={event=>this.setState({otpText:this.state.otpText+event.target.value})} autoFocus={true} ref={(input) => { this.otp[x] = input; }} key={x} id={x} inputStyle={{textAlign:'center'}} style={{width:'100%'}} type="tel" maxlength="1"/>
<Text onChange={event=>this.setState({otpText:this.state.otpText+event.target.value})} autoFocus={true} ref={(input) => { this.otp[x] = input; }} key={x} id={x} inputStyle={{textAlign:'center'}} style={{width:'100%'}} type="tel" maxLength="1"/>
</Grid>
))}
</Grid>
@ -148,4 +200,4 @@ class OtpPage extends React.Component{
}
}
export default withStyles(styles)(OtpPage);
export default withStyles(styles)(OtpPage);

View File

@ -9,7 +9,7 @@ import {
message,
Button,
Spin,
Icon
Icon, notification
} from 'antd';
import css from 'reactcss';
import RegisterForm from './Form';
@ -68,8 +68,15 @@ export default class ComponentName extends React.Component {
.authStore
.register(value)
.then(res => {
message.success(res.message);
notification.open({
message: 'Register Success',
description: 'Please check your email to continue'
});
this.props.history.push({
pathname:LINKS.LOGIN
});
this.setState({isLoading: false, isSuccess: true})
// this
})
.catch(err => {
if (err && err.errors && err.errors[0] && err.errors[0].message) {

View File

@ -33,4 +33,4 @@ export const styles = theme => ({
background : yellow['500'],
padding : 20
}
});
});

View File

@ -22,6 +22,7 @@ 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");
@ -40,6 +41,8 @@ class RegisterPage extends React.Component {
fileList_ktp: [],
fileList_photo: [],
query: {},
// form
confirmPassword: "",
phone_number: "",
@ -65,6 +68,18 @@ class RegisterPage extends React.Component {
}
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();
}
@ -114,6 +129,15 @@ class RegisterPage extends React.Component {
};
register = () => {
if (this.state.upload_photo === '') {
return message.warning("please upload photo");
}
if (this.state.upload_ktp === '') {
return message.warning("please upload ktp");
}
this.setState({ isLoading: true });
let data = {
fullname: this.state.full_name,
@ -129,12 +153,15 @@ class RegisterPage extends React.Component {
district_id: this.state.district,
subdistrict_id: this.state.subdistrict,
zip_code: this.state.zip_code,
referal: this.state.query.referal,
additional_data: {}
};
this.authStore.register(data).then(res => {
message.success("Please check your email to confirm your account");
setTimeout(() => {
this.setState({ isLoading: false });
}, 1000);
this.props.history.push(LINKS.LOGIN);
}, 250);
}).catch(err => {
this.setState({ isLoading: false });
@ -194,7 +221,7 @@ class RegisterPage extends React.Component {
return this.http.upload(file)
.then(res => {
this.setState({
[`upload_${key}`]: res.path
[`upload_${key}`]: appConfig.apiUrl + res.path.slice(1,res.path.length)
});
return res;
})
@ -253,7 +280,9 @@ class RegisterPage extends React.Component {
<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}>
<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}>
@ -336,7 +365,10 @@ class RegisterPage extends React.Component {
showUploadList={false}
{...this.createUploadProps("ktp")}
>
{upload_ktp ? <img src={upload_ktp} alt="avatar" /> : uploadButtonKtp}
{upload_ktp ? <img src={upload_ktp} alt="avatar" style={{
width: 104,
height: 104
}}/> : uploadButtonKtp}
</Upload>
</Grid>
<Grid item xs={12} sm={12} md={6} style={{ paddingLeft: 5, paddingRight: 5, paddingTop:16 }}>
@ -348,7 +380,10 @@ class RegisterPage extends React.Component {
showUploadList={false}
{...this.createUploadProps("photo")}
>
{upload_photo ? <img src={upload_photo} alt="avatar" /> : uploadButtonPhoto}
{upload_photo ? <img src={upload_photo} alt="avatar" style={{
width: 104,
height: 104
}}/> : uploadButtonPhoto}
</Upload>
</Grid>
@ -476,9 +511,29 @@ class RegisterPage extends React.Component {
</Grid>
</div>
<Grid item xs={12} sm={12} md={12}>
<TextField
label="Referal"
value={this.state.query.referal}
onChange={event => {
this.setState({
query: {
...this.state.query,
referal: event.target.value
}
})
}}
margin="normal"
type={"text"}
fullWidth
variant="outlined"
/>
</Grid>
<div style={{ padding: 5, marginTop: 20 }}>
<Button fullWidth variant="contained" style={{ backgroundColor: '#ffeb3b' }} onClick={this.register}>
<Button
fullWidth
variant="contained" style={{ backgroundColor: '#ffeb3b' }} onClick={this.register}>
{this.state.isLoading ? <CircularProgress className={classes.progress} /> : "Sign Up"}
</Button>
</div>

View File

@ -10,7 +10,8 @@ export const styles = theme => ({
},
gridContainer : {
flex :1,
justifyContent:'center'
justifyContent: 'center',
flexDirection: 'column'
},
registerContainer: {
marginTop : 50
@ -34,4 +35,4 @@ export const styles = theme => ({
background : yellow['500'],
padding : 20
},
});
});

View File

@ -1,24 +1,28 @@
import React from 'react';
import {inject, observer} from 'mobx-react';
import {
FlatButton,
Divider
} from 'material-ui';
} from '@material-ui/core';
import { Affix, Card, Slider, Select, Row, Col, Icon, Tag,Rate, Button, Checkbox , DatePicker, Alert, Input ,Avatar} from 'antd';
import {startCase} from 'lodash';
import LoadingDialog from "../../LoadingDialog";
import Loader from 'react-loader-advanced';
import './style.scss';
import {DIALOG} from "../../../stores/global_ui";
import EmptyComponent from '../../EmptyComponent';
import NavigationArrowBack from 'material-ui/svg-icons/navigation/arrow-back';
import {LINKS} from "../../../routes";
import {Route} from "react-router-dom";
import { withStyles } from '@material-ui/core/styles';
import get from 'lodash.get';
import MediaQuery from 'react-responsive';
const styles = theme => ({
button: {
margin: theme.spacing.unit,
},
divider: {
marginBottom: 10,
marginTop: 10,
}
});
@inject('appstate')
@observer
export default class CheckoutVouchers extends React.Component {
export class CheckoutVouchers extends React.Component {
constructor(props) {
super(props);
this.props = props;
@ -41,7 +45,7 @@ export default class CheckoutVouchers extends React.Component {
}
render() {
const {classes} = this.props;
const logoUrl = (this.props.vouchersStore.dataItems.images.logo) ? get(this.vouchersStore.dataItems, 'images.logo', '') : 'http://lorempixel.com/400/200';
let image = logoUrl;
@ -51,8 +55,8 @@ export default class CheckoutVouchers extends React.Component {
}
return (
<div className="row">
<div className="row">
<div className="checkout-parent">
<div className="upper-card">
<Card>
<div className="">
<div style={{display:'flex',justifyContent:'center'}}>
@ -61,7 +65,7 @@ export default class CheckoutVouchers extends React.Component {
</h3>
</div>
</div>
<Divider style={{marginBottom:10,marginTop:10}} />
<Divider component={"div"} className={classes.divider} />
<div className="row" style={{marginTop:30}}>
<div className="col s12 m5 l5">
<div style={{display:'flex',justifyContent:'center',alignItems:'center'}}>
@ -70,26 +74,30 @@ export default class CheckoutVouchers extends React.Component {
</div>
</div>
<div className="col s12 m7 l7">
<div style={{alignItems:'center', justifyContent: 'center'}}>
<div className={'right-container'}>
<Row>
<div className="col s4 m4">
<div className="col s12 m4">
<h3>Jenis Layanan</h3>
</div>
<div className="col s1 m1">
<h3>:</h3>
</div>
<div className="col s7 m7">
<MediaQuery query="(min-device-width: 800px)">
<div className="col s1 m1">
<h3>:</h3>
</div>
</MediaQuery>
<div className="col s12 m7">
<h3 style={{color:'#FF6F00'}}>{this.props.vouchersStore.dataItems.name} - {this.props.vouchersStore.skuName}</h3>
</div>
</Row>
<Row>
<div className="col s4 m4">
<div className="col s12 m4">
<h3>Point</h3>
</div>
<div className="col s1 m1">
<h3>:</h3>
</div>
<div className="col s7 m7">
<MediaQuery query="(min-device-width: 800px)">
<div className="col s1 m1">
<h3>:</h3>
</div>
</MediaQuery>
<div className="col s12 m7">
<h3 style={{color:'#FF6F00'}}>{(+this.props.vouchersStore.skuPrice || 0).toFixed(0)} Points</h3>
</div>
</Row>
@ -98,15 +106,15 @@ export default class CheckoutVouchers extends React.Component {
</div>
</Card>
</div>
<div className="row">
<Card >
<div className="bottom-card">
<Card>
<div className="row">
<div style={{display:'flex',justifyContent:'space-between'}}>
<h3 style={{color:''}}>Point</h3>
<h3 style={{color:'#FF6F00'}}>{this.props.appstate.wallet.data.point || 0} Points</h3>
</div>
</div>
<Divider style={{marginBottom:10,marginTop:10}} />
<Divider component={"div"} className={classes.divider} />
<div className="row">
<div style={{display:'flex',justifyContent:'space-between'}}>
<h3>Total Pembayaran Point</h3>
@ -122,3 +130,5 @@ export default class CheckoutVouchers extends React.Component {
)
}
}
export default withStyles(styles)(CheckoutVouchers);

View File

@ -1,4 +1,53 @@
.imageCard{
max-width: 20vw;
max-height: 20vw;
@media(min-width: 1000px){
.imageCard{
width: 20vw;
height: 25vh;
}
.upper-card{
width: 60vw;
margin-left: -1vw;
margin-bottom: 15px;
}
.bottom-card{
width: 60vw;
margin-left: -1vw;
}
.right-container{
//background-color: red;
height: 25vh;
display: flex;
flex-direction: column;
justify-content: center;
//align-items: center;
}
}
@media(max-width: 999px){
.imageCard{
width: 80vw;
height: 25vh;
margin-bottom: 30px;
}
.upper-card{
width: 90vw;
margin-left: -3.5vw;
margin-bottom: 15px;
}
.bottom-card{
width: 90vw;
margin-left: -3.5vw;
}
.right-container{
margin-left: -2.5vw;
}
}
.checkout-parent{
//width: 100%;
}

View File

@ -7,6 +7,7 @@ import { Route } from 'react-router-dom'
import {LINKS} from "../../../routes";
import NumberFormat from 'react-number-format';
import get from 'lodash.get';
import ReactHtmlParser from "react-html-parser";
const Option = Select.Option;
@ -83,7 +84,7 @@ export default class ModalVouchersComponent extends React.Component {
flex: 0.7,
padding: 30
}}>
<p className={'descriptionModal'} >{data.description}</p>
<p className={'descriptionModal'} >{ReactHtmlParser(data.description)}</p>
{(additional_data.information != null) && <Alert className={'informationAlertModal'} message={
<div className={'informationContainerModal'}>

View File

@ -8,12 +8,14 @@ import { Affix, Card, Slider, Select, Row, Col, Icon, Tag,Rate, Button, Checkbox
import {startCase} from 'lodash';
import LoadingDialog from "../../LoadingDialog";
import Loader from 'react-loader-advanced';
// import './style.scss';
import './style.scss';
import {DIALOG} from "../../../stores/global_ui";
import EmptyComponent from '../../EmptyComponent';
import NavigationArrowBack from 'material-ui/svg-icons/navigation/arrow-back';
import {LINKS} from "../../../routes";
import {APP_TYPE} from "../../../config/app";
import get from "lodash.get";
import ReactHtmlParser, { processNodes, convertNodeToElement, htmlparser2 } from 'react-html-parser';
const Panel = Collapse.Panel;
@ -34,7 +36,7 @@ export default class PaymentVouchers extends React.Component {
}
componentDidMount() {
console.log(this.props.vouchersStore, 'this.props.vouchersStore this.props.vouchersStore this.props.vouchersStore')
}
render() {
@ -51,16 +53,23 @@ export default class PaymentVouchers extends React.Component {
const qty = 1;
const total = price * qty;
let applicationName = 'Giift';
let applicationLogo = 'http://giift.asacreative.com/giift_logo_wide.4d15de72.png';
if(APP_TYPE === 'btn') {
applicationName = 'BTN';
applicationLogo = 'http://btn-redemption-2.bangun-kreatif.com/dr6u0fppdi4xy.cloudfront.net/FilesDirectory/Albilad/ImgIconImage/logo-btn.png';
// let applicationName = 'Giift';
// let applicationLogo = 'http://giift.asacreative.com/giift_logo_wide.4d15de72.png';
// if(APP_TYPE === 'btn') {
// applicationName = 'BTN';
// applicationLogo = 'http://btn-redemption-2.bangun-kreatif.com/dr6u0fppdi4xy.cloudfront.net/FilesDirectory/Albilad/ImgIconImage/logo-btn.png';
// }
const logoUrl = (this.props.vouchersStore.dataItems.images.logo) ? get(this.vouchersStore.dataItems, 'images.logo', '') : 'http://lorempixel.com/400/200';
let image = logoUrl;
if (!image.includes('http')) {
image = this.http.appendImagePath(image);
}
return(
<div>
<div className="row">
<div className="upper-card">
<Collapse bordered={true}>
<Panel style={{backgroundColor:'white'}} showArrow={false} header={
<div style={{display:'flex',justifyContent:'space-between', paddingRight:20, paddingLeft:15}}>
@ -94,25 +103,27 @@ export default class PaymentVouchers extends React.Component {
</Panel>
</Collapse>
</div>
<div className="row">
<Card title={<div style={{display:'flex',justifyContent:'space-between'}}>
<div>
<h3 style={{fontSize:20}}>
Points {applicationName}
<div className="bottom-card">
<Card title={<div style={{display:'flex',justifyContent:'space-between', alignItems: 'center'}}>
<div className={'item-container'}>
<h3 className={'item-name'}>
{this.props.vouchersStore.dataItems.name} - {this.props.vouchersStore.skuName}
</h3>
<h3 className={'item-points'}>
BTN Points Payment
</h3>
</div>
<div>
<img style={{width:120, height:40}} src={applicationLogo} />
</div>
<img className={'image-logo'} src={image} />
</div>}>
<div className="row">
<Alert message="Pastikan data anda sudah terverivikasi dan vouchers anda yang pilih sudah benar sebelum melakukan transaksi" type="warning" />
<Alert message="Pastikan data anda sudah terverifikasi dan vouchers yang anda pilih sudah benar sebelum melakukan konfirmasi transaksi ini" type="warning" />
</div>
<div>
<ul>
<li style={{margin:10}}>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</li>
<li style={{margin:10}}>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</li>
</ul>
<div>
{ReactHtmlParser(this.props.vouchersStore.dataItems.description)}
{/*<li style={{margin:10}}>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</li>*/}
{/*<li style={{margin:10}}>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</li>*/}
</div>
</div>
</Card>
</div>

View File

@ -0,0 +1,50 @@
.upper-card{
}
.bottom-card{
}
@media(min-width: 1000px){
.image-logo{
width: 10vw;
height: 10vh;
}
.item-container{
height: 10vh;
display: flex;
flex-direction: column;
justify-content: center;
.item-name{
padding-top: 1vh;
margin-bottom: -0.25vh;
font-size: 1.35em;
}
.item-points{
font-size: 0.95em;
color: #aaa;
}
}
}
@media(max-width: 999px){
.image-logo{
width: 25vw;
height: 10vh;
}
.item-container{
.item-name{
font-size: 1.15em;
margin-bottom: -0.25vh;
}
.item-points{
font-size: 0.75em;
color: #aaa;
}
}
}

View File

@ -1,26 +1,41 @@
import {inject, observer} from "mobx-react";
import PropTypes from 'prop-types';
import React from "react";
import './style.scss';
import {
Step,
Stepper,
StepLabel,
} from 'material-ui/Stepper';
import Button from '@material-ui/core/Button';
import RaisedButton from 'material-ui/RaisedButton';
import FlatButton from 'material-ui/FlatButton';
import NavigationArrowBack from 'material-ui/svg-icons/navigation/arrow-back';
import {Divider} from "material-ui";
import {Divider} from "@material-ui/core";
import CheckoutVouchers from "../Checkout";
import PaymentVouchers from "../Payment";
import {LINKS} from "../../../routes";
import {notification, Modal} from "antd";
import FinishVouchers from "../Finish";
import { withStyles } from '@material-ui/core/styles';
import Stepper from '@material-ui/core/Stepper';
import Step from '@material-ui/core/Step';
import StepLabel from '@material-ui/core/StepLabel';
import MediaQuery from 'react-responsive';
const confirm = Modal.confirm;
const styles = theme => ({
button: {
margin: theme.spacing.unit,
},
input: {
display: 'none',
},
divider: {
marginBottom: 10,
marginTop: 10,
}
});
@inject('appstate')
@observer
export default class VoucherStepperComponent extends React.Component {
export class VoucherStepper extends React.Component {
constructor(props) {
super(props);
@ -38,7 +53,7 @@ export default class VoucherStepperComponent extends React.Component {
componentWillMount() {
if(!this.vouchersStore.dataItems.name){
// alert('jalan')
this.props.history.push(LINKS.VOUCHERS);
this.props.history.push(LINKS.DASHBOARD);
}
// alert('engga')
}
@ -51,6 +66,7 @@ export default class VoucherStepperComponent extends React.Component {
title: 'Anda yakin mau menukarkan voucher?',
content: 'Sistem akan langsung memotong point anda ketika anda menekan tombol konfirmasi dibawah.',
onOk: () => {
this.globalUI.showDialogLoading();
this.vouchersStore.buyVoucher(this.vouchersStore.skuId)
.then(res => {
const openNotificationWithIcon = (type) => {
@ -94,19 +110,24 @@ export default class VoucherStepperComponent extends React.Component {
};
renderButton = () => {
const {classes} = this.props;
return(
<div style={{width: '100%', display: 'flex', flexDirection: 'row', justifyContent: 'space-between', marginTop: 12,}}>
<FlatButton
label="Back"
disabled={this.state.stepIndex === 2}
onClick={(this.state.stepIndex === 0) ? () => this.props.history.goBack() : this.handlePrev}
style={{marginRight: 12}}
/>
<RaisedButton
label={this.state.stepIndex === 2 ? 'Finish' : 'Next'}
primary={true}
onClick={this.handleNext}
/>
{/*<FlatButton*/}
{/*label="Back"*/}
{/*disabled={this.state.stepIndex === 2}*/}
{/*onClick={(this.state.stepIndex === 0) ? () => this.props.history.goBack() : this.handlePrev}*/}
{/*style={{marginRight: 12}}*/}
{/*/>*/}
<Button disabled={this.state.stepIndex === 2} onClick={(this.state.stepIndex === 0) ? () => this.props.history.goBack() : this.handlePrev} className={classes.button}>Back</Button>
<Button variant="contained" color="primary" className={classes.button} onClick={this.handleNext}>
{this.state.stepIndex === 2 ? 'Finish' : 'Next'}
</Button>
{/*<RaisedButton*/}
{/*label={this.state.stepIndex === 2 ? 'Finish' : 'Next'}*/}
{/*primary={true}*/}
{/*onClick={this.handleNext}*/}
{/*/>*/}
</div>
);
};
@ -126,6 +147,7 @@ export default class VoucherStepperComponent extends React.Component {
render() {
const {finished, stepIndex} = this.state;
const {classes} = this.props;
const contentStyle = {margin: '0 16px'};
if(!this.vouchersStore.dataItems.name){
@ -147,36 +169,36 @@ export default class VoucherStepperComponent extends React.Component {
{/*<Divider style={{marginBottom:10,marginTop:10}} />*/}
{/*</div>*/}
<div className={'stepper-container'}>
<Stepper activeStep={stepIndex}>
<Step>
<StepLabel>Checkout your Voucher</StepLabel>
</Step>
<Step>
<StepLabel>Process your Payment</StepLabel>
</Step>
<Step>
<StepLabel>Finish</StepLabel>
</Step>
</Stepper>
<Divider style={{marginBottom:10,marginTop:10}} />
<MediaQuery query="(min-device-width: 1224px)">
<Stepper activeStep={stepIndex}>
<Step>
<StepLabel>Checkout your Voucher</StepLabel>
</Step>
<Step>
<StepLabel>Process your Payment</StepLabel>
</Step>
<Step>
<StepLabel>Finish</StepLabel>
</Step>
</Stepper>
</MediaQuery>
<MediaQuery query="(max-device-width: 1224px)">
<Stepper activeStep={stepIndex}>
<Step>
<StepLabel></StepLabel>
</Step>
<Step>
<StepLabel></StepLabel>
</Step>
<Step>
<StepLabel></StepLabel>
</Step>
</Stepper>
</MediaQuery>
<Divider component="div" className={classes.divider} />
{/*<Divider style={{marginBottom:10,marginTop:10}} />*/}
<div style={contentStyle}>
{finished ? (
<p>
<a
href="#"
onClick={(event) => {
event.preventDefault();
this.setState({stepIndex: 0, finished: false});
}}
>
Click here
</a> to reset the example.
</p>
) : (
<div>
<p>{this.getStepContent(stepIndex)}</p>
</div>
)}
{this.getStepContent(stepIndex)}
</div>
</div>
</div>
@ -184,3 +206,9 @@ export default class VoucherStepperComponent extends React.Component {
}
}
VoucherStepper.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(VoucherStepper);

View File

@ -1,9 +1,23 @@
.stepper{
margin-top: 5vh;
.divider-container{
max-width: 65vw;
display: flex;
justify-content: center;
align-items: center;
//background-color: #fff;
@media(min-width: 1000px){
.divider-container{
width: 60vw;
}
.stepper-container{
width: 60vw;
}
}
.stepper-container{
max-width: 65vw;
@media(max-width: 999px){
.divider-container{
width: 90vw;
}
.stepper-container{
width: 90vw;
}
}
}

View File

@ -53,6 +53,7 @@ export default class WalletComponent extends React.Component {
}
componentDidMount() {
this.props.appstate.transaction.getAll();
this.purchasedItemStore.getAll().then(res => {
console.log(res, 'ini purchased items')
})
@ -74,38 +75,39 @@ export default class WalletComponent extends React.Component {
const voucher = <NumberFormat value={(this.props.appstate.wallet.data.wallet).toFixed(2)} displayType={'text'} thousandSeparator={true} prefix={'Rp '}/>;
const points = <NumberFormat value={this.props.appstate.wallet.data.point} displayType={'text'} thousandSeparator={true}/>;
const data = [
{
id: faker.random.uuid(),
created_at: faker.date.past(),
type: 'Points',
amount: faker.commerce.price()
},
{
id: faker.random.uuid(),
created_at: faker.date.past(),
type: 'Points',
amount: faker.commerce.price()
},
{
id: faker.random.uuid(),
created_at: faker.date.past(),
type: 'Voucher',
amount: faker.commerce.price()
},
{
id: faker.random.uuid(),
created_at: faker.date.past(),
type: 'Voucher',
amount: faker.commerce.price()
},
{
id: faker.random.uuid(),
created_at: faker.date.past(),
type: 'Points',
amount: faker.commerce.price()
},
];
// const data = [
// {
// id: faker.random.uuid(),
// created_at: faker.date.past(),
// type: 'Points',
// amount: faker.commerce.price()
// },
// {
// id: faker.random.uuid(),
// created_at: faker.date.past(),
// type: 'Points',
// amount: faker.commerce.price()
// },
// {
// id: faker.random.uuid(),
// created_at: faker.date.past(),
// type: 'Voucher',
// amount: faker.commerce.price()
// },
// {
// id: faker.random.uuid(),
// created_at: faker.date.past(),
// type: 'Voucher',
// amount: faker.commerce.price()
// },
// {
// id: faker.random.uuid(),
// created_at: faker.date.past(),
// type: 'Points',
// amount: faker.commerce.price()
// },
// ];
const data = this.props.appstate.transaction.list;
const columns = [{
title: 'Id',

View File

@ -9,7 +9,7 @@ export class Authentication {
@observable isLoggingIn = false;
@observable isInviting = false;
@observable removingUser = false;
@observable isNeedEmailVerification = false;
// @observable isNeedEmailVerification = false;
@observable userWallet = {};
@observable userProfile = {
email : '',
@ -37,6 +37,7 @@ export class Authentication {
// airline_settings: []
// }
};
@observable otpData = {}
constructor(context) {
this.context = context;
@ -51,9 +52,10 @@ export class Authentication {
return this.http.post("authentication/login", data)
.then(res => {
this.isLoggingIn = false;
this.isNeedEmailVerification = res.need_email_verification;
this.context.setToken(res.token);
this.context.loadDataAfterLogin();
if(res.token) {
this.context.setToken(res.token);
this.context.loadDataAfterLogin();
}
return res;
})
.catch(err => {
@ -73,6 +75,13 @@ export class Authentication {
})
}
@action
verifyEmail(key) {
return this.http.post('authentication/email_verification', {
key
})
}
@action
logout() {
this.context.setToken("");
@ -117,6 +126,31 @@ export class Authentication {
})
}
@action
resendEmail(data) {
this.isRegistering = true;
return this.http.post("authentication/resend_email_verification", data)
.then(res => {
return res;
})
.catch(err => {
throw err;
})
}
@action
validateOtp(data) {
return this.http.post("authentication/validate_otp", data)
.then(res => {
this.context.setToken(res.token);
this.context.loadDataAfterLogin();
return res;
})
.catch(err => {
throw err;
})
}
createCookie(name,value,days) {
let expires
if (days) {

View File

@ -98,7 +98,7 @@ export default class Transaction {
};
}
// @action
// @action
// getAll() {
// this.isLoading = true;
// return this.http.get("transaction")
@ -111,7 +111,7 @@ export default class Transaction {
@action
getAll() {
this.isLoading = true;
return this.http.get("transaction")
return this.http.get("transactions")
.then(res => {
this.list = res;
this.isLoading = false;