Authored by 于良

获取优惠券 review by shixiang

... ... @@ -15,8 +15,8 @@ export default class AutoSizeImage extends React.Component {
super (props);
this.state = {
width: 0,
height: 0,
width: Dimensions.get('window').width,
height: 44,
}
}
... ...
... ... @@ -14,6 +14,8 @@ import ReactNative, {
import Banner from '../../../community/components/home/Banner';
import SlicedImage from '../../../common/components/SlicedImage';
import AutoSizeImage from './AutoSizeImage';
import LoadingIndicator from '../../../common/components/LoadingIndicator';
import Prompt from './Prompt';
export default class CouponCenter extends Component {
... ... @@ -59,12 +61,20 @@ export default class CouponCenter extends Component {
case 'getCoupon':
let bg = SlicedImage.getSlicedUrl(data.get('image').get('src'), 0, 0, 2);
let optImage;
let resizeMode = 'contain';
let marginTop = 0;
if (data.get('status') == 1) {
optImage = require('../../images/click-txt.png');
resizeMode = 'center';
marginTop = 0;
} else if (data.get('status') == 2) {
optImage = require('../../images/zero.png');
resizeMode = 'contain';
marginTop = -9;
} else if (data.get('status') == 3) {
optImage = require('../../images/received.png');
resizeMode = 'contain';
marginTop = -9;
}
return (
<Image source={{uri: bg}} style={styles.couponContainer}>
... ... @@ -80,10 +90,14 @@ export default class CouponCenter extends Component {
style={styles.couponRight}
activeOpacity={0.8}
onPress={() => {
this.props.onGetCoupon && this.props.onGetCoupon(data.get('image').get('url'));
if (data.get('status') == 1) {
this.props.onGetCoupon && this.props.onGetCoupon(data.get('couponID'));
} else {
this.props.onPressCoupon && this.props.onPressCoupon(data.get('image').get('url'));
}
}}
>
<Image source={optImage} resizeMode={'center'}/>
<Image source={optImage} resizeMode={resizeMode} style={[styles.rightImage, {marginTop}]}/>
</TouchableOpacity>
</Image>
);
... ... @@ -94,12 +108,25 @@ export default class CouponCenter extends Component {
render() {
let data = this.props.floors.toArray();
return (
<ListView
enableEmptySections={true}
dataSource={this.dataSource.cloneWithRows(data)}
renderRow={this._renderRow}
/>
<View style={styles.container}>
<ListView
enableEmptySections={true}
dataSource={this.dataSource.cloneWithRows(data)}
renderRow={this._renderRow}
/>
<LoadingIndicator
isVisible={this.props.isFetching}
/>
{this.props.showSuccessTip ? <Prompt
icon={require('../../images/hud_success.png')}
text={'领取成功'}
onPromptHidden={this.props.onPromptHidden}
/> : null}
</View>
);
}
}
... ... @@ -107,11 +134,13 @@ export default class CouponCenter extends Component {
let {width, height} = Dimensions.get('window');
let bannerHeight = Math.ceil((310 / 640) * width);
let couponHeight = Math.ceil((180 / 640) * width);
let rightWidth = Math.ceil((110 / 640) * width);
let rightHeight = Math.ceil((180 / 110) * rightWidth);
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f0f0f0',
backgroundColor: 'white',
},
textContainer: {
... ... @@ -119,9 +148,9 @@ let styles = StyleSheet.create({
text: {
fontFamily: 'helvetica',
fontSize: 18,
lineHeight: 56,
lineHeight: 48,
textAlign: 'center',
paddingBottom: (56 - 18) / 2,
paddingBottom: (48 - 18) / 2,
},
couponContainer: {
width,
... ... @@ -129,11 +158,17 @@ let styles = StyleSheet.create({
flexDirection: 'row',
},
couponLeft: {
flex: 0.8,
flex: 0.78,
},
couponRight: {
flex: 0.2,
justifyContent: 'center',
flex: 0.22,
// justifyContent: 'center',
// alignItems: 'center'
},
rightImage: {
width: rightWidth,
height: rightHeight,
// backgroundColor: 'red'
},
});
... ...
'use strict';
import React, {Component} from 'react'
import {
StyleSheet,
View,
Text,
Image,
Dimensions,
Platform,
Animated,
} from 'react-native';
import TimerMixin from 'react-timer-mixin';
const initOpacity = 0.8;
export default class Prompt extends Component {
static propTypes = {
icon: Image.propTypes.source,
overlayColor: React.PropTypes.string,
title: React.PropTypes.string,
titleColor: React.PropTypes.string,
titleFontSize: React.PropTypes.number,
text: React.PropTypes.string,
textColor: React.PropTypes.string,
textFontSize: React.PropTypes.number,
duration: React.PropTypes.number,
onPromptHidden: React.PropTypes.func,
};
static defaultProps = {
isDismissible: false,
overlayColor: 'rgba(0,0,0,'+ initOpacity + ')',
titleColor: '#eeeeee',
titleFontSize: 15,
textColor: '#eeeeee',
textFontSize: 15,
duration: 2 * 1000, //2s
};
constructor(props) {
super(props);
this.state = {
fadeAnim: new Animated.Value(initOpacity),
};
}
componentDidMount() {
this.timer = TimerMixin.setTimeout(
() => {
this.state.fadeAnim.addListener(event => {
if (event.value == 0) {
this.props.onPromptHidden && this.props.onPromptHidden();
}
});
Animated.timing(
this.state.fadeAnim,
{toValue: 0},
).start();
},
this.props.duration
);
}
componentWillUnmount() {
TimerMixin.clearTimeout(this.timer);
}
render() {
let customStyles = StyleSheet.create({
overlay: {
alignItems: 'center',
justifyContent: 'center',
borderRadius: 10,
backgroundColor: this.props.overlayColor,
},
title: {
// color: this.props.titleColor,
// fontSize: this.props.titleFontSize,
marginTop: 10,
marginLeft: 15,
marginRight: 15,
marginBottom: 10,
width: 30,
height: 30,
},
text: {
color: this.props.textColor,
fontSize: this.props.textFontSize,
maxWidth: width - 30 - 30,
marginLeft: 15,
marginRight: 15,
marginBottom: 15,
},
});
return (
<Animated.View style={[styles.container, {opacity: this.state.fadeAnim,}]}>
<View style={customStyles.overlay}>
<Image source={this.props.icon} style={customStyles.title}/>
<Text style={customStyles.text}>{this.props.text}</Text>
</View>
</Animated.View>
);
}
}
let {width, height} = Dimensions.get('window');
let navbarHeight = (Platform.OS === 'android') ? 50 : 64;
const styles = StyleSheet.create({
container: {
position: 'absolute',
backgroundColor: 'transparent',
justifyContent: 'center',
alignItems: 'center',
top: -navbarHeight,
bottom: 0,
left: 0,
right: 0,
},
});
... ...
... ... @@ -8,6 +8,12 @@ export default keyMirror({
COUPON_CENTER_SUCCESS: null,
COUPON_CENTER_FAILURE: null,
GET_COUPON_REQUEST: null,
GET_COUPON_SUCCESS: null,
GET_COUPON_FAILURE: null,
JUMP_WITH_URL: null,
HIDE_SUCCESS_PROMPT: null,
});
... ...
... ... @@ -48,6 +48,7 @@ class CouponCenterContainer extends Component {
this._onPressImage = this._onPressImage.bind(this);
this._onPressCoupon = this._onPressCoupon.bind(this);
this._onGetCoupon = this._onGetCoupon.bind(this);
this._onPromptHidden = this._onPromptHidden.bind(this);
}
componentDidMount() {
... ... @@ -71,12 +72,16 @@ class CouponCenterContainer extends Component {
this.props.actions.jumpWithUrl(url);
}
_onGetCoupon(url) {
_onGetCoupon(couponID) {
this.props.actions.getCoupon(couponID);
}
_onPromptHidden() {
this.props.actions.promptHidden();
}
render() {
let {isFetching, floors} = this.props.coupon;
let {isFetching, floors, showSuccessTip} = this.props.coupon;
return (
<CouponCenter
isFetching={isFetching}
... ... @@ -85,6 +90,8 @@ class CouponCenterContainer extends Component {
onPressImage={this._onPressImage}
onPressCoupon={this._onPressCoupon}
onGetCoupon={this._onGetCoupon}
showSuccessTip={showSuccessTip}
onPromptHidden={this._onPromptHidden}
/>
);
}
... ...
... ... @@ -7,7 +7,11 @@ const {
COUPON_CENTER_REQUEST,
COUPON_CENTER_SUCCESS,
COUPON_CENTER_FAILURE,
GET_COUPON_REQUEST,
GET_COUPON_SUCCESS,
GET_COUPON_FAILURE,
JUMP_WITH_URL,
HIDE_SUCCESS_PROMPT,
} = require('../../constants/actionTypes').default;
export function couponCenterRequest() {
... ... @@ -43,11 +47,13 @@ export function couponCenter(reload = false) {
} else {
if (isFetching || floors.size > 0) {
console.log(222);
return;
}
}
let fetchCouponInfo = (contentCode, uid) => {
dispatch(couponCenterRequest());
return new CouponService().fetchFloors(contentCode, uid)
.then(json => {
let payload = parseFloors(json);
... ... @@ -58,7 +64,6 @@ export function couponCenter(reload = false) {
});
}
dispatch(couponCenterRequest());
ReactNative.NativeModules.YH_CommonHelper.uid()
.then(uid => {
fetchCouponInfo(contentCode, uid);
... ... @@ -150,6 +155,65 @@ function parseFloors(json) {
return floors;
}
export function getCouponRequest() {
return {
type: GET_COUPON_REQUEST,
};
}
export function getCouponSuccess(json) {
return {
type: GET_COUPON_SUCCESS,
payload: json
};
}
export function getCouponFailure(error) {
return {
type: GET_COUPON_FAILURE,
payload: error
};
}
export function getCoupon(couponID) {
return (dispatch, getState) => {
let getCoupon = (couponID, uid) => {
dispatch(getCouponRequest());
return new CouponService().getCoupon(couponID, uid)
.then(json => {
let floors = getState().coupon.floors.toJS();
for (var i = 0; i < floors.length; i++) {
let item = floors[i];
if (item.templateName == 'getCoupon' && item.data.couponID == couponID) {
item.data.status = 3; //领取成功
break;
}
}
dispatch(getCouponSuccess(floors));
})
.catch(error => {
dispatch(getCouponFailure(error));
});
}
ReactNative.NativeModules.YH_CommonHelper.uid()
.then(uid => {
getCoupon(couponID, uid);
})
.catch(error => {
console.log(error);
ReactNative.NativeModules.YH_CommonHelper.login()
.then(uid => {
dispatch(couponCenter(true));
})
.catch(error => {
});
});
};
}
export function jumpWithUrl(url) {
if (!url) {
__DEV__ && console.log('Illegal url');
... ... @@ -162,3 +226,9 @@ export function jumpWithUrl(url) {
payload: url
};
}
export function promptHidden() {
return {
type: HIDE_SUCCESS_PROMPT,
};
}
... ...
... ... @@ -7,6 +7,7 @@ let InitialState = Record({
isFetching: false,
error: null,
floors: List(),
showSuccessTip: false,
});
export default InitialState;
... ...
... ... @@ -7,7 +7,11 @@ const {
COUPON_CENTER_REQUEST,
COUPON_CENTER_SUCCESS,
COUPON_CENTER_FAILURE,
GET_COUPON_REQUEST,
GET_COUPON_SUCCESS,
GET_COUPON_FAILURE,
JUMP_WITH_URL,
HIDE_SUCCESS_PROMPT,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
... ... @@ -29,6 +33,29 @@ export default function couponReducer(state=initialState, action) {
return state.set('isFetching', false)
.set('error', action.payload);
}
case GET_COUPON_REQUEST: {
return state.set('isFetching', true)
.set('error', null)
.set('showSuccessTip', false);
}
case GET_COUPON_SUCCESS: {
return state.set('isFetching', false)
.set('error', null)
.set('floors', Immutable.fromJS(action.payload))
.set('showSuccessTip', true);
}
case GET_COUPON_FAILURE: {
return state.set('isFetching', false)
.set('error', action.payload)
.set('showSuccessTip', false);
}
case HIDE_SUCCESS_PROMPT: {
return state.set('showSuccessTip', false);
}
}
return state;
... ...
... ... @@ -26,4 +26,21 @@ export default class CouponService {
});
}
async getCoupon(couponId, uid) {
return await this.api.get({
url: '',
body: {
method: 'app.promotion.getCoupon',
couponId,
uid,
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
}
... ...