Authored by chenl

增加VIP特权页面。review by 庄佳佳。

... ... @@ -21,6 +21,11 @@ import {Record, List, Map} from 'immutable';
import appInitialState from './reducers/app/appInitialState';
import yearActivityInitialState from './reducers/yearActivity/yearActivityInitialState';
import YearActivityContainer from './containers/yearActivityContainer';
import fastExpressInitialState from './reducers/fastExpress/fastExpressInitialState';
import FastExpressContainer from './containers/fastExpressContainer';
import birthInitialState from './reducers/birth/birthInitialState';
import BirthContainer from './containers/birthContainer';
import MagazineContainer from './containers/magazineContainer';
import {
setPlatform,
... ... @@ -35,6 +40,8 @@ function getInitialState() {
const _initState = {
app: (new appInitialState()),
yearActivity: (new yearActivityInitialState()),
fastExpress: (new fastExpressInitialState()),
birth: (new birthInitialState()),
};
return _initState;
}
... ... @@ -44,13 +51,25 @@ export default function native(platform) {
let YH_Vip = React.createClass({
_renderContainer() {
// console.log(this.props.privilegeId);
console.log(this.props.privilegeId);
//VIP年度优惠特权触达页
// if (this.props.privilegeId == 4) {
if (this.props.privilegeId == 4) {
return <YearActivityContainer />;
// }
// else
// return <View/>
}
//VIP快速送达特权触达页
else if (this.props.privilegeId == 5) {
return <FastExpressContainer />;
}
//VIP电子杂志特权触达页
else if (this.props.privilegeId == 6) {
return <MagazineContainer />;
}
//VIP生日特惠特权触达页
else if (this.props.privilegeId == 8) {
return <BirthContainer />;
}
else
return <View/>
},
... ... @@ -59,7 +78,7 @@ export default function native(platform) {
store.dispatch(setPlatform(platform));
store.dispatch(setHost(this.props.host));
store.dispatch(setServiceHost(this.props.serviceHost));
store.dispatch(setPrivilegeId(4));
store.dispatch(setPrivilegeId(this.props.privilegeId));
return (
<Provider store={store}>
... ...
'use strict';
import React, {Component} from 'react';
import ReactNative, {
View,
Text,
Image,
Button,
ListView,
StyleSheet,
Dimensions,
TouchableOpacity,
Platform,
InteractionManager,
} from 'react-native';
import HeadTitleCell from '../cell/HeadTitleCell';
import ProductListCell from '../../../common/components/ListCell/ProductListCell';
import LoadingIndicator from '../../../common/components/LoadingIndicator';
export default class Birth extends Component {
constructor(props) {
super(props);
this.dataSource = new ListView.DataSource({rowHasChanged: (r1, r2) => !immutable.is(r1, r2)});
this.renderHeader = this.renderHeader.bind(this);
this.renderRow = this.renderRow.bind(this);
}
renderHeader(){
return(
<View style={styles.birthdayTipContainer}>
<Text style={styles.tipText}>生日特惠:除了在生日当月月初收到来自我们的真诚祝福,还将收到每年一次的”特殊优惠券”作为生日礼物。</Text>
<Text style={styles.tipText}>※需要在成为我们的会员时完善您的生日及相关信息,否则将无法得到优惠</Text>
<TouchableOpacity activeOpacity={1} onPress={() => {
this.props.onPressComplete && this.props.onPressComplete();}}>
<Text style={styles.completeButton}>完善生日信息</Text>
</TouchableOpacity>
<HeadTitleCell title={"你可能喜欢"} />
</View>
);
}
renderRow(rowData, sectionID, rowID) {
let paddingLeft = rowID % 2 == 1 ? rowMarginHorizontal*1.5 : rowMarginHorizontal*2;
let customStyle = {paddingLeft};
return (
<View style={[styles.product,]}>
<ProductListCell
style={[styles.listContainer, customStyle]}
key={'sectionID+rowID' + sectionID+rowID}
rowID={rowID}
data={rowData}
similarIndex={this.props.similarIndex}
onPressProduct={this.props.onPressProductListProduct}
onLongPressProduct={this.props.onLongPressProduct}
onPressFindSimilar={this.props.onPressFindSimilar}
/>
</View>
);
}
render() {
let {isFetching, data} = this.props;
if(!data || data.toArray().length == 0){
return null;
}
return (
<View style={styles.container}>
<ListView
contentContainerStyle={styles.contentContainer}
enableEmptySections={true}
dataSource={this.dataSource.cloneWithRows(data.toArray())}
renderRow={this.renderRow}
renderHeader={this.renderHeader}
onEndReached={this.props.onEndReached}
initialListSize={30}
pageSize={30}
/>
<LoadingIndicator isVisible={isFetching} />
</View>
);
}
}
let {width, height} = Dimensions.get('window');
const DEVICE_WIDTH_RATIO = width / 320;
let rowWidth = Math.ceil(137.5 * width / 320);
let rowMarginHorizontal = Math.ceil((width - rowWidth * 2)/7);
let rowHeight = Math.ceil(254 * DEVICE_WIDTH_RATIO);
let rowMarginTop = Math.ceil(10 * DEVICE_WIDTH_RATIO);
let rowMarginBottom = Math.ceil(4 * DEVICE_WIDTH_RATIO);
let productHeight = Platform.OS === 'ios'? (rowHeight + rowMarginTop + rowMarginBottom) : (rowHeight + 4 + rowMarginTop + rowMarginBottom);
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f0f0f0',
},
contentContainer: {
flexDirection: 'row',
flexWrap: 'wrap',
},
listContainer: {
width: width/2,
},
product: {
width: width/2,
backgroundColor: 'white',
height: productHeight,
},
birthdayTipContainer:{
width:width,
height:220,
flexDirection:'column',
alignItems:'center',
justifyContent:'center',
backgroundColor:'white',
},
tipText:{
fontSize: 12,
marginLeft:14,
marginRight:14,
color: '#c0c0c0',
textAlign: 'center',
fontWeight: 'bold',
lineHeight:18,
},
completeButton:{
fontSize:16,
paddingLeft:18,
paddingRight:18,
paddingTop:8,
paddingBottom:8,
marginTop:30,
marginBottom: 15,
color: '#777777',
textAlign: 'center',
borderColor:'#444444',
borderWidth:2,
borderRadius: 6,
},
});
... ...
'use strict';
import React, {Component} from 'react';
import ReactNative, {
View,
Text,
Image,
ListView,
StyleSheet,
Dimensions,
TouchableOpacity,
Platform,
InteractionManager,
} from 'react-native';
import HeadTitleCell from '../cell/HeadTitleCell';
import ProductListCell from '../../../common/components/ListCell/ProductListCell';
import LoadingIndicator from '../../../common/components/LoadingIndicator';
export default class FastExpress extends Component {
constructor(props) {
super(props);
this.dataSource = new ListView.DataSource({rowHasChanged: (r1, r2) => !immutable.is(r1, r2)});
this.renderHeader = this.renderHeader.bind(this);
this.renderRow = this.renderRow.bind(this);
}
renderHeader(){
let {data, fastExpressList} = this.props;
let desc1 = "白金会员可享受快速送达服务。订单将采用最快速度进行配送(比如航空快件),保证您可以尽快获得心仪的商品。";
let desc2 = "※ 如果您的收件区域位于可提供快速送达服务的快递范围外或订单内的商品包含航空禁运品,我们仍将统一采用可送达快递进行配送,敬请谅解。";
return(
<View style={styles.headerContainer}>
<View style={styles.fastHeader}>
<Text style={styles.fastHeaderCell}>{"等级"}</Text>
<Text style={styles.fastHeaderCell}>{"快速送达服务"}</Text>
</View>
{
fastExpressList.map((item, i) => {
let levelName = item.get('vip_name');
let isFastImage = item.get('is_fast_express');
return (
<View key={"fastExpress"+i} style={styles.fastContent} >
<Text style={styles.fastContentText}>{levelName}</Text>
<View style={styles.fastContentImageContainer}>
{
(isFastImage == 1) ? <Image source={require('../../images/fast.png')} style={styles.fastContentImage} />
: <Image source={require('../../images/nofast.png')} style={styles.fastContentImage} />
}
</View>
</View>
);
})}
<Text style={styles.headerDescription1}>{desc1}</Text>
<Text style={styles.headerDescription2}>{desc2}</Text>
<HeadTitleCell title={"新品推荐"} />
</View>
);
}
renderRow(rowData, sectionID, rowID) {
let paddingLeft = rowID % 2 == 1 ? rowMarginHorizontal*1.5 : rowMarginHorizontal*2;
let customStyle = {paddingLeft};
return (
<View style={[styles.product,]}>
<ProductListCell
style={[styles.listContainer, customStyle]}
key={'sectionID+rowID' + sectionID+rowID}
rowID={rowID}
data={rowData}
similarIndex={this.props.similarIndex}
onPressProduct={this.props.onPressProductListProduct}
onLongPressProduct={this.props.onLongPressProduct}
onPressFindSimilar={this.props.onPressFindSimilar}
/>
</View>
);
}
render() {
let {isFetching, data} = this.props;
if(!data || data.toArray().length == 0){
return null;
}
return (
<View style={styles.container}>
<ListView
contentContainerStyle={styles.contentContainer}
enableEmptySections={true}
dataSource={this.dataSource.cloneWithRows(data.toArray())}
renderRow={this.renderRow}
renderHeader={this.renderHeader}
onEndReached={this.props.onEndReached}
initialListSize={30}
pageSize={30}
/>
<LoadingIndicator isVisible={isFetching} />
</View>
);
}
}
let {width, height} = Dimensions.get('window');
const DEVICE_WIDTH_RATIO = width / 320;
let rowWidth = Math.ceil(137.5 * width / 320);
let rowMarginHorizontal = Math.ceil((width - rowWidth * 2)/7);
let rowHeight = Math.ceil(254 * DEVICE_WIDTH_RATIO);
let rowMarginTop = Math.ceil(10 * DEVICE_WIDTH_RATIO);
let rowMarginBottom = Math.ceil(4 * DEVICE_WIDTH_RATIO);
let productHeight = Platform.OS === 'ios'? (rowHeight + rowMarginTop + rowMarginBottom) : (rowHeight + 4 + rowMarginTop + rowMarginBottom);
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
},
contentContainer: {
flexDirection: 'row',
flexWrap: 'wrap',
},
headerContainer: {
width: width,
height: 300,
marginTop: 20,
},
fastHeader: {
flexDirection: 'row',
width: width - 50,
height: 40,
marginLeft: 25,
marginRight: 25,
backgroundColor: '#f0f0f0',
alignItems: 'center',
justifyContent: 'center',
},
fastHeaderCell: {
flex: 1,
textAlign: 'center',
fontSize: 15,
color: '#393939',
},
fastContent: {
flexDirection: 'row',
width: width - 50,
height: 40,
marginLeft: 25,
marginRight: 25,
alignItems: 'center',
justifyContent: 'center',
borderLeftWidth: 1,
borderRightWidth: 1,
borderBottomWidth: 1,
borderColor: '#f0f0f0',
},
fastContentText:{
flex: 1,
textAlign: 'center',
fontSize: 15,
color: '#393939',
},
fastContentImageContainer:{
flex: 1,
height: 40,
alignItems: 'center',
justifyContent: 'center',
borderLeftWidth: 1,
borderColor: '#f0f0f0',
},
fastContentImage:{
width: 30,
height: 30,
},
headerDescription1:{
width: width - 50,
marginLeft: 25,
marginRight: 25,
marginTop: 15,
textAlign: 'center',
fontSize: 11,
color: '#C0C0C0',
},
headerDescription2:{
width: width - 50,
marginLeft: 25,
marginRight: 25,
marginTop: 5,
marginBottom: 15,
textAlign: 'center',
fontSize: 11,
color: '#C0C0C0',
},
listContainer: {
width: width/2,
},
product: {
width: width/2,
backgroundColor: 'white',
height: productHeight,
},
});
... ...
'use strict';
import React, {Component} from 'react';
import ReactNative, {
View,
Text,
Image,
Button,
ListView,
StyleSheet,
Dimensions,
ScrollView,
TouchableOpacity,
Platform,
InteractionManager,
} from 'react-native';
export default class Magazine extends Component {
constructor(props) {
super(props);
this.renderRow = this.renderRow.bind(this);
this.dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => !Immutable.is(r1, r2),
});
}
renderRow(rowData,sectionID,rowID,highlightRow) {
if(rowID == 0){
return (
<Image style={styles.magazineImage} source={require('../../images/magazine1.png')} />
);
}
else if(rowID == 1){
return (
<Image style={styles.magazineImage} source={require('../../images/magazine2.png')} />
);
}
else if(rowID == 2){
return (
<Image style={styles.magazineImage} source={require('../../images/magazine3.png')} />
);
}
else if(rowID == 3){
return (
<Image style={styles.magazineImage} source={require('../../images/magazine1.png')} />
);
}
else
return null;
}
render() {
let content = "《YOHO!潮流志》、《YOHO!GIRL》是年轻人的潮流宝典,不仅网罗了方方面面的潮流讯息,"+
"亦会让你对话潮流明星和各大潮牌主理人,轻松掌握当季新品内容及背后故事,手把手教你如何变身潮人。";
let magazineData = [1,1,1];
return (
<ScrollView style={styles.container}>
<View style={styles.magazineContainer}>
<Text style={styles.magazineDesc}>{content}</Text>
</View>
<Text style={styles.about}>ABOUT</Text>
<ListView
style={styles.magazineList}
dataSource={this.dataSource.cloneWithRows(magazineData)}
horizontal={true}
renderRow={this.renderRow}
/>
<Text style={styles.yohoNowText1}>{"点击或扫描二维码YOHO!NOW APP"}</Text>
<TouchableOpacity style={styles.yohoNowImageContainer} activeOpacity={1} onPress={() => {
this.props.onPressYohoNow && this.props.onPressYohoNow();}}>
<Image style={styles.yohoNowImage} source={require('../../images/yohonow.png')} />
</TouchableOpacity>
</ScrollView>
);
}
}
let {width, height} = Dimensions.get('window');
const DEVICE_WIDTH_RATIO = width / 320;
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f0f0f0',
},
magazineContainer: {
width: width - 60,
height: 350,
backgroundColor: 'white',
marginTop: 40,
marginLeft: 30,
marginRight: 30,
marginBottom: 40,
},
about:{
position: 'absolute',
top: 10,
left: 50,
fontSize: 35,
color: 'rgb(212,169,68)',
fontWeight: 'bold',
},
magazineDesc:{
fontSize: 15,
color: 'rgb(33,33,33)',
fontWeight: 'bold',
marginTop: 20,
marginLeft: 12,
marginRight: 12,
},
magazineList:{
position: 'absolute',
top: 170,
left: 10,
width: width - 20,
},
magazineImage:{
width: 106,
height: 190,
marginLeft: 3,
marginRight: 3,
},
yohoNowText1:{
position: 'absolute',
top: 380,
width: width - 20,
},
yohoNowImageContainer:{
position: 'absolute',
top: 400,
height: 125,
},
yohoNowImage:{
width: 125,
height: 125,
},
});
... ...
... ... @@ -13,4 +13,16 @@ export default keyMirror({
GET_YEARACTIVITY_PRODUCT_SUCCESS:null,
GET_YEARACTIVITY_PRODUCT_FAILURE:null,
GET_FASTEXPRESS_INFO_REQUEST:null,
GET_FASTEXPRESS_INFO_SUCCESS:null,
GET_FASTEXPRESS_INFO_FAILURE:null,
GET_FASTEXPRESS_PRODUCT_REQUEST:null,
GET_FASTEXPRESS_PRODUCT_SUCCESS:null,
GET_FASTEXPRESS_PRODUCT_FAILURE:null,
GET_BIRTH_PRODUCT_REQUEST:null,
GET_BIRTH_PRODUCT_SUCCESS:null,
GET_BIRTH_PRODUCT_FAILURE:null,
});
... ...
'use strict'
import React, {Component} from 'react';
import ReactNative, {
StyleSheet,
Dimensions,
Platform,
View,
Text,
NativeModules,
InteractionManager,
NativeAppEventEmitter,
Alert,
} from 'react-native'
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {Map} from 'immutable';
import * as birthActions from '../reducers/birth/birthActions';
import Birth from '../components/birth/Birth';
const actions = [
birthActions,
];
function mapStateToProps(state) {
return {
...state
};
}
function mapDispatchToProps(dispatch) {
const creators = Map()
.merge(...actions)
.filter(value => typeof value === 'function')
.toObject();
return {
actions: bindActionCreators(creators, dispatch),
dispatch
};
}
class BirthContainer extends Component {
constructor(props) {
super(props);
this.onPressProductListProduct = this.onPressProductListProduct.bind(this);
this.onLongPressProduct = this.onLongPressProduct.bind(this);
this.onPressFindSimilar = this.onPressFindSimilar.bind(this);
this.onEndReached = this.onEndReached.bind(this);
this.onPressComplete = this.onPressComplete.bind(this);
}
componentDidMount() {
this.props.actions.getBirthProductList();
}
onPressComplete() {
let url = `http://m.yohobuy.com?openby:yohobuy={"action":"go.mineinfo","params":{}}`;
ReactNative.NativeModules.YH_CommonHelper.jumpWithUrl(url);
}
onEndReached() {
InteractionManager.runAfterInteractions(() => {
this.props.actions.getBirthProductList();
});
}
onPressProductListProduct(product, rowId=0) {
let productSkn = product && product.get('product_skn', 0);
if (!productSkn) {
return;
}
let url = `http://m.yohobuy.com?openby:yohobuy={"action":"go.productDetail","params":{"product_skn":"${productSkn}"}}`;
ReactNative.NativeModules.YH_CommonHelper.jumpWithUrl(url);
}
onLongPressProduct(rowID) {
if (rowID) {
this.props.actions.setSimilarIndex(rowID);
}
}
onPressFindSimilar(product) {
if (!product) {
return;
}
ReactNative.NativeModules.YH_CommonHelper.jumpFindSimilar(product.toJS());
}
render() {
let {isFetching, similarIndex, list} = this.props.birth;
return (
<Birth
isFetching={isFetching}
data={list}
similarIndex={similarIndex}
style={styles.container}
onEndReached={this.onEndReached}
onPressProductListProduct={this.onPressProductListProduct}
onLongPressProduct={this.onLongPressProduct}
onPressFindSimilar={this.onPressFindSimilar}
onPressComplete={this.onPressComplete}
/>
);
}
}
let styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default connect(mapStateToProps, mapDispatchToProps)(BirthContainer);
... ...
'use strict'
import React, {Component} from 'react';
import ReactNative, {
StyleSheet,
Dimensions,
Platform,
View,
Text,
NativeModules,
InteractionManager,
NativeAppEventEmitter,
Alert,
} from 'react-native'
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {Map} from 'immutable';
import * as fastExpressActions from '../reducers/fastExpress/fastExpressActions';
import FastExpress from '../components/fastExpress/FastExpress';
const actions = [
fastExpressActions,
];
function mapStateToProps(state) {
return {
...state
};
}
function mapDispatchToProps(dispatch) {
const creators = Map()
.merge(...actions)
.filter(value => typeof value === 'function')
.toObject();
return {
actions: bindActionCreators(creators, dispatch),
dispatch
};
}
class FastExpressContainer extends Component {
constructor(props) {
super(props);
this.onPressProductListProduct = this.onPressProductListProduct.bind(this);
this.onLongPressProduct = this.onLongPressProduct.bind(this);
this.onPressFindSimilar = this.onPressFindSimilar.bind(this);
this.onEndReached = this.onEndReached.bind(this);
}
componentDidMount() {
this.props.actions.getFastExpressInfo();
this.props.actions.getFastProductList();
}
onEndReached() {
InteractionManager.runAfterInteractions(() => {
this.props.actions.getFastProductList();
});
}
onPressProductListProduct(product, rowId=0) {
let productSkn = product && product.get('product_skn', 0);
if (!productSkn) {
return;
}
let url = `http://m.yohobuy.com?openby:yohobuy={"action":"go.productDetail","params":{"product_skn":"${productSkn}"}}`;
ReactNative.NativeModules.YH_CommonHelper.jumpWithUrl(url);
}
onLongPressProduct(rowID) {
if (rowID) {
this.props.actions.setSimilarIndex(rowID);
}
}
onPressFindSimilar(product) {
if (!product) {
return;
}
ReactNative.NativeModules.YH_CommonHelper.jumpFindSimilar(product.toJS());
}
render() {
let {isFetching,similarIndex, list, fastExpressList} = this.props.fastExpress;
return (
<FastExpress
isFetching={isFetching}
fastExpressList={fastExpressList}
data={list}
similarIndex={similarIndex}
style={styles.container}
onEndReached={this.onEndReached}
onPressProductListProduct={this.onPressProductListProduct}
onLongPressProduct={this.onLongPressProduct}
onPressFindSimilar={this.onPressFindSimilar}
/>
);
}
}
let styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default connect(mapStateToProps, mapDispatchToProps)(FastExpressContainer);
... ...
'use strict'
import React, {Component} from 'react';
import ReactNative, {
StyleSheet,
Dimensions,
Platform,
View,
Text,
NativeModules,
InteractionManager,
NativeAppEventEmitter,
Alert,
} from 'react-native'
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {Map} from 'immutable';
import * as magazineActions from '../reducers/magazine/magazineActions';
import Magazine from '../components/magazine/Magazine';
const actions = [
magazineActions,
];
function mapStateToProps(state) {
return {
...state
};
}
function mapDispatchToProps(dispatch) {
const creators = Map()
.merge(...actions)
.filter(value => typeof value === 'function')
.toObject();
return {
actions: bindActionCreators(creators, dispatch),
dispatch
};
}
class MagazineContainer extends Component {
constructor(props) {
super(props);
this.onPressYohoNow = this.onPressYohoNow.bind(this);
}
onPressYohoNow(){
ReactNative.NativeModules.YH_CommonHelper.searchYohoNow();
}
render() {
return (
<Magazine
style={styles.container}
onPressYohoNow={this.onPressYohoNow}
/>
);
}
}
let styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default connect(mapStateToProps, mapDispatchToProps)(MagazineContainer);
... ...
... ... @@ -7,6 +7,8 @@ let InitialState = Record({
host: 'http://api.yoho.cn',
serviceHost: 'http://service.yoho.cn',
privilegeId: 0,
userLevel: 3,
});
export default InitialState;
... ...
'use strict';
import ReactNative from 'react-native';
import BirthService from '../../services/birthService';
import Immutable, {Map} from 'immutable';
const {
SET_SIMILAR_PRODUCT_INDEX,
GET_BIRTH_PRODUCT_REQUEST,
GET_BIRTH_PRODUCT_SUCCESS,
GET_BIRTH_PRODUCT_FAILURE,
} = require('../../constants/actionTypes').default;
import parseUtils from '../../utils/parseUtils';
export function setSimilarIndex(rowID) {
return (dispatch, getState) => {
dispatch( {
type: SET_SIMILAR_PRODUCT_INDEX,
payload: {rowID},
});
}
}
export function getBirthProductList() {
return (dispatch, getState) => {
let {app, birth} = getState();
if (birth.get('isFetching') || birth.get('endReached')) {
return;
}
let userLevel = app.userLevel;
let page = birth.get('currentPage') + 1;
dispatch(getBirthProductRequest());
return new BirthService(app.host).getBirthProductList(userLevel, page)
.then(json => {
let payload = parseUtils.parsePageInfoList(json);
if (payload.currentPage > 1) {
let oldList = birth.get('list').toJS();
let newList = [...oldList, ...payload.list];
payload.list = newList;
}
//商品列表是否到末页
payload.endReached = (payload.list.length == 0) || (payload.currentPage == payload.pageCount);
dispatch(getBirthProductSuccess(payload));
})
.catch(error => {
dispatch(getBirthProductFailure());
});
};
}
export function getBirthProductRequest() {
return {
type: GET_BIRTH_PRODUCT_REQUEST,
};
}
export function getBirthProductSuccess(json) {
return {
type: GET_BIRTH_PRODUCT_SUCCESS,
payload: json
}
}
export function getBirthProductFailure(error) {
return {
type: GET_BIRTH_PRODUCT_FAILURE,
payload: error
}
}
... ...
'use strict';
import {Record, List, Map} from 'immutable';
let InitialState = Record({
isFetching: false,
list: List(),
currentPage: 0,
endReached: false,
similarIndex: -1,
total: 0,
pageSize: 50,
pageCount: 0,
});
export default InitialState;
... ...
'use strict';
import InitialState from './birthInitialState';
import Immutable, {Map} from 'immutable';
const {
SET_TYPE,
SET_SIMILAR_PRODUCT_INDEX,
GET_BIRTH_PRODUCT_REQUEST,
GET_BIRTH_PRODUCT_SUCCESS,
GET_BIRTH_PRODUCT_FAILURE,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
export default function birthReducer(state=initialState, action) {
switch(action.type) {
case SET_SIMILAR_PRODUCT_INDEX: {
return state.set('similarIndex', action.payload.rowID);
}
case GET_BIRTH_PRODUCT_REQUEST: {
return state.set('isFetching', true);
}
case GET_BIRTH_PRODUCT_SUCCESS:{
let json = action.payload;
return state.set('isFetching', false)
.set('list', Immutable.fromJS(json.list))
.set('currentPage', json.currentPage)
.set('pageCount', json.pageCount)
.set('total', json.total)
.set('endReached', json.endReached);
}
case GET_BIRTH_PRODUCT_FAILURE: {
return state.set('isFetching', false);
}
}
return state;
}
... ...
'use strict';
import ReactNative from 'react-native';
import FastExpressService from '../../services/fastExpressService';
import Immutable, {Map} from 'immutable';
const {
SET_TYPE,
SET_SIMILAR_PRODUCT_INDEX,
GET_FASTEXPRESS_INFO_REQUEST,
GET_FASTEXPRESS_INFO_SUCCESS,
GET_FASTEXPRESS_INFO_FAILURE,
GET_FASTEXPRESS_PRODUCT_REQUEST,
GET_FASTEXPRESS_PRODUCT_SUCCESS,
GET_FASTEXPRESS_PRODUCT_FAILURE,
} = require('../../constants/actionTypes').default;
import parseUtils from '../../utils/parseUtils';
export function setSimilarIndex(rowID) {
return (dispatch, getState) => {
dispatch( {
type: SET_SIMILAR_PRODUCT_INDEX,
payload: {rowID},
});
}
}
export function getFastExpressInfo() {
return (dispatch, getState) => {
let {app, fastExpress} = getState();
return new FastExpressService(app.host).getFastExpressInfo()
.then(json => {
dispatch(getFastExpressInfoSuccess(json));
})
.catch(error => {
dispatch(getFastExpressInfoFailure());
});
};
}
export function getFastProductList() {
return (dispatch, getState) => {
let {app, fastExpress} = getState();
if (fastExpress.get('isFetching') || fastExpress.get('endReached')) {
return;
}
let userLevel = app.userLevel;
let page = fastExpress.get('currentPage') + 1;
dispatch(getFastProductRequest());
return new FastExpressService(app.host).getFastExpressProduct(userLevel, page)
.then(json => {
let payload = parseUtils.parsePageInfoList(json);
if (payload.currentPage > 1) {
let oldList = fastExpress.get('list').toJS();
let newList = [...oldList, ...payload.list];
payload.list = newList;
}
//商品列表是否到末页
payload.endReached = (payload.list.length == 0) || (payload.currentPage == payload.pageCount);
dispatch(getFastProductSuccess(payload));
})
.catch(error => {
dispatch(getFastProductFailure());
});
};
}
export function getFastExpressInfoRequest() {
return {
type: GET_FASTEXPRESS_INFO_REQUEST,
};
}
export function getFastExpressInfoSuccess(json) {
return {
type: GET_FASTEXPRESS_INFO_SUCCESS,
payload: json
}
}
export function getFastExpressInfoFailure(error) {
return {
type: GET_FASTEXPRESS_INFO_FAILURE,
payload: error
}
}
export function getFastProductRequest() {
return {
type: GET_FASTEXPRESS_PRODUCT_REQUEST,
};
}
export function getFastProductSuccess(json) {
return {
type: GET_FASTEXPRESS_PRODUCT_SUCCESS,
payload: json
}
}
export function getFastProductFailure(error) {
return {
type: GET_FASTEXPRESS_PRODUCT_FAILURE,
payload: error
}
}
... ...
'use strict';
import {Record, List, Map} from 'immutable';
let InitialState = Record({
isFetching: false,
list: List(),
currentPage: 0,
endReached: false,
similarIndex: -1,
total: 0,
pageSize: 50,
pageCount: 0,
fastExpressList: List(),
});
export default InitialState;
... ...
'use strict';
import InitialState from './fastExpressInitialState';
import Immutable, {Map} from 'immutable';
const {
SET_TYPE,
SET_SIMILAR_PRODUCT_INDEX,
GET_FASTEXPRESS_INFO_REQUEST,
GET_FASTEXPRESS_INFO_SUCCESS,
GET_FASTEXPRESS_INFO_FAILURE,
GET_FASTEXPRESS_PRODUCT_REQUEST,
GET_FASTEXPRESS_PRODUCT_SUCCESS,
GET_FASTEXPRESS_PRODUCT_FAILURE,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
export default function fastExpressReducer(state=initialState, action) {
switch(action.type) {
case SET_SIMILAR_PRODUCT_INDEX: {
return state.set('similarIndex', action.payload.rowID);
}
case GET_FASTEXPRESS_INFO_REQUEST: {
return state.set('isFetching', true);
}
case GET_FASTEXPRESS_INFO_SUCCESS:{
return state.set('isFetching', false)
.set('fastExpressList', Immutable.fromJS(action.payload));
}
case GET_FASTEXPRESS_INFO_FAILURE: {
return state.set('isFetching', true);
}
case GET_FASTEXPRESS_PRODUCT_REQUEST: {
return state.set('isFetching', true);
}
case GET_FASTEXPRESS_PRODUCT_SUCCESS:{
let json = action.payload;
return state.set('isFetching', false)
.set('list', Immutable.fromJS(json.list))
.set('currentPage', json.currentPage)
.set('pageCount', json.pageCount)
.set('total', json.total)
.set('endReached', json.endReached);
}
case GET_FASTEXPRESS_PRODUCT_FAILURE: {
return state.set('isFetching', false);
}
}
return state;
}
... ...
import {combineReducers} from 'redux';
import app from './app/appReducer';
import yearActivity from './yearActivity/yearActivityReducer';
import fastExpress from './fastExpress/fastExpressReducer';
import birth from './birth/birthReducer';
const rootReducer = combineReducers({
app,
yearActivity,
fastExpress,
birth,
});
export default rootReducer;
... ...
'use strict';
import ReactNative from 'react-native';
import Immutable, {Map} from 'immutable';
const {
SET_SIMILAR_PRODUCT_INDEX,
} = require('../../constants/actionTypes').default;
import parseUtils from '../../utils/parseUtils';
export function setSimilarIndex(rowID) {
return (dispatch, getState) => {
dispatch( {
type: SET_SIMILAR_PRODUCT_INDEX,
payload: {rowID},
});
}
}
\ No newline at end of file
... ...
'use strict';
import Request from '../../common/services/NativeRequest';
export default class birthService {
constructor (host) {
let baseURL = 'http://api.yoho.cn';
if(host){
baseURL = host;
}
this.api = new Request(baseURL);
}
async getBirthProductList(userLevel, page){
return await this.api.get({
url: '',
body: {
method: 'app.product.vip',
user_vip_level: userLevel,
page,
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
}
... ...
'use strict';
import Request from '../../common/services/NativeRequest';
export default class fastExpressService {
constructor (host) {
let baseURL = 'http://api.yoho.cn';
if(host){
baseURL = host;
}
this.api = new Request("http://192.168.103.59:8080/gateway/");
}
async getFastExpressInfo(){
return await this.api.get({
url: '',
body: {
method: 'app.vipgrade.fastexpress',
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
async getFastExpressProduct(userLevel, page){
return await this.api.get({
url: '',
body: {
method: 'app.product.vip',
user_vip_level: userLevel,
page,
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
}
... ...