Authored by yoho-js001

React native good goods recomment kick start.

... ... @@ -19,6 +19,7 @@ import Installment from './installment/Installment';
import Home from './home/Home';
import Outlet from './outlet/Outlet'
import BLK from './blk/BLK'
import GoodGoodsRecommend from './goodGoodsRecommend/GoodGoodsRecommend'
export default function native(platform) {
Coupon(platform);
... ... @@ -35,6 +36,7 @@ export default function native(platform) {
Outlet(platform);
BLK(platform)
Mine(platform);
GoodGoodsRecommend(platform);
if (Platform.OS === 'ios') {
Community(platform);
... ...
'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 listInitialState from './reducers/list/listInitialState';
import detailInitialState from './reducers/detail/detailInitialState';
import ListContainer from './containers/ListContainer';
import DetailContainer from './containers/DetailContainer';
import {
setPlatform,
setHost,
setServiceHost,
} from './reducers/app/appActions';
import {
setProductSKN,
} from './reducers/detail/detailActions';
function getInitialState() {
const _initState = {
app: (new appInitialState()),
list: (new listInitialState()),
detail: (new detailInitialState()),
};
return _initState;
}
export default function native(platform) {
let YH_GoodGoodsRecommend = React.createClass({
render() {
const store = configureStore(getInitialState());
store.dispatch(setPlatform(platform));
store.dispatch(setHost(this.props.host));
store.dispatch(setServiceHost(this.props.serviceHost));
let type = this.props.type;
if (type == 'list') {
return (
<Provider store={store}>
<ListContainer />
</Provider>
);
} else {
store.dispatch(setProductSKN(this.props.product_skn));
return (
<Provider store={store}>
<DetailContainer />
</Provider>
);
}
}
});
AppRegistry.registerComponent('YH_GoodGoodsRecommend', () => YH_GoodGoodsRecommend);
}
... ...
'use strict';
import React, {Component} from 'react';
import Immutable, {Map} from 'immutable';
import LoadingIndicator from '../../../common/components/LoadingIndicator';
import ReactNative, {
View,
Text,
Image,
ListView,
StyleSheet,
Dimensions,
TouchableOpacity,
InteractionManager,
Platform,
} from 'react-native';
export default class Detail extends Component {
constructor(props) {
super(props);
this.renderRow = this.renderRow.bind(this);
this.dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => !Immutable.is(r1, r2),
sectionHeaderHasChanged: (s1, s2) => !Immutable.is(s1, s2),
});
}
shouldComponentUpdate(nextProps){
if (Immutable.is(nextProps.resource, this.props.resource)) {
return false;
} else {
return true;
}
}
renderRow(rowData,sectionID,rowID,highlightRow) {
return null;
}
render() {
let isFetching = true;
let dataSource = {};
return (
<View style={styles.container}>
{!isFetching?<ListView
contentContainerStyle={styles.contentContainer}
enableEmptySections={true}
showsVerticalScrollIndicator={false}
dataSource={this.dataSource.cloneWithRowsAndSections(dataSource)}
renderRow={this.renderRow}
/>:<LoadingIndicator
isVisible={isFetching}
/>}
</View>
);
}
}
let {width, height} = Dimensions.get('window');
let styles = StyleSheet.create({
container: {
flex: 1,
width: width,
height: height - 64,
},
contentContainer:{
backgroundColor: 'white',
},
GoodsGroupHeader: {
flex: 1,
},
});
... ...
import keyMirror from 'key-mirror';
export default keyMirror({
SET_PLATFORM: null,
SET_HOST: null,
SET_SERVICE_HOST: null,
SET_CHANNEL: null,
SET_PRODUCT_SKN: 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 detailActions from '../reducers/detail/detailActions';
import Detail from '../components/detail/Detail';
import {urlAddParamOfType} from '../../common/utils/urlHandler';
const actions = [
detailActions,
];
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 DetailContainer extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
}
componentWillUnmount() {
}
_onPressProduct(product) {
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);
}
render() {
return (
<View style={styles.container}>
<Detail
/>
</View>
);
}
}
let styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default connect(mapStateToProps, mapDispatchToProps)(DetailContainer);
... ...
'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;
}
... ...
'use strict';
import ReactNative from 'react-native';
import DetailService from '../../services/DetailService';
import helper from '../../../common/utils/helper';
const {
SET_PRODUCT_SKN,
} = require('../../constants/actionTypes').default;
export function setProductSKN(product_skn) {
return {
type: SET_PRODUCT_SKN,
payload: product_skn,
};
}
... ...
'use strict';
import {Record, List, Map} from 'immutable';
let InitialState = Record({
product_skn: '',
article: new (Record({
isFetching: false,
error: null,
data: null,
})),
author: new (Record({
isFetching: false,
error: null,
data: null,
})),
content: new (Record({
isFetching: false,
error: null,
data: List(),
})),
brand: new (Record({
isFetching: false,
error: null,
data: List(),
})),
otherArticle: new (Record({
isFetching: false,
error: null,
data: List(),
})),
weixin: new (Record({
isFetching: false,
error: null,
data: List(),
})),
goods_group_Filter: 0,
goods_group_y: 0,
});
export default InitialState;
... ...
'use strict';
import InitialState from './detailInitialState';
import Immutable, {Map} from 'immutable';
const {
SET_PRODUCT_SKN,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
export default function detailReducer(state=initialState, action) {
switch(action.type) {
case SET_PRODUCT_SKN: {
return state.set('product_skn', action.payload);
}
}
return state;
}
... ...
import {combineReducers} from 'redux';
import app from './app/appReducer';
import list from './list/listReducer';
import detail from './detail/detailReducer';
const rootReducer = combineReducers({
app,
list,
detail,
});
export default rootReducer;
... ...
'use strict';
import {Record, List, Map} from 'immutable';
let InitialState = Record({
});
export default InitialState;
... ...
'use strict';
import InitialState from './listInitialState';
import Immutable, {Map} from 'immutable';
const {
SET_PRODUCT_SKN,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
export default function detailReducer(state=initialState, action) {
switch(action.type) {
}
return state;
}
... ...
'use strict';
import Request from '../../common/services/NativeRequest';
export default class DetailService {
constructor (host) {
let baseURL = 'http://service.yoho.cn';
if(host){
baseURL = host;
}
this.api = new Request(baseURL);
}
// 获取资讯
async getArticle(article_id) {
return await this.api.get({
url: '/guang/service/v2/article/getArticle',
body: {
article_id,
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
// 获取作者信息
async getAuthor(author_id) {
return await this.api.get({
url: '/guang/service/v1/author/getAuthor',
body: {
author_id,
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
// 获取资讯内容
async getArticleContent(article_id) {
return await this.api.get({
url: '/guang/service/v2/article/getArticleContent',
body: {
article_id,
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
// 获取资讯相关的品牌
async getBrand(article_id) {
return await this.api.get({
url: '/guang/service/v2/article/getBrand',
body: {
article_id,
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
// 获取资讯相关的其它资讯
async getOtherArticle(article_id, tags, offset=0, limit=3) {
return await this.api.get({
url: '/guang/service/v2/article/getOtherArticle',
body: {
article_id,
tags,
offset,
limit,
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
async getWeixinPublic() {
return await this.api.get({
url: '',
body: {
method: 'app.resources.getSingleTemplate',
module: 'wechat',
key: 'guang_detail_wechat'
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
async productInfoBySkns(skns) {
return await this.api.get({
url: '',
body: {
method: 'app.search.li',
query: skns.join(' '),
limit: skns.length,
order: 's_t_desc',
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
}
... ...
/**
* # 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);
};
... ...