Authored by yoho-js001

Part of UI.

... ... @@ -90,14 +90,14 @@ export default class Tags extends React.Component {
let {style, items} = this.props;
// let tags = ['is_discount', 'resale', ];
let ary = items?items.toArray():[];
return (
<View style={[styles.container]}>
<ListView
style={[styles.container]}
contentContainerStyle={[styles.contentContainer]}
enableEmptySections={true}
dataSource={this.dataSource.cloneWithRows(items.toArray())}
dataSource={this.dataSource.cloneWithRows(ary)}
renderRow={this._renderRow}
scrollEnabled={false}
scrollsToTop={false}
... ...
'use strict';
import React, {Component} from 'react';
import ReactNative, {
View,
Text,
Image,
Platform,
ListView,
StyleSheet,
Dimensions,
TouchableOpacity,
} from 'react-native';
import SlicedImage from '../../../common/components/SlicedImage';
export default class ProductListCell extends Component {
constructor(props) {
super(props);
this._renderImages = this._renderImages.bind(this);
}
_renderImages() {
let {data, sourceType} = this.props;
let url = data?data.get('default_images').replace('{width}', rowWidth).replace('{height}', imageHeight):'http://imgsrc.baidu.com/forum/pic/item/770a6d2f12d46d7f71f05d7c.jpg'; // 商品缩略图
return (
<View style={styles.imageContainer}>
<Image style={styles.image} source={{uri: url}}>
</Image>
</View>
);
}
render() {
let {data, sourceType, rowID, style} = this.props;
return (
<TouchableOpacity
style={[styles.container, style]}
activeOpacity={1}
onPress={() => {
this.props.onPressProduct && this.props.onPressProduct(data, rowID);
}}
>
<View>
{this._renderImages()}
</View>
</TouchableOpacity>
);
}
}
let {width, height} = Dimensions.get('window');
const DEVICE_WIDTH_RATIO = width / 320;
let rowWidth = Math.ceil(137.5 * DEVICE_WIDTH_RATIO);
let rowHeight = Math.ceil(254 * DEVICE_WIDTH_RATIO);
let rowMarginTop = Math.ceil(10 * DEVICE_WIDTH_RATIO);
let rowMarginBottom = Math.ceil(4 * DEVICE_WIDTH_RATIO);
const IMAGE_WIDTH = 145;
const IMAGE_HEIGHT = 193;
const IMAGE_RATIO = IMAGE_HEIGHT / IMAGE_WIDTH;
let imageTop = 14 * DEVICE_WIDTH_RATIO;
let imageHeight = rowWidth * IMAGE_RATIO;
let almostSoldOutImageHeight = Math.ceil(14 * DEVICE_WIDTH_RATIO);
let almostSoldOutImageTop = imageHeight - almostSoldOutImageHeight;
let nameMarginTop = Math.ceil(12 * DEVICE_WIDTH_RATIO);
let nameHeight = Math.ceil(36 * DEVICE_WIDTH_RATIO);
let priceMarginTop = Math.ceil(-4 * DEVICE_WIDTH_RATIO);
let gpSoldOutImageHeight = Math.ceil(25 * DEVICE_WIDTH_RATIO);
let tagHeight = Math.ceil(14 * DEVICE_WIDTH_RATIO);
let styles = StyleSheet.create({
container: {
width: rowWidth,
height: Platform.OS === 'ios'?rowHeight:rowHeight+4,
marginTop: rowMarginTop,
marginBottom: rowMarginBottom,
},
rowContainer: {
width: rowWidth,
height: Platform.OS === 'ios'?rowHeight:rowHeight+4,
},
imageContainer: {
width: rowWidth,
height: imageHeight,
backgroundColor: '#f0f0f0',
marginTop: tagHeight,
},
image: {
width: rowWidth,
height: imageHeight,
backgroundColor: '#f0f0f0',
},
soldOutImage: {
position: 'absolute',
top: 0,
left: 0,
width: rowWidth,
height: imageHeight,
},
almostSoldOutImage: {
top: almostSoldOutImageTop,
width: rowWidth,
height: almostSoldOutImageHeight,
backgroundColor: '#ff9e0d',
},
nameContainer: {
// justifyContent: 'center',
marginTop: nameMarginTop,
width: rowWidth,
height: nameHeight,
},
name: {
fontFamily: 'STHeitiSC-Light',
fontSize: 12,
color: '#444444',
},
priceContainer: {
flexDirection: 'row',
marginTop: priceMarginTop,
},
nowPrice: {
fontSize: 12,
color: '#d0021b',
},
oldPriceContainer: {
flexDirection: 'row',
marginLeft: 5,
},
oldPrice: {
fontSize: 12,
color: '#b0b0b0',
height: 16,
},
deleteLine: {
position: 'absolute',
top: (16 / 2) - 0.8,
left: 0,
right: 0,
height: 1,
backgroundColor: '#b0b0b0',
},
gpSoldOutImage: {
position: 'absolute',
top: 5,
right: 5,
width: gpSoldOutImageHeight,
height: gpSoldOutImageHeight,
},
});
... ...
'use strict';
import React, {Component} from 'react';
import ReactNative, {
View,
Text,
Image,
ListView,
StyleSheet,
Dimensions,
TouchableOpacity,
InteractionManager,
Platform,
} from 'react-native';
import Immutable, {Map} from 'immutable';
export default class BrandCell extends Component {
constructor(props) {
super(props);
}
render() {
return (
<View style={styles.container}>
</View>
);
}
}
let {width, height} = Dimensions.get('window');
let styles = StyleSheet.create({
container: {
height: 60,
width: 60,
backgroundColor: 'green',
marginLeft: 10,
},
});
... ...
... ... @@ -35,8 +35,10 @@ let {width, height} = Dimensions.get('window');
let styles = StyleSheet.create({
container: {
height: 100,
width: width,
width: width/2,
backgroundColor: 'green',
borderTopColor: 'black',
borderWidth: 1,
},
contentContainer: {
... ...
... ... @@ -18,7 +18,12 @@ import FeaturedCell from './FeaturedCell'
import LatestCommonCell from './LatestCommonCell'
import LatestSectionHeader from './LatestSectionHeader'
import RecommendCell from './RecommendCell'
import BrandProductMoreFilter from '../../../brandStore/components/brandStore/brandStoreSubView/Cells/BrandProductMoreFilter';
import ProductCategoryList from '../../../brandStore/components/brandStore/brandStoreSubView/Cells/ProductCategoryList';
import BrandProductFilter from '../../../brandStore/components/brandStore/brandStoreSubView/Cells/BrandProductFilter';
import YH_SectionView from '../../../community/components/home/YH_SectionView';
import BrandProductListCell from '../../../common/components/ListCell/ProductListCell';
import TagsCell from './TagsCell'
export default class NewArrival extends Component {
... ... @@ -30,6 +35,7 @@ export default class NewArrival extends Component {
this._renderFooter = this._renderFooter.bind(this);
this.trigggePullToRefresh = this.trigggePullToRefresh.bind(this);
this._renderSectionHeader = this._renderSectionHeader.bind(this);
this._onPressProductFilter = this._onPressProductFilter.bind(this);
this.dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => !Immutable.is(r1, r2),
... ... @@ -57,6 +63,19 @@ export default class NewArrival extends Component {
}
}
_onPressProductFilter(value){
if(value === 'filter'){
this.listView && this.listView.scrollTo({x: 0, y: yPosition, animated: false});
}
if(value==='default'){
this.listView && this.listView.scrollTo({x: 0, y: yPosition, animated: false});
}
this.props.onPressProductFilter && this.props.onPressProductFilter(value);
}
_renderRow(rowData, sectionID, rowID) {
switch (sectionID) {
case 'banner': {
... ... @@ -77,13 +96,8 @@ export default class NewArrival extends Component {
]
);
return (
<BannerCell
data={testData}
duration={3}
width={width}
height={bannerHeight}
onPress={this.props.onPressBanner}
/>
<View style={{width: width, height: bannerHeight, backgroundColor: 'green'}}/>
);
}
break;
... ... @@ -100,9 +114,76 @@ export default class NewArrival extends Component {
}
break;
case 'latest': {
let paddingLeft = rowID % 2 == 1 ? rowMarginHorizontal / 2 : rowMarginHorizontal;
let customStyle = rowID == 0 || rowID == 1 ? {paddingLeft} : {paddingLeft};
if (rowID == 0) {
return (
<TagsCell style={[styles.listContainer, customStyle]}/>
)
}
let testData = {
"element_type":"product",
"small_sort_id": 125,
"vip1_price": 459,
"is_seckill": "N",
"gender": "1",
"product_price_plan_list": null,
"vip3_price": 459,
"is_global": "N",
"first_shelve_time": 1482980848,
"is_outlets": 2,
"is_discount": "Y",
"brand_domain": "5cm",
"is_special": null,
"vip_discount_type": 3,
"product_id": 505592,
"is_advance": "N",
"sales_num": 0,
"sales_phrase": "",
"is_student_rebate": "N",
"cn_alphabet": "5CMnandayi/fengyi",
"product_skn": 512584842,
"shelve_time": 0,
"is_deposit_advance": "N",
"vip2_price": 459,
"age_level": "1",
"is_student_price": "N",
"edit_time": 1482980848,
"is_new": "Y",
"student_price": null,
"is_limited": "N",
"brand_name": "5CM",
"max_sort_id": 1,
"product_name": "5CM男大衣/风衣",
"brand_id": 4,
"default_images": "http://imgsrc.baidu.com/forum/pic/item/770a6d2f12d46d7f71f05d7c.jpg",
"yohood_id": null,
"stock_number": 100,
"storage_num": 100,
"is_soon_sold_out": "N",
"middle_sort_id": 22,
"sales_price": 459,
"market_price": 500,
"is_promotion": 0,
"vip_price": 0,
"is_limitbuy": "N",
"country_id": 2,
"status": 1
}
return (
<LatestCommonCell/>
)
<BrandProductListCell
style={[styles.listContainer, customStyle]}
key={'row' + rowID}
rowID={rowID}
data={Immutable.fromJS(testData)}
onPressProduct={this.props.onPressProductListProduct}
/>
);
}
break;
default:
... ... @@ -115,7 +196,19 @@ export default class NewArrival extends Component {
switch (sectionID) {
case 'latest': {
return (
<LatestSectionHeader/>
<View
style={styles.brandFilterContainer}
onLayout={(evt) => {
yPosition = evt.nativeEvent.layout.y;
}}
>
<BrandProductFilter
onPressFilter={this._onPressProductFilter}
lastSelected={true}
moreFilter={true}
selectOrder={'s_p_desc'}
/>
</View>
)
}
... ... @@ -142,6 +235,14 @@ export default class NewArrival extends Component {
'latest': [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
}
let {
isFetching,
productList,
categoryFilterList,
filterCategoryDetailFilterList,
filterNameFactors,
} = this.props;
return (
<View style={styles.container}>
<ListView
... ... @@ -156,6 +257,20 @@ export default class NewArrival extends Component {
renderFooter={this._renderFooter}
renderSectionHeader={this._renderSectionHeader}
/>
{productList.isFilter ?
<ProductCategoryList
productList={productList}
onPressFilter={this._onPressProductFilter}
lastSelected={this.props.productList.isFilter}
moreFilter={this.props.productList.isMoreFilter}
selectOrder={this.props.productList.order}
categoryFilterList={categoryFilterList}
filterCategoryDetailFilterList={filterCategoryDetailFilterList}
onPressProductFilterLeftItem={this.props.onPressProductFilterLeftItem}
filterNameFactors={filterNameFactors}
onPressProductFilterRightItem={this.props.onPressProductFilterRightItem}
onPressCloseMoreFilter={this.props.onPressCloseMoreFilter}
onPressMoreFilter={this.props.onPressMoreFilter}/> : null}
</View>
);
}
... ... @@ -163,13 +278,31 @@ export default class NewArrival extends Component {
let {width, height} = Dimensions.get('window');
let bannerHeight = Math.ceil((363 / 750) * width);
let yPosition = 0;
let rowWidth = Math.ceil(137.5 * width / 320);
let rowHeight = Math.ceil(254 * width / 320);
let rowMarginTop = Math.ceil(10 * width / 320);
let rowMarginHorizontal = (width - rowWidth * 2) / 3;
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f0f0f0',
backgroundColor: 'white',
},
listContainer: {
width: width / 2,
},
contentContainer: {
flexDirection: 'row',
flexWrap: 'wrap',
},
brandFilterContainer: {
marginLeft: -1,
width: width + 2,
height: 40,
borderTopColor: '#e5e5e5',
borderBottomColor: '#e5e5e5',
borderWidth: 0.5,
},
});
... ...
... ... @@ -14,16 +14,39 @@ import ReactNative, {
} from 'react-native';
import Immutable, {Map} from 'immutable';
import BrandCell from './BrandCell'
export default class RecommendCell extends Component {
constructor(props) {
super(props);
this.dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2,
});
this._renderRow = this._renderRow.bind(this);
}
render() {
_renderRow(rowData, rowID) {
return (
<BrandCell/>
)
}
render() {
let dataSource = [0,1,1,1,1,2,2,2,2,0,0,0,0,0,0,0,0,0];
return (
<View style={styles.container}>
<View style={styles.header}>
<Text style={styles.headerText}>为您推荐</Text>
<TouchableOpacity style={styles.moreButton} onPress={()=>{console.log('.....');}}></TouchableOpacity>
</View>
<ListView
initialListSize={100}
contentContainerStyle={styles.contentContainer}
dataSource={this.dataSource.cloneWithRows(dataSource)}
renderRow={this._renderRow}
enableEmptySections={true}
horizontal={true}
showsHorizontalScrollIndicator={true}
/>
</View>
);
... ... @@ -38,7 +61,27 @@ let styles = StyleSheet.create({
width: width,
backgroundColor: 'brown',
},
header: {
backgroundColor: '#f0f0f0',
width: width,
height: 40,
alignItems: 'center',
flexDirection: 'row',
},
headerText: {
fontSize: 14,
color: 'black',
width: width,
textAlign: 'center',
},
moreButton: {
position: 'absolute',
backgroundColor: 'red',
width: 60,
height: 40,
left: width - 70,
},
contentContainer: {
backgroundColor: 'white',
},
});
... ...
'use strict';
import React, {Component} from 'react';
import ReactNative, {
View,
Text,
Image,
Platform,
ListView,
StyleSheet,
Dimensions,
TouchableOpacity,
} from 'react-native';
import SlicedImage from '../../../common/components/SlicedImage';
export default class ProductListCell extends Component {
constructor(props) {
super(props);
this._renderImages = this._renderImages.bind(this);
}
_renderImages() {
let {data, sourceType} = this.props;
let url = data?data.get('default_images').replace('{width}', rowWidth).replace('{height}', imageHeight):'http://imgsrc.baidu.com/forum/pic/item/770a6d2f12d46d7f71f05d7c.jpg'; // 商品缩略图
return (
<View style={styles.imageContainer}>
<Image style={styles.image} source={{uri: url}}>
</Image>
</View>
);
}
render() {
let {data, sourceType, rowID, style} = this.props;
return (
<TouchableOpacity
style={[styles.container, style]}
activeOpacity={1}
onPress={() => {
this.props.onPressProduct && this.props.onPressProduct(data, rowID);
}}
>
<View>
{this._renderImages()}
</View>
</TouchableOpacity>
);
}
}
let {width, height} = Dimensions.get('window');
const DEVICE_WIDTH_RATIO = width / 320;
let rowWidth = Math.ceil(137.5 * DEVICE_WIDTH_RATIO);
let rowHeight = Math.ceil(254 * DEVICE_WIDTH_RATIO);
let rowMarginTop = Math.ceil(10 * DEVICE_WIDTH_RATIO);
let rowMarginBottom = Math.ceil(4 * DEVICE_WIDTH_RATIO);
const IMAGE_WIDTH = 145;
const IMAGE_HEIGHT = 193;
const IMAGE_RATIO = IMAGE_HEIGHT / IMAGE_WIDTH;
let imageTop = 14 * DEVICE_WIDTH_RATIO;
let imageHeight = rowWidth * IMAGE_RATIO;
let almostSoldOutImageHeight = Math.ceil(14 * DEVICE_WIDTH_RATIO);
let almostSoldOutImageTop = imageHeight - almostSoldOutImageHeight;
let nameMarginTop = Math.ceil(12 * DEVICE_WIDTH_RATIO);
let nameHeight = Math.ceil(36 * DEVICE_WIDTH_RATIO);
let priceMarginTop = Math.ceil(-4 * DEVICE_WIDTH_RATIO);
let gpSoldOutImageHeight = Math.ceil(25 * DEVICE_WIDTH_RATIO);
let tagHeight = Math.ceil(14 * DEVICE_WIDTH_RATIO);
let styles = StyleSheet.create({
container: {
width: rowWidth,
height: Platform.OS === 'ios'?rowHeight:rowHeight+4,
marginTop: rowMarginTop,
marginBottom: rowMarginBottom,
},
rowContainer: {
width: rowWidth,
height: Platform.OS === 'ios'?rowHeight:rowHeight+4,
},
imageContainer: {
width: rowWidth,
height: imageHeight,
backgroundColor: '#f0f0f0',
marginTop: tagHeight,
},
image: {
width: rowWidth,
height: imageHeight,
backgroundColor: '#f0f0f0',
},
soldOutImage: {
position: 'absolute',
top: 0,
left: 0,
width: rowWidth,
height: imageHeight,
},
almostSoldOutImage: {
top: almostSoldOutImageTop,
width: rowWidth,
height: almostSoldOutImageHeight,
backgroundColor: '#ff9e0d',
},
nameContainer: {
// justifyContent: 'center',
marginTop: nameMarginTop,
width: rowWidth,
height: nameHeight,
},
name: {
fontFamily: 'STHeitiSC-Light',
fontSize: 12,
color: '#444444',
},
priceContainer: {
flexDirection: 'row',
marginTop: priceMarginTop,
},
nowPrice: {
fontSize: 12,
color: '#d0021b',
},
oldPriceContainer: {
flexDirection: 'row',
marginLeft: 5,
},
oldPrice: {
fontSize: 12,
color: '#b0b0b0',
height: 16,
},
deleteLine: {
position: 'absolute',
top: (16 / 2) - 0.8,
left: 0,
right: 0,
height: 1,
backgroundColor: '#b0b0b0',
},
gpSoldOutImage: {
position: 'absolute',
top: 5,
right: 5,
width: gpSoldOutImageHeight,
height: gpSoldOutImageHeight,
},
});
... ...
'use strict';
import React, {Component} from 'react';
import ReactNative, {
View,
Text,
Image,
Platform,
ListView,
StyleSheet,
Dimensions,
TouchableOpacity,
} from 'react-native';
import SlicedImage from '../../../common/components/SlicedImage';
export default class ProductListCell extends Component {
constructor(props) {
super(props);
this._renderImages = this._renderImages.bind(this);
this._renderTags = this._renderTags.bind(this);
}
_renderImages() {
let {data, sourceType} = this.props;
let url = data?data.get('default_images').replace('{width}', rowWidth).replace('{height}', imageHeight):'http://imgsrc.baidu.com/forum/pic/item/770a6d2f12d46d7f71f05d7c.jpg'; // 商品缩略图
return (
<View style={styles.imageContainer}>
<Image style={styles.image} source={{uri: url}}>
</Image>
</View>
);
}
_renderTags() {
testData.map((item, i) => {
console.log('......');
console.log(item);
return (
<View style={{backgroundColor: 'red',width: 30, height: 20}}>
</View>
);
})
}
render() {
let {data, sourceType, rowID, style} = this.props;
let testData = ['夹克','棉衣','衬衫','外套','鞋子','衬衫','外套','鞋子'];
return (
<TouchableOpacity
style={[styles.container, style]}
activeOpacity={1}
onPress={() => {
this.props.onPressProduct && this.props.onPressProduct(data, rowID);
}}
>
<View>
{this._renderImages()}
<View style={styles.bottomContainer}>
{testData.map((item, i) => {
return (
<View style={styles.tag} key={i}>
<TouchableOpacity style={styles.button} onPress={()=>{console.log(item);}}>
<Text style={styles.tagName}>{item}</Text>
</TouchableOpacity>
</View>
);
})}
</View>
</View>
</TouchableOpacity>
);
}
}
let {width, height} = Dimensions.get('window');
const DEVICE_WIDTH_RATIO = width / 320;
let rowWidth = Math.ceil(137.5 * DEVICE_WIDTH_RATIO);
let rowHeight = Math.ceil(254 * DEVICE_WIDTH_RATIO);
let rowMarginTop = Math.ceil(10 * DEVICE_WIDTH_RATIO);
let rowMarginBottom = Math.ceil(4 * DEVICE_WIDTH_RATIO);
const IMAGE_WIDTH = 145;
const IMAGE_HEIGHT = 193;
const IMAGE_RATIO = IMAGE_HEIGHT / IMAGE_WIDTH;
let imageTop = 14 * DEVICE_WIDTH_RATIO;
let imageHeight = rowWidth * IMAGE_RATIO;
let almostSoldOutImageHeight = Math.ceil(14 * DEVICE_WIDTH_RATIO);
let almostSoldOutImageTop = imageHeight - almostSoldOutImageHeight;
let nameMarginTop = Math.ceil(12 * DEVICE_WIDTH_RATIO);
let nameHeight = Math.ceil(36 * DEVICE_WIDTH_RATIO);
let priceMarginTop = Math.ceil(-4 * DEVICE_WIDTH_RATIO);
let gpSoldOutImageHeight = Math.ceil(25 * DEVICE_WIDTH_RATIO);
let tagHeight = Math.ceil(14 * DEVICE_WIDTH_RATIO);
let topHeight = Math.ceil(160 * width/750);
let bottomHeight = Math.ceil(400 * width/750);
let tagWidth = (rowWidth - 30)/2;
let tagHeight1 = 25;
let styles = StyleSheet.create({
container: {
width: rowWidth,
height: Platform.OS === 'ios'?rowHeight:rowHeight+4,
marginTop: rowMarginTop,
marginBottom: rowMarginBottom,
},
rowContainer: {
width: rowWidth,
height: Platform.OS === 'ios'?rowHeight:rowHeight+4,
},
imageContainer: {
width: rowWidth,
height: topHeight,
backgroundColor: '#f0f0f0',
marginTop: tagHeight,
},
image: {
width: rowWidth,
height: topHeight,
backgroundColor: '#f0f0f0',
},
bottomContainer: {
backgroundColor: '#f0f0f0',
width: rowWidth,
height: bottomHeight,
flexDirection: 'row',
flexWrap: 'wrap',
paddingTop: 25,
justifyContent: 'space-between',
paddingLeft: 10,
paddingRight: 10,
},
tag: {
backgroundColor: 'white',
width: tagWidth,
height: tagHeight1,
marginTop: 0,
marginBottom: 15,
borderRadius: 3,
},
button: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
},
tagName: {
fontFamily: 'STHeitiSC-Light',
fontSize: 12,
color: '#444444',
textAlign: 'center',
width: tagWidth,
},
});
... ...
... ... @@ -6,7 +6,16 @@ export default keyMirror({
SET_HOST: null,
SET_SERVICE_HOST: null,
SET_CHANNEL: null,
RECOMMEND_SHOP_REQUEST: null,
RECOMMEND_SHOP_SUCCESS: null,
RECOMMEND_SHOP_FAILURE: null,
RECOMMEND_BRAND_REQUEST: null,
RECOMMEND_BRAND_SUCCESS: null,
RECOMMEND_BRAND_FAILURE: null,
PRODUCT_LIST_REQUEST: null,
PRODUCT_LIST_SUCCESS: null,
PRODUCT_LIST_FAILURE: null,
});
... ...
... ... @@ -48,10 +48,11 @@ class NewArrivalContainer extends Component {
super(props);
this._onEndReached = this._onEndReached.bind(this);
this._onPressProductFilter = this._onPressProductFilter.bind(this);
}
componentDidMount() {
}
componentWillUnmount() {
... ... @@ -59,16 +60,42 @@ class NewArrivalContainer extends Component {
}
_onEndReached() {
}
}
_onPressProductFilter(value) {
if (value === 'filter') {
this.props.actions.setFilterView(!this.props.newArrival.productList.isFilter);
this.props.actions.setFilterMoreView(false);
} else if(value === 'default'){
this.props.actions.setFilterMoreView(!this.props.newArrival.productList.isMoreFilter);
this.props.actions.setFilterView(false);
}else{
this.props.actions.setFilterMoreView(false);
this.props.actions.setFilterView(false);
this.props.actions.resetListPageInfo();
this.props.actions.setProductListFilter(value);
this.props.actions.getProductList(true);
}
}
render() {
let {newArrival} = this.props;
let {
categoryFilterList,
filterCategoryDetailFilterList,
productList,
filterFactors,
filterNameFactors,
} = newArrival;
let isFetching = productList.isFetching;
return (
<View style={styles.container}>
<NewArrival
data={newArrival}
onEndReached={this._onEndReached}
isFetching={isFetching}
productList={productList}
categoryFilterList={categoryFilterList}
filterCategoryDetailFilterList={filterCategoryDetailFilterList}
filterNameFactors={filterNameFactors}
/>
</View>
);
... ...
... ... @@ -5,7 +5,319 @@ import NewArrivalService from '../../services/NewArrivalService';
const {
SET_CHANNEL,
RECOMMEND_SHOP_REQUEST,
RECOMMEND_SHOP_SUCCESS,
RECOMMEND_SHOP_FAILURE,
RECOMMEND_BRAND_REQUEST,
RECOMMEND_BRAND_SUCCESS,
RECOMMEND_BRAND_FAILURE,
PRODUCT_LIST_REQUEST,
PRODUCT_LIST_SUCCESS,
PRODUCT_LIST_FAILURE,
} = require('../../constants/actionTypes').default;
export function getTopInfo() {
return (dispatch, getState) => {
let {app} = getState();
dispatch(topInfoRequest());
return new NewArrivalService(app.host).fetchRecommendShop(channel)
.then(json => {
dispatch(topInfoSuccess(json));
})
.catch(error => {
dispatch(topInfoFailure(error));
});
}
}
export function topInfoRequest() {
return {
type: RECOMMEND_SHOP_REQUEST,
};
}
export function topInfoSuccess(json) {
return {
type: RECOMMEND_SHOP_SUCCESS,
payload: json
}
}
export function topInfoFailure(error) {
return {
type: RECOMMEND_SHOP_FAILURE,
payload: error
}
}
/*
* 底部产品列表
*/
export function getProductList(reload=false) {
return (dispatch, getState) => {
let {app, newArrival} = getState();
let { productList, filterFactors} = newArrival;
if (reload) {
} else {
if (productList.isFetching || productList.endReached || productList.error) {
return;
}
}
let order = productList.order;
let page = productList.currentPage + 1;
let pageSize = productList.pageSize;
let channel = app.channel;
let bSelectedFilterFactor,allFilterFactors;
allFilterFactors = filterFactors.toJS();
for (let prop in allFilterFactors) {
if (allFilterFactors.hasOwnProperty(prop)) {
if (allFilterFactors[prop] === '') {
delete allFilterFactors[prop];
}
if (prop == 'sizeKey') {
allFilterFactors['size'] = allFilterFactors[prop];
delete allFilterFactors[prop];
}
}
}
dispatch(productListRequest());
return new NewArrivalService(app.host).productList(channel, order, page, pageSize, allFilterFactors)
.then(json => {
let payload = parseProductList(json);
payload.endReached = payload.currentPage == payload.pageCount || payload.list.length < pageSize;
if (payload.currentPage > 1) {
let oldList = productList.list.toJS();
let list = [...oldList, ...payload.list];
payload.list = list;
}
dispatch(productListSuccess(payload));
})
.catch(error => {
dispatch(productListFailure(error));
});
};
}
export function productListRequest() {
return {
type: PRODUCT_LIST_REQUEST,
};
}
export function productListSuccess(json) {
return {
type: PRODUCT_LIST_SUCCESS,
payload: json
}
}
export function productListFailure(error) {
return {
type: PRODUCT_LIST_FAILURE,
payload: error
}
}
function parseProductList(json) {
let currentPage = json && json.page ? json.page : 1;
let pageCount = json && json.page_total ? json.page_total : 0;
let total = json && json.total ? json.total : 0;
let filter = json && json.filter ? json.filter : {};
let list = json && json.product_list ? json.product_list : [];
let filterCategoryDetailFilterList = {};
let categoryFilterList = [];
if (filter['gender']) {
categoryFilterList.push({
key: 'gender',
name: '性别',
isSelect: true,
});
let genderList = filter['gender'];
let newGenderList =[];
newGenderList.push({
key:'1,2,3',
name: '所有性别',
isSelect: true,
});
for (let gender in genderList) {
if (genderList.hasOwnProperty(gender)) {
newGenderList.push({
key: gender,
name: genderList[gender],
isSelect: false,
});
}
}
filterCategoryDetailFilterList.gender;
filterCategoryDetailFilterList.gender = newGenderList;
}
if (filter['group_sort']) {
categoryFilterList.push({
key: 'sort',
name: '品类',
isSelect: false,
});
let sortList = filter['group_sort'];
let newSortList = [];
newSortList.push({
key: '',
name: '所有品类',
isSelect: true,
});
sortList.map((item, i) => {
newSortList.push({
key: item.relation_parameter.sort ? item.relation_parameter.sort : '',
name: item.category_name,
isSelect: false,
})
});
filterCategoryDetailFilterList.sort;
filterCategoryDetailFilterList.sort = newSortList;
}
if (filter['brand']) {
categoryFilterList.push({
key: 'brand',
name: '品牌',
isSelect: false,
});
let brandList = filter['brand'];
let newBrandList = [];
newBrandList.push({
key: '',
name: '所有品牌',
isSelect: true,
});
brandList.map((item, i) => {
newBrandList.push({
key: item.id,
name: item.brand_name,
isSelect: false,
})
});
filterCategoryDetailFilterList.brand;
filterCategoryDetailFilterList.brand = newBrandList;
}
if (filter['color']) {
categoryFilterList.push({
key: 'color',
name: '颜色',
isSelect: false,
});
let colorList = filter['color'];
let newColorList = [];
newColorList.push({
key: '',
name: '所有颜色',
isSelect: true,
});
colorList.map((item, i) => {
newColorList.push({
key: item.color_id,
name: item.color_name,
isSelect: false,
});
});
filterCategoryDetailFilterList.color;
filterCategoryDetailFilterList.color = newColorList;
}
if (filter['size']) {
categoryFilterList.push({
key: 'sizeKey',
name: '尺码',
isSelect: false,
});
let sizeList = filter['size'];
let newSizeList = [];
newSizeList.push({
key: '',
name: '所有尺码',
isSelect: true,
});
sizeList.map((item, i) => {
newSizeList.push({
key: item.size_id,
name: item.size_name,
isSelect: false,
});
});
filterCategoryDetailFilterList.sizeKey;
filterCategoryDetailFilterList.sizeKey = newSizeList;
}
if (filter['priceRange']) {
categoryFilterList.push({
key: 'price',
name: '价格',
isSelect: false,
});
let priceObject = filter['priceRange'];
priceObject = sortListByField(priceObject, 'name'); // 折扣,价格区间,需要排序
let newPriceList = [];
newPriceList.push({
key: '',
name: '所有价格',
isSelect: true,
});
_.forEach(priceObject, (v, k) => {
newPriceList.push({
key: v._key,
name: v._value,
isSelect: false,
});
});
filterCategoryDetailFilterList.price;
filterCategoryDetailFilterList.price = newPriceList;
}
if (filter['discount']) {
categoryFilterList.push({
key: 'p_d',
name: '折扣',
isSelect: false,
});
let p_dObject = filter['discount'];
p_dObject = sortListByField(p_dObject, 'name'); // 折扣,价格区间,需要排序
let newP_dList = [];
newP_dList.push({
key: '',
name: '所有折扣',
isSelect: true,
});
_.forEach(p_dObject, (v, k) => {
newP_dList.push({
key: v._key,
name: v.name,
isSelect: false,
});
});
filterCategoryDetailFilterList.p_d;
filterCategoryDetailFilterList.p_d = newP_dList;
}
return {
list,
categoryFilterList,
filterCategoryDetailFilterList,
currentPage,
pageCount,
total,
};
}
... ...
... ... @@ -3,7 +3,49 @@
import {Record, List, Map} from 'immutable';
let InitialState = Record({
topPart: new (Record({
isFetching: false,
error: null,
topList: List(),
brandList: List(),
featuredList: List(),
})),
categoryFilterList: List(),
filterCategoryDetailFilterList: List(),
productList: new (Record({
isFetching: false,
isFilter: false,
isMoreFilter:false,
error: null,
list: List(),
order: 's_n_desc',
currentPage: 0,
pageCount: 0,
pageSize: 60,//60,
total: 0,
endReached: false,
sourceType: 0, // 0 - 默认,1 - 购,全球2 - 奥莱
})),
filterFactors: new (Record({
gender: '', //性别
color: '', //颜色
price: '', //价格
sizeKey: '', //尺码
p_d: '', //折扣
sort: '', //品类
brand: '', //品牌
})),
filterNameFactors: new (Record({
gender: '所有性别', //性别
color: '所有颜色', //颜色
price: '所有价格', //价格
sizeKey: '所有尺码', //尺码
p_d: '所有折扣', //折扣
sort: '所有品类', //品类
brand: '所有品牌', //品牌
})),
});
export default InitialState;
... ...
... ... @@ -6,6 +6,17 @@ import Immutable, {Map} from 'immutable';
const {
SET_CHANNEL,
RECOMMEND_SHOP_REQUEST,
RECOMMEND_SHOP_SUCCESS,
RECOMMEND_SHOP_FAILURE,
RECOMMEND_BRAND_REQUEST,
RECOMMEND_BRAND_SUCCESS,
RECOMMEND_BRAND_FAILURE,
PRODUCT_LIST_REQUEST,
PRODUCT_LIST_SUCCESS,
PRODUCT_LIST_FAILURE,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
... ... @@ -13,7 +24,64 @@ const initialState = new InitialState;
export default function newArrivalReducer(state=initialState, action) {
switch(action.type) {
case RECOMMEND_SHOP_REQUEST: {
return state.setIn(['topPart', 'isFetching'], true).setIn(['topPart', 'error'], null);
}
case RECOMMEND_SHOP_SUCCESS: {
let {
first_part,
shop_list,
second_part,
} = action.payload;
return state.setIn(['topPart', 'topList'], Immutable.fromJS(first_part))
.setIn(['topPart', 'brandList'], Immutable.fromJS(shop_list))
.setIn(['topPart', 'featuredList'], Immutable.fromJS(second_part));
}
case RECOMMEND_SHOP_FAILURE: {
return state.setIn(['topPart', 'isFetching'], false)
.setIn(['topPart', 'error'], action.payload);
}
case PRODUCT_LIST_REQUEST: {
return state.setIn(['productList', 'isFetching'], true)
.setIn(['productList', 'error'], null);
}
case PRODUCT_LIST_SUCCESS: {
let {
list,
categoryFilterList,
filterCategoryDetailFilterList,
currentPage,
pageCount,
total,
recId,
endReached,
} = action.payload;
let newState = state.setIn(['productList', 'isFetching'], false)
.setIn(['productList', 'error'], null)
.setIn(['productList', 'list'], Immutable.fromJS(list))
.setIn(['productList', 'currentPage'], currentPage)
.setIn(['productList', 'pageCount'], pageCount)
.setIn(['productList', 'total'], total)
.setIn(['productList', 'recId'], recId)
.setIn(['productList', 'endReached'], endReached);
if (currentPage == 1 && state.categoryFilterList.size == 0 && state.filterCategoryDetailFilterList.size == 0) {
newState = newState.set('categoryFilterList', Immutable.fromJS(categoryFilterList))
.set('filterCategoryDetailFilterList', Immutable.fromJS(filterCategoryDetailFilterList));
}
return newState;
}
case PRODUCT_LIST_FAILURE: {
return state.setIn(['productList', 'isFetching'], false)
.setIn(['productList', 'error'], action.payload);
}
}
return state;
... ...
... ... @@ -11,5 +11,61 @@ export default class HomeService {
}
this.api = new Request(baseURL);
}
async fetchRecommendShop(yh_channel) {
return await this.api.get({
url: '',
body: {
method: 'app.newproduct.rec.shop',
yh_channel,
limit: 10,
page: 1,
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
async fetchRecommendBrand(yh_channel) {
return await this.api.get({
url: '',
body: {
method: 'app.newproduct.rec.brand',
yh_channel,
limit: 60,
page: 1,
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
async productList(yh_channel=1, order='s_t_asc', page=1, limit=60, filterFactors={}) {
return await this.api.get({
url: '',
body: {
method: 'app.search.li',
yh_channel,
order,
page,
limit,
...filterFactors,
brand,
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
}
... ...