Authored by 于良

增加coupon模块 review by shixiang

... ... @@ -3,9 +3,10 @@
import Community from './community/Community';
import Plustar from './plustar/Plustar';
import QRCode from './qrcode/QRCode';
import Coupon from './coupon/Coupon';
export default function native(platform) {
Community(platform);
Plustar(platform);
QRCode(platform);
Coupon(platform);
}
... ...
'use strict';
import React from 'react';
import ReactNative from 'react-native';
const {
Image,
Dimensions,
StyleSheet,
} = ReactNative;
export default class AutoSizeImage extends React.Component {
constructor(props) {
super (props);
this.state = {
width: 0,
height: 0,
}
}
componentDidMount() {
Image.getSize(this.props.src, (width, height) => {
let imgWidth = Dimensions.get('window').width;
let imgHeight = Math.ceil((height / width) * imgWidth);
this.setState({
width: imgWidth,
height: imgHeight,
});
});
}
render() {
return (
<Image
source={{uri: this.props.src}}
style={{ width: this.state.width, height: this.state.height }}
resizeMode={'contain'}
/>
);
}
}
... ...
... ... @@ -4,34 +4,136 @@ import React, {Component} from 'react';
import ReactNative, {
View,
Text,
Image,
ListView,
StyleSheet,
Dimensions,
TouchableOpacity,
} from 'react-native';
import Banner from '../../../community/components/home/Banner';
import SlicedImage from '../../../common/components/SlicedImage';
import AutoSizeImage from './AutoSizeImage';
export default class CouponCenter extends Component {
constructor(props) {
super(props);
this._renderRow = this._renderRow.bind(this);
this.dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => !Immutable.is(r1, r2),
});
}
componentDidMount() {
_renderRow(rowData: object, sectionID: number, rowID: number) {
let data = rowData.get('data');
switch (rowData.get('templateName')) {
case 'carousel_banner':
case 'focus':
return (
<Banner
data={data}
width={width}
height={bannerHeight}
onPress={this.props.onPressBanner}
/>
);
case 'text':
return (
<Text style={styles.text}>{data}</Text>
);
case 'single_image':
let src = SlicedImage.getSlicedUrl(data.get('src'), 0, 0, 2);
return (
<TouchableOpacity
activeOpacity={0.8}
onPress={() => {
this.props.onPressImage && this.props.onPressImage(data.get('url'));
}}
>
<AutoSizeImage src={src}/>
</TouchableOpacity>
);
case 'getCoupon':
let bg = SlicedImage.getSlicedUrl(data.get('image').get('src'), 0, 0, 2);
let optImage;
if (data.get('status') == 1) {
optImage = require('../../images/click-txt.png');
} else if (data.get('status') == 2) {
optImage = require('../../images/zero.png');
} else if (data.get('status') == 3) {
optImage = require('../../images/received.png');
}
return (
<Image source={{uri: bg}} style={styles.couponContainer}>
<TouchableOpacity
style={styles.couponLeft}
activeOpacity={0.8}
onPress={() => {
this.props.onPressCoupon && this.props.onPressCoupon(data.get('image').get('url'));
}}
>
</TouchableOpacity>
<TouchableOpacity
style={styles.couponRight}
activeOpacity={0.8}
onPress={() => {
this.props.onGetCoupon && this.props.onGetCoupon(data.get('image').get('url'));
}}
>
<Image source={optImage} resizeMode={'center'}/>
</TouchableOpacity>
</Image>
);
default:
return null;
}
}
render() {
let data = this.props.floors.toArray();
return (
<View/>
<ListView
enableEmptySections={true}
dataSource={this.dataSource.cloneWithRows(data)}
renderRow={this._renderRow}
/>
);
}
}
let {width, height} = Dimensions.get('window');
let bannerHeight = Math.ceil((310 / 640) * width);
let couponHeight = Math.ceil((180 / 640) * width);
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f0f0f0',
},
textContainer: {
},
text: {
fontFamily: 'helvetica',
fontSize: 18,
lineHeight: 56,
textAlign: 'center',
paddingBottom: (56 - 18) / 2,
},
couponContainer: {
width,
height: couponHeight,
flexDirection: 'row',
},
couponLeft: {
flex: 0.8,
},
couponRight: {
flex: 0.2,
justifyContent: 'center',
},
});
... ...
... ... @@ -3,6 +3,11 @@ import keyMirror from 'key-mirror';
export default keyMirror({
SET_PLATFORM: null,
COUPON_CENTER_REQUEST: null,
COUPON_CENTER_SUCCESS: null,
COUPON_CENTER_FAILURE: null,
JUMP_WITH_URL: null,
});
... ...
... ... @@ -14,11 +14,11 @@ import {
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {Map} from 'immutable';
import * as qrcodeActions from '../reducers/qrcode/qrcodeActions';
import * as couponActions from '../reducers/coupon/couponActions';
import CouponCenter from '../components/coupon/CouponCenter';
const actions = [
qrcodeActions,
couponActions,
];
function mapStateToProps(state) {
... ... @@ -44,24 +44,48 @@ class CouponCenterContainer extends Component {
constructor(props) {
super(props);
this._onPressBanner = this._onPressBanner.bind(this);
this._onPressImage = this._onPressImage.bind(this);
this._onPressCoupon = this._onPressCoupon.bind(this);
this._onGetCoupon = this._onGetCoupon.bind(this);
}
componentDidMount() {
this.props.actions.couponCenter();
}
componentWillUnmount() {
}
_onPressBanner(url) {
console.log(url);
this.props.actions.jumpWithUrl(url);
}
_onPressImage(url) {
this.props.actions.jumpWithUrl(url);
}
render() {
_onPressCoupon(url) {
this.props.actions.jumpWithUrl(url);
}
_onGetCoupon(url) {
}
render() {
let {isFetching, floors} = this.props.coupon;
return (
<View style={styles.container}>
<CouponCenter/>
</View>
<CouponCenter
isFetching={isFetching}
floors={floors}
onPressBanner={this._onPressBanner}
onPressImage={this._onPressImage}
onPressCoupon={this._onPressCoupon}
onGetCoupon={this._onGetCoupon}
/>
);
}
}
... ...
... ... @@ -4,9 +4,151 @@ import ReactNative from 'react-native';
import CouponService from '../../services/CouponService';
const {
COUPON_CENTER_REQUEST,
COUPON_CENTER_SUCCESS,
COUPON_CENTER_FAILURE,
JUMP_WITH_URL,
} = require('../../constants/actionTypes').default;
export function couponCenterRequest() {
return {
type: COUPON_CENTER_REQUEST,
};
}
export function couponCenterSuccess(json) {
return {
type: COUPON_CENTER_SUCCESS,
payload: json
};
}
export function couponCenterFailure(error) {
return {
type: COUPON_CENTER_FAILURE,
payload: error
};
}
/*
* index number 请求数据的index
* reload bool 是否需要强制重新请求数据,
*/
export function couponCenter(reload = false) {
return (dispatch, getState) => {
let {app, coupon} = getState();
let {isFetching, floors, contentCode} = coupon;
if (reload) {
// 强制刷新数据
} else {
if (isFetching || floors.size > 0) {
return;
}
}
let fetchCouponInfo = (contentCode, uid) => {
return new CouponService().fetchFloors(contentCode, uid)
.then(json => {
let payload = parseFloors(json);
dispatch(couponCenterSuccess(payload));
})
.catch(error => {
dispatch(couponCenterFailure(error));
});
}
dispatch(couponCenterRequest());
ReactNative.NativeModules.YH_CommonHelper.uid()
.then(uid => {
fetchCouponInfo(contentCode, uid);
})
.catch(error => {
fetchCouponInfo(contentCode, 0);
});
};
}
function parseFloors(json) {
let carousel_banner = (data) => {
let images = [];
data && data.list && data.list.map((item, i) => {
let src = item.src ? item.src : '';
let url = item.url ? item.url : '';
images.push({src, url});
});
return images;
};
let focus = (data) => {
let images = [];
data && data.map((item, i) => {
let src = item.src ? item.src : '';
let url = item.url ? item.url : '';
images.push({src, url});
});
return images;
};
let text = (data) => {
let text = data && data.text ? data.text : '';
return text;
};
let single_image = (data) => {
let src = data && data[0] && data[0].src ? data[0].src : '';
let url = data && data[0] && data[0].url ? data[0].url : '';
return {src, url};
};
let getCoupon = (data) => {
let coupon = data && data[0] ? data[0] : {};
let text = coupon.text ? coupon.text : '';
let couponID = coupon.couponID ? coupon.couponID : '';
let image = {
src : coupon.image && coupon.image.src ? coupon.image.src : '',
url : coupon.image && coupon.image.url ? coupon.image.url : '',
};
let isShow = coupon.isShow;
let status = coupon.status;
return {
text,
couponID,
image,
isShow,
status,
};
};
let floors = [];
json && json.map((item, i) => {
let templateName = item.template_name;
if (!templateName) {
templateName = item.templateName;
}
let data;
if (templateName == 'carousel_banner') {
data = carousel_banner(item.data);
} else if (templateName == 'focus') {
data = focus(item.data)
} else if (templateName == 'text') {
data = text(item.data)
} else if (templateName == 'single_image') {
data = single_image(item.data)
} else if (templateName == 'getCoupon') {
data = getCoupon(item.data)
}
let floor = {
data,
templateName,
};
floors.push(floor);
});
return floors;
}
export function jumpWithUrl(url) {
if (!url) {
... ... @@ -14,7 +156,7 @@ export function jumpWithUrl(url) {
return;
}
ReactNative.NativeModules.YH_PlustarHelper.jumpWithUrl(url);
ReactNative.NativeModules.YH_CommonHelper.jumpWithUrl(url);
return {
type: JUMP_WITH_URL,
payload: url
... ...
... ... @@ -3,23 +3,10 @@
import {Record, List, Map} from 'immutable';
let InitialState = Record({
activeTab: 0,
gender: -1,
0: new (Record({
isFetching: false,
error: null,
head: List(),
foot: List(),
list: List(),
})),
1: new (Record({
isFetching: false,
error: null,
head: List(),
foot: List(),
list: List(),
})),
segment: null,
contentCode: 'b78b32ed81b18dde8ac84fd33602b88b',
isFetching: false,
error: null,
floors: List(),
});
export default InitialState;
... ...
... ... @@ -4,6 +4,9 @@ import InitialState from './couponInitialState';
import Immutable, {Map} from 'immutable';
const {
COUPON_CENTER_REQUEST,
COUPON_CENTER_SUCCESS,
COUPON_CENTER_FAILURE,
JUMP_WITH_URL,
} = require('../../constants/actionTypes').default;
... ... @@ -11,7 +14,21 @@ const initialState = new InitialState;
export default function couponReducer(state=initialState, action) {
switch(action.type) {
case COUPON_CENTER_REQUEST: {
return state.set('isFetching', true)
.set('error', null);
}
case COUPON_CENTER_SUCCESS: {
return state.set('isFetching', false)
.set('error', null)
.set('floors', Immutable.fromJS(action.payload));
}
case COUPON_CENTER_FAILURE: {
return state.set('isFetching', false)
.set('error', action.payload);
}
}
return state;
... ...
... ... @@ -5,16 +5,17 @@ import Request from '../../common/services/Request';
export default class CouponService {
constructor () {
let baseURL = 'http://service.yoho.cn';
let baseURL = 'http://api.yoho.cn';
this.api = new Request(baseURL);
}
async fetchList(brand_type, options) {
async fetchFloors(contentCode, uid) {
return await this.api.get({
url: '/guang/api/v3/plustar/getlist',
url: '',
body: {
brand_type,
...options,
method: 'app.promotion.queryCouponCenter',
contentCode,
uid,
}
})
.then((json) => {
... ...