Authored by chenl

Merge branch '5.4' of http://git.yoho.cn/mobile/YH_RNComponent into local

... ... @@ -10,6 +10,9 @@ import Classify from './classify/Classify';
import Seckill from './seckill/Seckill';
import Guang from './guang/Guang';
import Message from './message/Message';
import NewArrival from './newArrival/NewArrival';
// import Search from './search/Search';
export default function native(platform) {
... ... @@ -19,7 +22,8 @@ export default function native(platform) {
Seckill(platform);
Guang(platform);
Plustar(platform);
Message(platform)
NewArrival(NewArrival)
if (Platform.OS === 'ios') {
Community(platform);
... ...
... ... @@ -123,7 +123,6 @@ export default function brandStoreReducer(state=initialState, action) {
.set('is_show_shop_name', is_show_shop_name)
.set('shop_domain', shop_domain)
.set('shops_id', shops_id)
.set('is_addFav',false);
let nextState = state.set('info', info);
return nextState;
}
... ...
... ... @@ -41,21 +41,17 @@ export default class BannerReourceList extends React.Component {
<TouchableOpacity activeOpacity={0.5} onPress={() => {
this.props.onPressSlideItem && this.props.onPressSlideItem(rowData, rowID);
}}>
<View style={styles.row}>
<View style={styles.thumbnailV}>
<Image
source={{uri: newSrc}}
style={styles.thumbnail}
resizeMode={'contain'}
>
<View style={styles.textV}>
<Text style={styles.text} numberOfLines={1}>
{rowData.name}
</Text>
</View>
</Image>
</View>
<View style={styles.thumbnailV}>
<Image
source={{uri: newSrc}}
style={styles.thumbnail}
resizeMode={'contain'}
></Image>
<View style={styles.textV}>
<Text style={styles.text} numberOfLines={1}>
{rowData.name}
</Text>
</View>
</View>
</TouchableOpacity>
);
... ... @@ -113,14 +109,9 @@ let styles = StyleSheet.create({
width:Dimensions.get('window').width,
backgroundColor: 'white',
},
row: {
marginLeft: 10,
width: itemWidth,
height: itemWidth,
backgroundColor: 'white',
},
textV: {
marginTop: itemHeight - 20,
position: 'absolute',
top: itemHeight - 20,
width: itemWidth,
alignItems: 'center',
height: 20,
... ... @@ -140,6 +131,7 @@ let styles = StyleSheet.create({
fontWeight: 'bold',
},
thumbnailV: {
marginLeft: 10,
width: itemWidth,
height: itemHeight,
backgroundColor: 'white',
... ...
'use strict';
import React from 'react';
import ReactNative, {
AppRegistry,
Platform,
} from 'react-native';
import {
Provider,
connect
} from 'react-redux';
import configureStore from './store/configureStore';
import {Record, List, Map} from 'immutable';
import appInitialState from './reducers/app/appInitialState';
import messageInitialState from './reducers/message/messageInitialState';
import MessageContainer from './containers/MessageContainer';
import {
setPlatform,
setHost,
setServiceHost,
} from './reducers/app/appActions';
function getInitialState() {
const _initState = {
app: (new appInitialState()),
message: (new messageInitialState()),
};
return _initState;
}
export default function native(platform) {
let YH_Message = React.createClass({
render() {
const store = configureStore(getInitialState());
store.dispatch(setPlatform(platform));
store.dispatch(setHost(this.props.host));
store.dispatch(setServiceHost(this.props.serviceHost));
return (
<Provider store={store}>
<MessageContainer />
</Provider>
);
}
});
AppRegistry.registerComponent('YH_Message', () => YH_Message);
}
... ...
'use strict';
import React, {Component} from 'react';
import ReactNative, {
View,
Text,
Image,
ListView,
StyleSheet,
Dimensions,
TouchableOpacity,
InteractionManager,
Platform,
} from 'react-native';
export default class Message 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) {
return (
<TouchableOpacity
onPress={() => {
console.log(rowID)
}}
>
<View style={styles.rowContainer}>
<Text>{rowData.get('title')}</Text>
<Text>{rowData.get('detail')}</Text>
</View>
</TouchableOpacity>
);
}
render() {
let dataSource = this.props.data.dataSource.toArray();
return (
<View style={styles.container}>
<ListView
contentContainerStyle={styles.contentContainer}
dataSource={this.dataSource.cloneWithRows(dataSource)}
renderRow={this._renderRow}
enableEmptySections={true}
/>
</View>
);
}
}
let {width, height} = Dimensions.get('window');
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f0f0f0',
},
contentContainer: {
},
rowContainer: {
},
});
... ...
import keyMirror from 'key-mirror';
export default keyMirror({
SET_PLATFORM: null,
SET_HOST: null,
SET_SERVICE_HOST: null,
SET_CHANNEL: null,
});
... ...
'use strict'
import React, {Component} from 'react';
import ReactNative, {
StyleSheet,
Dimensions,
Platform,
View,
Text,
NativeModules,
InteractionManager,
NativeAppEventEmitter,
} from 'react-native'
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {Map} from 'immutable';
import * as messageActions from '../reducers/message/messageActions';
import Message from '../components/message/Message';
const actions = [
messageActions,
];
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 MessageContainer extends Component {
constructor(props) {
super(props);
this._onRefresh = this._onRefresh.bind(this);
}
componentDidMount() {
}
componentWillUnmount() {
}
_onRefresh() {
}
render() {
let {message} = this.props;
return (
<View style={styles.container}>
<Message
data={message}
onRefresh={this._onRefresh}
/>
</View>
);
}
}
let styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default connect(mapStateToProps, mapDispatchToProps)(MessageContainer);
... ...
'use strict';
import ReactNative from 'react-native';
const {
SET_PLATFORM,
SET_CHANNEL,
SET_HOST,
SET_SERVICE_HOST,
} = require('../../constants/actionTypes').default;
export function setPlatform(platform) {
return {
type: SET_PLATFORM,
payload: platform
};
}
export function setChannel(channel) {
return {
type: SET_CHANNEL,
payload: channel
};
}
export function setHost(host) {
return {
type: SET_HOST,
payload: host
};
}
export function setServiceHost(host) {
return {
type: SET_SERVICE_HOST,
payload: host
};
}
\ No newline at end of file
... ...
'use strict';
import {Record, List, Map} from 'immutable';
let InitialState = Record({
platform: 'ios', // ios, android
channel: 1, // 1 - boy, 2 - girl, 3 - kid, 4 - lifestyle, 5 - yoho
host: 'http://api.yoho.cn',
serviceHost: 'http://service.yoho.cn',
});
export default InitialState;
... ...
'use strict';
import InitialState from './appInitialState';
const {
SET_PLATFORM,
SET_CHANNEL,
SET_HOST,
SET_SERVICE_HOST,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
export default function appReducer(state = initialState, action) {
if (!(state instanceof InitialState)) return initialState.merge(state);
switch (action.type) {
case SET_PLATFORM:
return state.set('platform', action.payload);
case SET_CHANNEL:
return state.set('channel', action.payload);
case SET_HOST:
return state.set('host', action.payload);
case SET_SERVICE_HOST:
return state.set('serviceHost', action.payload);
}
return state;
}
... ...
import {combineReducers} from 'redux';
import app from './app/appReducer';
import message from './message/messageReducer';
const rootReducer = combineReducers({
app,
message,
});
export default rootReducer;
... ...
'use strict';
import ReactNative from 'react-native';
import MessageService from '../../services/MessageService';
const {
SET_CHANNEL,
} = require('../../constants/actionTypes').default;
... ...
'use strict';
import Immutable, {Record, List, Map} from 'immutable';
let dataSource = Immutable.fromJS([
{
id: 'member',
title: '会员信息',
detail: '会员等级变更提醒、会员生日福利',
},
{
id: 'asset',
title: '我的资产',
detail: '新注册用户提示新人专享优惠券信息',
},
{
id: 'customer',
title: '客户服务',
detail: '没有收到任何关于你的消息',
},
{
id: 'other',
title: '其他',
detail: '没有收到任何系统给消息',
},
]);
let InitialState = Record({
dataSource,
newMessage: new (Record({
isFetching: false,
error: null,
data: List(),
})),
});
export default InitialState;
... ...
'use strict';
import InitialState from './messageInitialState';
import Immutable, {Map} from 'immutable';
const {
SET_CHANNEL,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
export default function messageReducer(state=initialState, action) {
switch(action.type) {
}
return state;
}
... ...
'use strict';
import Request from '../../common/services/Request';
export default class MessageService {
constructor (host) {
let baseURL = 'http://api.yoho.cn';
if(host){
baseURL = host;
}
this.api = new Request(baseURL);
}
}
... ...
/**
* # configureStore.js
*
* A Redux boilerplate setup
*
*/
'use strict';
/**
* ## Imports
*
* redux functions
*/
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import createLogger from 'redux-logger';
/**
* ## Reducer
* The reducer contains the 4 reducers from
* device, global, auth, profile
*/
import reducer from '../reducers';
const logger = createLogger({
predicate: (getState, action) => process.env.NODE_ENV === `development`
});
/**
* ## creatStoreWithMiddleware
* Like the name...
*/
const createStoreWithMiddleware = applyMiddleware(
thunk,
logger
)(createStore);
/**
* ## configureStore
* @param {Object} the state with for keys:
* device, global, auth, profile
*
*/
export default function configureStore(initialState) {
return createStoreWithMiddleware(reducer, initialState);
};
... ...
'use strict';
import React from 'react';
import ReactNative, {
AppRegistry,
Platform,
} from 'react-native';
import {
Provider,
connect
} from 'react-redux';
import configureStore from './store/configureStore';
import {Record, List, Map} from 'immutable';
import appInitialState from './reducers/app/appInitialState';
import newArrivalInitialState from './reducers/newArrival/newArrivalInitialState';
import NewArrivalContainer from './containers/NewArrivalContainer';
import {
setPlatform,
setHost,
setServiceHost,
} from './reducers/app/appActions';
function getInitialState() {
const _initState = {
app: (new appInitialState()),
newArrival: (new newArrivalInitialState()),
};
return _initState;
}
export default function native(platform) {
let YH_NewArrival = React.createClass({
render() {
const store = configureStore(getInitialState());
store.dispatch(setPlatform(platform));
store.dispatch(setHost(this.props.host));
store.dispatch(setServiceHost(this.props.serviceHost));
return (
<Provider store={store}>
<NewArrivalContainer />
</Provider>
);
}
});
AppRegistry.registerComponent('YH_NewArrival', () => YH_NewArrival);
}
... ...
'use strict';
import React, {Component} from 'react';
import ReactNative, {
View,
Text,
Image,
ListView,
StyleSheet,
Dimensions,
TouchableOpacity,
InteractionManager,
Platform,
} from 'react-native';
export default class NewArrival extends Component {
constructor(props) {
super(props);
this._renderRow = this._renderRow.bind(this);
this._onEndReached = this._onEndReached.bind(this);
this._renderFooter = this._renderFooter.bind(this);
this.trigggePullToRefresh = this.trigggePullToRefresh.bind(this);
this.dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => !Immutable.is(r1, r2),
});
}
componentDidMount() {
this.trigggePullToRefresh();
}
componentWillReceiveProps(nextProps) {
if (nextProps.data.ptr) {
this.listView && this.listView.scrollTo({x: 0, y: 0, animated: false, });
}
}
trigggePullToRefresh() {
if (Platform.OS === 'ios') {
InteractionManager.runAfterInteractions(() => {
this.listView && this.listView.getScrollResponder().startPullToRefresh();
});
} else {
this.props.onRefresh && this.props.onRefresh();
}
}
_renderRow(rowData: object, sectionID: number, rowID: number) {
return null;
}
_onEndReached() {
}
_renderFooter() {
return null;
}
render() {
let {list, ptr, isFetching, endReached, showLoginTip, cachedList} = this.props.data;
let dataSource = list.size == 0 ? cachedList.toArray() : list.toArray();
let isLoadingMore = list.size != 0 && !ptr && isFetching;
return (
<View style={styles.container}>
<ListView
ref={(c) => {
this.listView = c;
}}
contentContainerStyle={styles.contentContainer}
dataSource={this.dataSource.cloneWithRows(dataSource)}
renderRow={this._renderRow}
enableEmptySections={true}
onEndReached={this._onEndReached}
renderFooter={this._renderFooter}
/>
</View>
);
}
}
let {width, height} = Dimensions.get('window');
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f0f0f0',
},
contentContainer: {
},
});
... ...
import keyMirror from 'key-mirror';
export default keyMirror({
SET_PLATFORM: null,
SET_HOST: null,
SET_SERVICE_HOST: null,
SET_CHANNEL: null,
});
... ...
'use strict'
import React, {Component} from 'react';
import ReactNative, {
StyleSheet,
Dimensions,
Platform,
View,
Text,
NativeModules,
InteractionManager,
NativeAppEventEmitter,
} from 'react-native'
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {Map} from 'immutable';
import * as newArrivalActions from '../reducers/newArrival/newArrivalActions';
import NewArrival from '../components/newArrival/NewArrival';
const actions = [
newArrivalActions,
];
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 NewArrivalContainer extends Component {
constructor(props) {
super(props);
this._onEndReached = this._onEndReached.bind(this);
}
componentDidMount() {
}
componentWillUnmount() {
}
_onEndReached() {
}
render() {
let {newArrival} = this.props;
return (
<View style={styles.container}>
<NewArrival
data={newArrival}
onEndReached={this._onEndReached}
/>
</View>
);
}
}
let styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default connect(mapStateToProps, mapDispatchToProps)(NewArrivalContainer);
... ...
'use strict';
import ReactNative from 'react-native';
const {
SET_PLATFORM,
SET_CHANNEL,
SET_HOST,
SET_SERVICE_HOST,
} = require('../../constants/actionTypes').default;
export function setPlatform(platform) {
return {
type: SET_PLATFORM,
payload: platform
};
}
export function setChannel(channel) {
return {
type: SET_CHANNEL,
payload: channel
};
}
export function setHost(host) {
return {
type: SET_HOST,
payload: host
};
}
export function setServiceHost(host) {
return {
type: SET_SERVICE_HOST,
payload: host
};
}
\ No newline at end of file
... ...
'use strict';
import {Record, List, Map} from 'immutable';
let InitialState = Record({
platform: 'ios', // ios, android
channel: 1, // 1 - boy, 2 - girl, 3 - kid, 4 - lifestyle, 5 - yoho
host: 'http://api.yoho.cn',
serviceHost: 'http://service.yoho.cn',
});
export default InitialState;
... ...
'use strict';
import InitialState from './appInitialState';
const {
SET_PLATFORM,
SET_CHANNEL,
SET_HOST,
SET_SERVICE_HOST,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
export default function appReducer(state = initialState, action) {
if (!(state instanceof InitialState)) return initialState.merge(state);
switch (action.type) {
case SET_PLATFORM:
return state.set('platform', action.payload);
case SET_CHANNEL:
return state.set('channel', action.payload);
case SET_HOST:
return state.set('host', action.payload);
case SET_SERVICE_HOST:
return state.set('serviceHost', action.payload);
}
return state;
}
... ...
import {combineReducers} from 'redux';
import app from './app/appReducer';
import newArrival from './newArrival/newArrivalReducer';
const rootReducer = combineReducers({
app,
newArrival,
});
export default rootReducer;
... ...
'use strict';
import ReactNative from 'react-native';
import NewArrivalService from '../../services/NewArrivalService';
const {
SET_CHANNEL,
} = require('../../constants/actionTypes').default;
... ...
'use strict';
import {Record, List, Map} from 'immutable';
let InitialState = Record({
});
export default InitialState;
... ...
'use strict';
import InitialState from './newArrivalInitialState';
import Immutable, {Map} from 'immutable';
const {
SET_CHANNEL,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
export default function newArrivalReducer(state=initialState, action) {
switch(action.type) {
}
return state;
}
... ...
'use strict';
import Request from '../../common/services/Request';
export default class HomeService {
constructor (host) {
let baseURL = 'http://api.yoho.cn';
if(host){
baseURL = host;
}
this.api = new Request(baseURL);
}
}
... ...
/**
* # configureStore.js
*
* A Redux boilerplate setup
*
*/
'use strict';
/**
* ## Imports
*
* redux functions
*/
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import createLogger from 'redux-logger';
/**
* ## Reducer
* The reducer contains the 4 reducers from
* device, global, auth, profile
*/
import reducer from '../reducers';
const logger = createLogger({
predicate: (getState, action) => process.env.NODE_ENV === `development`
});
/**
* ## creatStoreWithMiddleware
* Like the name...
*/
const createStoreWithMiddleware = applyMiddleware(
thunk,
logger
)(createStore);
/**
* ## configureStore
* @param {Object} the state with for keys:
* device, global, auth, profile
*
*/
export default function configureStore(initialState) {
return createStoreWithMiddleware(reducer, initialState);
};
... ...
... ... @@ -94,19 +94,19 @@ export default function native(platform) {
}
let type = this.props.type;
if (type == 'list') {
if (type == 'detail') {
let id=this.props.id;
let udid=this.props.udid;
store.dispatch(setId(id));
return (
<Provider store={store}>
<PlustarContainer />
<DetailContainer />
</Provider>
);
} else {
let id=this.props.id;
let udid=this.props.udid;
store.dispatch(setId(id));
return (
<Provider store={store}>
<DetailContainer />
<PlustarContainer />
</Provider>
);
}
... ...
'use strict';
import React from 'react';
import ReactNative from 'react-native';
const {
View,
Image,
Text,
TouchableOpacity,
Dimensions,
StyleSheet,
} = ReactNative;
export default class GPTags extends React.Component {
constructor(props) {
super (props);
}
render() {
let {title, isLimit} = this.props;
let leftWidth = tagMaxWidth;
if (isLimit) {
leftWidth = tagMaxWidth - limitWidth - 2;
}
let textMaxWidth = leftWidth - iconWidth - 5 * 2;
return (
<View style={styles.container}>
<View style={[styles.leftContainer, {width: leftWidth}]}>
<Image
style={styles.icon}
source={require('../../images/tag/globalpurchase_fly_smallicon.png')}
/>
<Text numberOfLines={1} style={[styles.text, {maxWidth: textMaxWidth}]}>{title}</Text>
</View>
{isLimit ? <Image
style={styles.limit}
source={require('../../images/tag/gp_tip_xl_product.png')}
/> : null}
</View>
);
}
}
let {width, height} = Dimensions.get('window');
const DEVICE_WIDTH_RATIO = width / 320;
let tagMaxWidth = Math.ceil(137.5 * DEVICE_WIDTH_RATIO);
let tagHeight = Math.ceil(14 * DEVICE_WIDTH_RATIO);
let iconWidth = Math.ceil(10 * DEVICE_WIDTH_RATIO);
let limitWidth = Math.ceil(30 * DEVICE_WIDTH_RATIO);
let limitHeight = Math.ceil(14 * DEVICE_WIDTH_RATIO);
let styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
width: width,
height: tagHeight,
},
leftContainer: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#462e3d',
height: tagHeight,
},
icon: {
marginLeft: 5,
width: iconWidth,
height: iconWidth,
resizeMode: 'contain',
},
text: {
marginLeft: 5,
marginRight: 5,
color: 'white',
fontSize: 10,
fontFamily: 'STHeitiSC-Light',
},
limit: {
marginLeft: 2,
width: limitWidth,
height: limitHeight,
resizeMode: 'contain',
},
});
... ... @@ -13,7 +13,7 @@ import ReactNative, {
import SlicedImage from '../../../common/components/SlicedImage';
import LoadMoreIndicator from '../../../common/components/LoadMoreIndicator';
import ProductListCell from './ProductListCell';
import ProductListCell from '../../../common/components/ListCell/ProductListCell';
import ProductFilter from './ProductFilter';
import ProductShopCell from './ProductShopCell';
... ...
'use strict';
import React, {Component} from 'react';
import ReactNative, {
View,
Text,
Image,
ListView,
StyleSheet,
Dimensions,
TouchableOpacity,
} from 'react-native';
import SlicedImage from '../../../common/components/SlicedImage';
import Tags from './Tags';
import GPTags from './GPTags';
export default class Search extends Component {
constructor(props) {
super(props);
this._renderTags = this._renderTags.bind(this);
this._renderImages = this._renderImages.bind(this);
this._renderPrice = this._renderPrice.bind(this);
}
_renderTags() {
let {data, sourceType} = this.props;
let isGlobalProduct = data.get('is_global') && data.get('is_global') == 'Y'; // 是否全球购商品
let tags = data.get('tags'); // 商品标签
// 数据源是全球购
if (sourceType == 1) {
if (isGlobalProduct) {
} else {
tags = ['is_in_stock', ...tags];
}
}
let countryName = isGlobalProduct && data.get('country_name'); // 全球购国家名称
if (isGlobalProduct) {
return <GPTags title={countryName} limit={showGPLimitTag}/>;
} else {
return <Tags items={tags}/>;
}
}
_renderImages() {
let {data, sourceType} = this.props;
let url = data.get('default_images').replace('{width}', rowWidth).replace('{height}', imageHeight); // 商品缩略图
url = SlicedImage.getSlicedUrl(data.get('default_images'), 290, 386, 2);
let isGlobalProduct = data.get('is_global') && data.get('is_global') == 'Y'; // 是否全球购商品
let showGPLimitTag = isGlobalProduct && data.get('is_limited') && data.get('is_limited') == 'Y'; // 全球购限量商品
let showGPSoldOut = isGlobalProduct && data.get('is_stock') && data.get('is_stock') == 'Y'; // 全球购售罄
let showAlmostSoldOut = !isGlobalProduct && data.get('tags', []).indexOf('is_soon_sold_out') !== -1; // 非全球购的即将售罄
let showSoldOut = sourceType == 2 && data.get('storage_num') && data.get('storage_num') == 0; // 数据源是奥莱才显示
return (
<View style={styles.imageContainer}>
<Image style={styles.image} source={{uri: url}}>
{showAlmostSoldOut ? <Image style={styles.almostSoldOutImage} source={require('../../images/tag/tip_jjsq.png')}/> : null}
{showSoldOut ? <Image style={styles.soldOutImage} source={require('../../images/tag/outlet_sellout_bg.png')}/> : null}
{showGPSoldOut ? <Image style={styles.gpSoldOutImage} source={require('../../images/tag/gp_tip_SQ.png')}/> : null}
</Image>
</View>
);
}
_renderPrice() {
let {data, sourceType} = this.props;
let isGlobalProduct = data.get('is_global') && data.get('is_global') == 'Y'; // 是否全球购商品
let salePrice = 0; // 售卖价
let originPrice = 0; // 原价
let salePriceStr = ''; // 拼接的售卖价
let originPriceStr = ''; // 拼接的原价
let showOriginPrice = true; // 是否显示原价
let salePriceColor = '#d0021b'; // 不显示原价时,售卖价颜色
if (isGlobalProduct) {
salePrice = parseFloat(data.get('final_price'));
originPrice = parseFloat(data.get('orign_price'));
salePriceStr = data.get('formart_final_price');
originPriceStr = data.get('formart_orign_price');
} else {
salePrice = parseFloat(data.get('sales_price'));
originPrice = parseFloat(data.get('market_price'));
salePriceStr = '¥' + salePrice.toFixed(2);
originPriceStr = '¥' + originPrice.toFixed(2);
}
if (!originPrice || (salePrice == originPrice)) {
showOriginPrice = false;
salePriceColor = '#444444';
}
if (showOriginPrice) {
return (
<View style={styles.priceContainer}>
<Text style={[styles.nowPrice, {color: salePriceColor}]} numberOfLines={1}>{salePriceStr}</Text>
<View style={styles.oldPriceContainer}>
<Text style={styles.oldPrice} numberOfLines={1}>{originPriceStr}</Text>
<View style={styles.deleteLine}/>
</View>
</View>
);
} else {
return (
<View style={styles.priceContainer}>
<Text style={[styles.nowPrice, {color: salePriceColor}]} numberOfLines={1}>{salePriceStr}</Text>
</View>
);
}
}
render() {
let {data, sourceType, rowID, style} = this.props;
let name = data.get('product_name') ? data.get('product_name') : '';
return (
<TouchableOpacity
style={[styles.container, style]}
activeOpacity={1}
onPress={() => {
this.props.onPressProduct && this.props.onPressProduct(data, rowID);
}}
>
<View>
{this._renderTags()}
{this._renderImages()}
<View style={styles.nameContainer}>
<Text style={styles.name} numberOfLines={2}>{name}</Text>
</View>
{this._renderPrice()}
</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);
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(7 * DEVICE_WIDTH_RATIO);
let nameHeight = Math.ceil(36 * DEVICE_WIDTH_RATIO);
let gpSoldOutImageHeight = Math.ceil(25 * DEVICE_WIDTH_RATIO);
let styles = StyleSheet.create({
container: {
width: rowWidth,
height: rowHeight,
marginTop: rowMarginTop,
},
rowContainer: {
width: rowWidth,
height: rowHeight,
},
imageContainer: {
width: rowWidth,
height: imageHeight,
backgroundColor: '#f0f0f0',
},
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',
},
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 from 'react';
import ReactNative from 'react-native';
const {
View,
Image,
Text,
ListView,
Dimensions,
StyleSheet,
} = ReactNative;
export default class Tags extends React.Component {
constructor(props) {
super (props);
this.config = {
is_discount: {
image: require('../../images/tag/tip_sale.png'),
width: 30,
}, // YH_ProductTagTypeSale
resale: {
image: require('../../images/tag/tip_zdz.png'),
width: 45,
}, // YH_ProductTagTypeReSale
'mid-year': {
image: require('../../images/tag/tip_nzrc.png'),
width: 45,
}, // YH_ProductTagTypeSaleMiddle
'year-end': {
image: require('../../images/tag/tip_nzdc.png'),
width: 45,
}, // YH_ProductTagTypeSaleHot
is_new: {
image: require('../../images/tag/tip_new.png'),
width: 30,
}, // YH_ProductTagTypeNew
is_yohood: {
image: require('../../images/tag/tip_xpj.png'),
width: 45,
}, // YH_ProductTagTypeYohood
is_limited: {
image: require('../../images/tag/tip_xl_product.png'),
width: 30,
}, // YH_ProductTagTypeLimited
is_in_stock: {
image: require('../../images/tag/tip_gnzf.png'),
width: 45,
}, // YH_ProductTagTypeInland
is_deposit_advance: {
image: require('../../images/tag/tip_advance.png'),
width: 30,
}, // YH_ProductTagTypeDeposit
default: {
image: '',
width: 45,
},
};
this._renderRow = this._renderRow.bind(this);
this.dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 != r2,
});
}
_renderRow(rowData, sectionID, rowID) {
let item = this.config[rowData];
if (!item) {
return null;
}
let width = Math.ceil(item.width * DEVICE_WIDTH_RATIO);
let marginLeft = rowID == 0 ? 0 : 2;
let iconStyle = {width, height: tagHeight, marginLeft};
return (
<Image style={[styles.icon, iconStyle]} source={item.image}/>
);
}
render() {
let {style, items} = this.props;
// let tags = ['is_discount', 'resale', ];
return (
<View style={[styles.container]}>
<ListView
style={[styles.container]}
contentContainerStyle={[styles.contentContainer]}
enableEmptySections={true}
dataSource={this.dataSource.cloneWithRows(items.toArray())}
renderRow={this._renderRow}
scrollEnabled={false}
scrollsToTop={false}
horizontal={true}
showsHorizontalScrollIndicator={false}
/>
</View>
);
}
}
let {width, height} = Dimensions.get('window');
const DEVICE_WIDTH_RATIO = width / 320;
let tagHeight = Math.ceil(14 * DEVICE_WIDTH_RATIO);
let styles = StyleSheet.create({
container: {
},
contentContainer: {
height: tagHeight,
},
icon: {
resizeMode: 'contain',
},
});