Authored by 于良

品牌搜索 review by 孙凯

@@ -20,6 +20,7 @@ import YH_SearchBar from '../../../common/components/YH_SearchBar'; @@ -20,6 +20,7 @@ import YH_SearchBar from '../../../common/components/YH_SearchBar';
20 import ChannelFliter from './ChannelFliter'; 20 import ChannelFliter from './ChannelFliter';
21 import AllBrandListCell from './AllBrandListCell'; 21 import AllBrandListCell from './AllBrandListCell';
22 import NewHotBannerListCell from './NewHotBannerListCell'; 22 import NewHotBannerListCell from './NewHotBannerListCell';
  23 +import BrandSearch from './BrandSearch';
23 24
24 25
25 export default class Brand extends Component { 26 export default class Brand extends Component {
@@ -66,7 +67,14 @@ export default class Brand extends Component { @@ -66,7 +67,14 @@ export default class Brand extends Component {
66 67
67 return ( 68 return (
68 <View style={styles.header}> 69 <View style={styles.header}>
69 - <YH_SearchBar/> 70 + <TouchableOpacity
  71 + activeOpacity={1}
  72 + onPress={() => {
  73 + this.props.onPressSearch && this.props.onPressSearch();
  74 + }}
  75 + >
  76 + <YH_SearchBar editable={false} />
  77 + </TouchableOpacity>
70 {banner?<BrandSwiper resource={banner} onPressSlideItem={this.props.onPressSlideItem}/>:null} 78 {banner?<BrandSwiper resource={banner} onPressSlideItem={this.props.onPressSlideItem}/>:null}
71 {custom_brands?<BannerReourceList resource={custom_brands} onPressSlideItem={this.props.onPressSlideItem}/>:null} 79 {custom_brands?<BannerReourceList resource={custom_brands} onPressSlideItem={this.props.onPressSlideItem}/>:null}
72 {brandsText?<BrandFliter dataSource={brandsText} selectID={brandFliter} onPressFilter={this.props.onPressFilter}/>:null} 80 {brandsText?<BrandFliter dataSource={brandsText} selectID={brandFliter} onPressFilter={this.props.onPressFilter}/>:null}
@@ -97,6 +105,7 @@ export default class Brand extends Component { @@ -97,6 +105,7 @@ export default class Brand extends Component {
97 render() { 105 render() {
98 106
99 let { 107 let {
  108 + showSearch,
100 brandFliter, 109 brandFliter,
101 channelFliter, 110 channelFliter,
102 brandListForBoy, 111 brandListForBoy,
@@ -107,6 +116,7 @@ export default class Brand extends Component { @@ -107,6 +116,7 @@ export default class Brand extends Component {
107 reourceForGirl, 116 reourceForGirl,
108 reourceForKid, 117 reourceForKid,
109 reourceForLifeStyle, 118 reourceForLifeStyle,
  119 + search,
110 } = this.props; 120 } = this.props;
111 121
112 let data; 122 let data;
@@ -148,6 +158,7 @@ export default class Brand extends Component { @@ -148,6 +158,7 @@ export default class Brand extends Component {
148 return ( 158 return (
149 <View style={styles.container}> 159 <View style={styles.container}>
150 <ChannelFliter selectID={channelFliter} onChannelPressFliter={this.props.onChannelPressFliter}/> 160 <ChannelFliter selectID={channelFliter} onChannelPressFliter={this.props.onChannelPressFliter}/>
  161 +
151 <ListView 162 <ListView
152 contentContainerStyle={contentContainerStyle} 163 contentContainerStyle={contentContainerStyle}
153 enableEmptySections={true} 164 enableEmptySections={true}
@@ -156,6 +167,8 @@ export default class Brand extends Component { @@ -156,6 +167,8 @@ export default class Brand extends Component {
156 renderSectionHeader={renderSectionHeader} 167 renderSectionHeader={renderSectionHeader}
157 renderHeader={this.renderHeader} 168 renderHeader={this.renderHeader}
158 /> 169 />
  170 +
  171 + {showSearch ? <BrandSearch style={styles.search} data={search}/> : null}
159 </View> 172 </View>
160 ); 173 );
161 } 174 }
@@ -166,6 +179,7 @@ let {width, height} = Dimensions.get('window'); @@ -166,6 +179,7 @@ let {width, height} = Dimensions.get('window');
166 let styles = StyleSheet.create({ 179 let styles = StyleSheet.create({
167 container: { 180 container: {
168 flex: 1, 181 flex: 1,
  182 + backgroundColor: 'white',
169 }, 183 },
170 contentContainerOne:{ 184 contentContainerOne:{
171 185
@@ -191,4 +205,8 @@ let styles = StyleSheet.create({ @@ -191,4 +205,8 @@ let styles = StyleSheet.create({
191 width, 205 width,
192 backgroundColor: '#444', 206 backgroundColor: '#444',
193 }, 207 },
  208 + search: {
  209 +
  210 +
  211 + },
194 }); 212 });
  1 +'use strict';
  2 +
  3 +import React, {Component} from 'react';
  4 +import ReactNative, {
  5 + View,
  6 + Text,
  7 + Image,
  8 + ListView,
  9 + StyleSheet,
  10 + Dimensions,
  11 + TouchableOpacity,
  12 +} from 'react-native';
  13 +
  14 +import KeywordCell from './KeywordCell';
  15 +import YH_SearchBar from '../../../common/components/YH_SearchBar';
  16 +
  17 +export default class SearchKeyword extends Component {
  18 +
  19 + constructor(props) {
  20 + super(props);
  21 +
  22 + this._renderRow = this._renderRow.bind(this);
  23 + this._renderSeparator = this._renderSeparator.bind(this);
  24 +
  25 + this.dataSource = new ListView.DataSource({
  26 + rowHasChanged: (r1, r2) => !Immutable.is(r1, r2),
  27 + sectionHeaderHasChanged: (s1, s2) => !Immutable.is(s1, s2),
  28 + });
  29 + }
  30 +
  31 + componentDidMount() {
  32 + this.searchBar && this.searchBar.focus();
  33 + }
  34 +
  35 + _renderRow(rowData, sectionID, rowID) {
  36 + if (rowData.size == 0) {
  37 + return null;
  38 + }
  39 +
  40 + let icon = rowID == 0 ? require('../../images/shijian.png') : require('../../images/huo.png');
  41 + let title = rowID == 0 ? '最近搜索' : '热门搜索';
  42 + let onPressAction = rowID == 0 ? this.props.onPressClearHistory : null;
  43 + return (
  44 + <KeywordCell
  45 + key={'row' + rowID}
  46 + icon={icon}
  47 + title={title}
  48 + list={rowData}
  49 + onPressAction={onPressAction}
  50 + onPressKeyword={this.props.onPressKeyword}
  51 + />
  52 + );
  53 + }
  54 +
  55 + _renderSeparator(sectionID, rowID, adjacentRowHighlighted) {
  56 + if (rowID == 0 && this.props.data.history.size > 0) {
  57 + return (
  58 + <View key={'sep' + rowID} style={styles.separator}>
  59 + <View style={styles.line}/>
  60 + </View>
  61 + );
  62 + }
  63 +
  64 + return null;
  65 + }
  66 +
  67 + render() {
  68 + let {history, hot, style} = this.props.data;
  69 + let list = [history, hot];
  70 +
  71 + return (
  72 + <View style={[styles.container, style]}>
  73 + <YH_SearchBar
  74 + ref={(c) => {
  75 + this.searchBar = c;
  76 + }}
  77 + />
  78 + <ListView
  79 + contentContainerStyle={styles.contentContainer}
  80 + enableEmptySections={true}
  81 + dataSource={this.dataSource.cloneWithRows(list)}
  82 + renderRow={this._renderRow}
  83 + renderSeparator={this._renderSeparator}
  84 + keyboardDismissMode={'on-drag'}
  85 + />
  86 +
  87 + </View>
  88 + );
  89 + }
  90 +}
  91 +
  92 +let {width, height} = Dimensions.get('window');
  93 +
  94 +
  95 +let styles = StyleSheet.create({
  96 + container: {
  97 + flex: 1,
  98 + position: 'absolute',
  99 + top: 0,
  100 + left: 0,
  101 + width,
  102 + height,
  103 + backgroundColor: 'white',
  104 + },
  105 + contentContainer: {
  106 +
  107 + },
  108 + separator: {
  109 + height: 15,
  110 + },
  111 + line: {
  112 + marginHorizontal: 30,
  113 + top: 10 ,
  114 + height: 1,
  115 + backgroundColor: '#e5e5e5',
  116 + },
  117 +});
  1 +'use strict';
  2 +
  3 +import React from 'react';
  4 +import ReactNative from 'react-native';
  5 +
  6 +const {
  7 + View,
  8 + Image,
  9 + Text,
  10 + ScrollView,
  11 + TouchableOpacity,
  12 + Dimensions,
  13 + StyleSheet,
  14 +} = ReactNative;
  15 +
  16 +import KeywordHeader from './KeywordHeader';
  17 +import KeywordText from './KeywordText';
  18 +
  19 +export default class KeywordCell extends React.Component {
  20 +
  21 + constructor(props) {
  22 + super (props);
  23 +
  24 + }
  25 +
  26 + render() {
  27 +
  28 + let {icon, title, list, onPressAction, onPressKeyword} = this.props;
  29 +
  30 + return (
  31 + <View style={styles.container}>
  32 + <KeywordHeader
  33 + icon={icon}
  34 + title={title}
  35 + onPressAction={onPressAction}
  36 + />
  37 + <View style={styles.textContainer}>
  38 + {list.toJS().map((item, i) => {
  39 + return <KeywordText key={i} keyword={item.keyword} onPressKeyword={onPressKeyword}/>;
  40 + })}
  41 + </View>
  42 +
  43 + </View>
  44 + );
  45 + }
  46 +}
  47 +
  48 +let styles = StyleSheet.create({
  49 + container: {
  50 +
  51 + },
  52 + textContainer: {
  53 + marginHorizontal: 26,
  54 + flexDirection: 'row',
  55 + flexWrap: 'wrap',
  56 + },
  57 +});
  1 +'use strict';
  2 +
  3 +import React from 'react';
  4 +import ReactNative from 'react-native';
  5 +
  6 +const {
  7 + View,
  8 + Image,
  9 + Text,
  10 + TouchableOpacity,
  11 + Dimensions,
  12 + StyleSheet,
  13 +} = ReactNative;
  14 +
  15 +export default class KeywordHeader extends React.Component {
  16 +
  17 + constructor(props) {
  18 + super (props);
  19 +
  20 + }
  21 +
  22 + renderAction() {
  23 + if (this.props.onPressAction) {
  24 + return (
  25 + <TouchableOpacity style={styles.action} onPress={() => {
  26 + this.props.onPressAction && this.props.onPressAction();
  27 + }}>
  28 + <Image
  29 + style={styles.delete}
  30 + source={require('../../images/shanchu.png')}
  31 + resizeMode={'contain'}
  32 + />
  33 + </TouchableOpacity>
  34 + );
  35 + }
  36 +
  37 + return null;
  38 + }
  39 +
  40 + render() {
  41 + let {icon, title, onPressAction} = this.props;
  42 + return (
  43 + <View style={styles.container}>
  44 + <Image
  45 + style={styles.icon}
  46 + source={icon}
  47 + resizeMode={'contain'}
  48 + />
  49 + <Text style={styles.text}>{title}</Text>
  50 +
  51 + {this.renderAction()}
  52 + </View>
  53 + );
  54 + }
  55 +}
  56 +
  57 +let styles = StyleSheet.create({
  58 + container: {
  59 + flexDirection: 'row',
  60 + alignItems: 'center',
  61 + width: Dimensions.get('window').width,
  62 + height: 40,
  63 + },
  64 + icon: {
  65 + marginLeft: 15,
  66 + width: 13,
  67 + height: 17,
  68 + },
  69 + text: {
  70 + marginLeft: 10,
  71 + color: '#b0b0b0',
  72 + fontSize: 12,
  73 + },
  74 + action: {
  75 + position: 'absolute',
  76 + right: 10,
  77 + height: 40,
  78 + },
  79 + delete: {
  80 + width: 28,
  81 + height: 28,
  82 + top: 6,
  83 + },
  84 +});
  1 +'use strict';
  2 +
  3 +import React from 'react';
  4 +import ReactNative from 'react-native';
  5 +
  6 +const {
  7 + View,
  8 + Image,
  9 + Text,
  10 + TouchableHighlight,
  11 + Dimensions,
  12 + StyleSheet,
  13 +} = ReactNative;
  14 +
  15 +export default class KeywordText extends React.Component {
  16 +
  17 + constructor(props) {
  18 + super (props);
  19 +
  20 + this.state = {
  21 + helight: false,
  22 + }
  23 + }
  24 +
  25 + render() {
  26 + let {keyword, onPressKeyword} = this.props;
  27 + let textColor = this.state.helight ? {color: 'rgb(66, 66, 66)'} : {color: 'rgb(191, 191, 191)'};
  28 + return (
  29 + <TouchableHighlight
  30 + style={styles.container}
  31 + underlayColor={'rgb(255, 255, 255)'}
  32 + onPress={() => {
  33 + onPressKeyword && onPressKeyword(keyword);
  34 + }}
  35 + onPressIn={() => {
  36 + this.setState({
  37 + helight: !this.state.helight,
  38 + });
  39 + }}
  40 + onPressOut={() => {
  41 + this.setState({
  42 + helight: !this.state.helight,
  43 + });
  44 + }}
  45 + >
  46 + <Text style={[styles.text, textColor]}>{keyword}</Text>
  47 + </TouchableHighlight>
  48 + );
  49 + }
  50 +}
  51 +
  52 +let styles = StyleSheet.create({
  53 + container: {
  54 + flexDirection: 'row',
  55 + alignItems: 'center',
  56 + alignSelf: 'flex-start',
  57 + height: 25,
  58 + backgroundColor: 'rgb(255, 255, 255)',
  59 + borderColor: 'rgb(191, 191, 191)',
  60 + borderRadius: 3,
  61 + borderWidth: 1,
  62 + margin: 4,
  63 + },
  64 + text: {
  65 + marginHorizontal: 10,
  66 + marginVertical: 6,
  67 + fontSize: 13,
  68 + },
  69 +});
@@ -23,10 +23,6 @@ export default keyMirror({ @@ -23,10 +23,6 @@ export default keyMirror({
23 23
24 LOAD_CACHED_INTEREST_LIST: null, 24 LOAD_CACHED_INTEREST_LIST: null,
25 25
26 - GET_COUPON_REQUEST: null,  
27 - GET_COUPON_SUCCESS: null,  
28 - GET_COUPON_FAILURE: null,  
29 -  
30 GET_BRAND_LIST_FOR_BOY_REQUEST: null, 26 GET_BRAND_LIST_FOR_BOY_REQUEST: null,
31 GET_BRAND_LIST_FOR_BOY_SUCCESS: null, 27 GET_BRAND_LIST_FOR_BOY_SUCCESS: null,
32 GET_BRAND_LIST_FOR_BOY_FAILURE: null, 28 GET_BRAND_LIST_FOR_BOY_FAILURE: null,
@@ -62,9 +58,14 @@ export default keyMirror({ @@ -62,9 +58,14 @@ export default keyMirror({
62 SET_BRAND_FILTER: null, 58 SET_BRAND_FILTER: null,
63 SET_CHANNEL_FILTER: null, 59 SET_CHANNEL_FILTER: null,
64 60
65 - JUMP_WITH_URL: null, 61 + BRAND_SHOW_SEARCH: null,
  62 + FETCH_BRAND_SEARCH_HISTORY: null,
  63 + INSERT_BRAND_SEARCH_HISTORY: null,
  64 + CLEAR_BRAND_SEARCH_HISTORY: null,
  65 + BRAND_HOT_KEYWORD_REQUEST: null,
  66 + BRAND_HOT_KEYWORD_SUCCESS: null,
  67 + BRAND_HOT_KEYWORD_FAILURE: null,
66 68
67 - HIDE_SUCCESS_PROMPT: null,  
68 - HIDE_NET_ERROR_PROMPT: null, 69 + JUMP_WITH_URL: null,
69 70
70 }); 71 });
@@ -50,23 +50,27 @@ class BrandContainer extends Component { @@ -50,23 +50,27 @@ class BrandContainer extends Component {
50 this._onPressSlideItem = this._onPressSlideItem.bind(this); 50 this._onPressSlideItem = this._onPressSlideItem.bind(this);
51 this._onPressFilter = this._onPressFilter.bind(this); 51 this._onPressFilter = this._onPressFilter.bind(this);
52 this._onChannelPressFliter = this._onChannelPressFliter.bind(this); 52 this._onChannelPressFliter = this._onChannelPressFliter.bind(this);
  53 + this._onPressSearch = this._onPressSearch.bind(this);
  54 + this._onPressClearHistory = this._onPressClearHistory.bind(this);
53 55
54 } 56 }
55 57
56 componentDidMount() { 58 componentDidMount() {
57 this.props.actions.getBrandList(0); 59 this.props.actions.getBrandList(0);
58 this.props.actions.getBrandResource(0); 60 this.props.actions.getBrandResource(0);
  61 + this.props.actions.searchHistory();
  62 + this.props.actions.hotKeyword();
59 } 63 }
60 64
61 componentWillUnmount() { 65 componentWillUnmount() {
62 66
63 } 67 }
64 68
65 - _onPressSlideItem(url){ 69 + _onPressSlideItem(url) {
66 console.log('aaa'); 70 console.log('aaa');
67 } 71 }
68 72
69 - _onPressFilter(value){ 73 + _onPressFilter(value) {
70 this.props.actions.setBrandFilter(value); 74 this.props.actions.setBrandFilter(value);
71 } 75 }
72 76
@@ -107,8 +111,17 @@ class BrandContainer extends Component { @@ -107,8 +111,17 @@ class BrandContainer extends Component {
107 this.props.actions.setChannelFilter(value); 111 this.props.actions.setChannelFilter(value);
108 } 112 }
109 113
  114 + _onPressSearch() {
  115 + this.props.actions.setShowSearch(!this.props.brand.showSearch);
  116 + }
  117 +
  118 + _onPressClearHistory() {
  119 + this.props.actions.clearSearchHistory();
  120 + }
  121 +
110 render() { 122 render() {
111 let { 123 let {
  124 + showSearch,
112 channelFliter, 125 channelFliter,
113 brandFliter, 126 brandFliter,
114 brandListForBoy, 127 brandListForBoy,
@@ -119,8 +132,9 @@ class BrandContainer extends Component { @@ -119,8 +132,9 @@ class BrandContainer extends Component {
119 reourceForGirl, 132 reourceForGirl,
120 reourceForKid, 133 reourceForKid,
121 reourceForLifeStyle, 134 reourceForLifeStyle,
  135 + search,
122 } = this.props.brand; 136 } = this.props.brand;
123 - console.log(this.props.brand); 137 +
124 return ( 138 return (
125 <View style={styles.container}> 139 <View style={styles.container}>
126 <Brand 140 <Brand
@@ -137,6 +151,10 @@ class BrandContainer extends Component { @@ -137,6 +151,10 @@ class BrandContainer extends Component {
137 onPressFilter= {this._onPressFilter} 151 onPressFilter= {this._onPressFilter}
138 onPressSlideItem= {this._onPressSlideItem} 152 onPressSlideItem= {this._onPressSlideItem}
139 onChannelPressFliter={this._onChannelPressFliter} 153 onChannelPressFliter={this._onChannelPressFliter}
  154 + showSearch={showSearch}
  155 + search={search}
  156 + onPressSearch={this._onPressSearch}
  157 + onPressClearHistory={this._onPressClearHistory}
140 /> 158 />
141 </View> 159 </View>
142 ); 160 );
@@ -41,6 +41,13 @@ const { @@ -41,6 +41,13 @@ const {
41 GET_BRAND_RESOURCE_FOR_LIFESTYLE_SUCCESS, 41 GET_BRAND_RESOURCE_FOR_LIFESTYLE_SUCCESS,
42 GET_BRAND_RESOURCE_FOR_LIFESTYLE_FAILURE, 42 GET_BRAND_RESOURCE_FOR_LIFESTYLE_FAILURE,
43 43
  44 + BRAND_SHOW_SEARCH,
  45 + FETCH_BRAND_SEARCH_HISTORY,
  46 + INSERT_BRAND_SEARCH_HISTORY,
  47 + CLEAR_BRAND_SEARCH_HISTORY,
  48 + BRAND_HOT_KEYWORD_REQUEST,
  49 + BRAND_HOT_KEYWORD_SUCCESS,
  50 + BRAND_HOT_KEYWORD_FAILURE,
44 51
45 } = require('../../constants/actionTypes').default; 52 } = require('../../constants/actionTypes').default;
46 53
@@ -59,6 +66,13 @@ export function setChannelFilter(filter) { @@ -59,6 +66,13 @@ export function setChannelFilter(filter) {
59 }; 66 };
60 } 67 }
61 68
  69 +export function setShowSearch(show) {
  70 + return {
  71 + type: BRAND_SHOW_SEARCH,
  72 + payload: show
  73 + };
  74 +}
  75 +
62 export function getBrandListForBoyRequest() { 76 export function getBrandListForBoyRequest() {
63 return { 77 return {
64 type: GET_BRAND_LIST_FOR_BOY_REQUEST, 78 type: GET_BRAND_LIST_FOR_BOY_REQUEST,
@@ -331,3 +345,130 @@ export function parseResourceResources(json) { @@ -331,3 +345,130 @@ export function parseResourceResources(json) {
331 brandsText, 345 brandsText,
332 }; 346 };
333 } 347 }
  348 +
  349 +
  350 +export function searchHistory() {
  351 + return (dispatch, getState) => {
  352 + ReactNative.NativeModules.YH_ClassifyHelper.fetchSearchHistory()
  353 + .then(data => {
  354 + dispatch({
  355 + type: FETCH_BRAND_SEARCH_HISTORY,
  356 + payload: parseSearchHistory(data)
  357 + });
  358 + })
  359 + .catch(error => {
  360 +
  361 + });
  362 + };
  363 +}
  364 +
  365 +export function insertSearchHistory(keyword) {
  366 + return (dispatch, getState) => {
  367 + ReactNative.NativeModules.YH_ClassifyHelper.insertSearchHistory(keyword)
  368 + .then(data => {
  369 + dispatch({
  370 + type: INSERT_BRAND_SEARCH_HISTORY,
  371 + payload: parseSearchHistory(data)
  372 + });
  373 + })
  374 + .catch(error => {
  375 +
  376 + });
  377 + };
  378 +}
  379 +
  380 +export function clearSearchHistory() {
  381 + return (dispatch, getState) => {
  382 + ReactNative.NativeModules.YH_ClassifyHelper.clearSearchHistory()
  383 + .then(data => {
  384 + dispatch({
  385 + type: CLEAR_BRAND_SEARCH_HISTORY,
  386 + payload: parseSearchHistory(data)
  387 + });
  388 + })
  389 + .catch(error => {
  390 +
  391 + });
  392 + };
  393 +}
  394 +
  395 +function parseSearchHistory(data) {
  396 + let list = [];
  397 + data.map((item, i) => {
  398 + list.push({keyword: item});
  399 + });
  400 +
  401 + return list;
  402 +}
  403 +
  404 +export function hotKeywordRequest() {
  405 + return {
  406 + type: BRAND_HOT_KEYWORD_REQUEST,
  407 + };
  408 +}
  409 +
  410 +export function hotKeywordSuccess(json) {
  411 + return {
  412 + type: BRAND_HOT_KEYWORD_SUCCESS,
  413 + payload: json
  414 + };
  415 +}
  416 +
  417 +export function hotKeywordFailure(error) {
  418 + return {
  419 + type: BRAND_HOT_KEYWORD_FAILURE,
  420 + payload: error
  421 + };
  422 +}
  423 +
  424 +
  425 +export function hotKeyword(reload=false) {
  426 + return (dispatch, getState) => {
  427 + let {app, brand} = getState();
  428 + let {search} = brand;
  429 + let {isFetching} = search;
  430 + if (reload) {
  431 + // 强制刷新数据
  432 +
  433 + } else {
  434 + if (isFetching) {
  435 + return;
  436 + }
  437 + }
  438 +
  439 + let fetchHotKeyword = (uid) => {
  440 + dispatch(hotKeywordRequest());
  441 + return new BrandService(app.host).fetchHotKeyword(uid)
  442 + .then(json => {
  443 + let payload = parseHotKeyword(json);
  444 + dispatch(hotKeywordSuccess(payload));
  445 + })
  446 + .catch(error => {
  447 + dispatch(hotKeywordFailure(error));
  448 + });
  449 + }
  450 +
  451 + ReactNative.NativeModules.YH_CommonHelper.uid()
  452 + .then(uid => {
  453 + fetchHotKeyword(uid);
  454 + })
  455 + .catch(error => {
  456 + fetchHotKeyword(0);
  457 + });
  458 + };
  459 +}
  460 +
  461 +function parseHotKeyword(json) {
  462 + let list = [];
  463 + Array.isArray(json) && json.map((item, i) => {
  464 + let brandName = item.brandName ? item.brandName : '';
  465 + let keyword = brandName;
  466 + let brandDomain = item.brandDomain ? item.brandDomain : '';
  467 + let brandId = item.brandId ? item.brandId : '';
  468 + list.push({keyword, brandName, brandDomain, brandId});
  469 + });
  470 +
  471 + return {
  472 + list,
  473 + };
  474 +}
@@ -53,6 +53,13 @@ let InitialState = Record({ @@ -53,6 +53,13 @@ let InitialState = Record({
53 brandsText: List(), 53 brandsText: List(),
54 hasSuccess: false, 54 hasSuccess: false,
55 })), 55 })),
  56 + showSearch: false,
  57 + search: new (Record({
  58 + history: List(),
  59 + isFetching: false,
  60 + error: null,
  61 + hot: List(),
  62 + })),
56 }); 63 });
57 64
58 export default InitialState; 65 export default InitialState;
@@ -41,24 +41,33 @@ const { @@ -41,24 +41,33 @@ const {
41 GET_BRAND_RESOURCE_FOR_LIFESTYLE_SUCCESS, 41 GET_BRAND_RESOURCE_FOR_LIFESTYLE_SUCCESS,
42 GET_BRAND_RESOURCE_FOR_LIFESTYLE_FAILURE, 42 GET_BRAND_RESOURCE_FOR_LIFESTYLE_FAILURE,
43 43
  44 + BRAND_SHOW_SEARCH,
  45 + FETCH_BRAND_SEARCH_HISTORY,
  46 + INSERT_BRAND_SEARCH_HISTORY,
  47 + CLEAR_BRAND_SEARCH_HISTORY,
  48 + BRAND_HOT_KEYWORD_REQUEST,
  49 + BRAND_HOT_KEYWORD_SUCCESS,
  50 + BRAND_HOT_KEYWORD_FAILURE,
  51 +
44 } = require('../../constants/actionTypes').default; 52 } = require('../../constants/actionTypes').default;
45 53
46 const initialState = new InitialState; 54 const initialState = new InitialState;
47 55
48 export default function brandReducer(state=initialState, action) { 56 export default function brandReducer(state=initialState, action) {
49 switch(action.type) { 57 switch(action.type) {
50 - case SET_TYPE: {  
51 - return state.set('type', action.payload);  
52 - }  
53 58
54 - case SET_BRAND_FILTER:{ 59 + case SET_BRAND_FILTER: {
55 return state.set('brandFliter', action.payload); 60 return state.set('brandFliter', action.payload);
56 } 61 }
57 62
58 - case SET_CHANNEL_FILTER:{ 63 + case SET_CHANNEL_FILTER: {
59 return state.set('channelFliter', action.payload); 64 return state.set('channelFliter', action.payload);
60 } 65 }
61 66
  67 + case BRAND_SHOW_SEARCH: {
  68 + return state.set('showSearch', action.payload);
  69 + }
  70 +
62 case GET_BRAND_LIST_FOR_BOY_REQUEST: 71 case GET_BRAND_LIST_FOR_BOY_REQUEST:
63 { 72 {
64 return state; 73 return state;
@@ -232,6 +241,28 @@ export default function brandReducer(state=initialState, action) { @@ -232,6 +241,28 @@ export default function brandReducer(state=initialState, action) {
232 return state.setIn(['reourceForLifeStyle', 'hasSuccess'], false); 241 return state.setIn(['reourceForLifeStyle', 'hasSuccess'], false);
233 } 242 }
234 243
  244 + case FETCH_BRAND_SEARCH_HISTORY:
  245 + case INSERT_BRAND_SEARCH_HISTORY:
  246 + case CLEAR_BRAND_SEARCH_HISTORY: {
  247 + return state.setIn(['search', 'history'], Immutable.fromJS(action.payload));
  248 + }
  249 +
  250 + case BRAND_HOT_KEYWORD_REQUEST: {
  251 + return state.setIn(['search', 'isFetching'], true)
  252 + .setIn(['search', 'error'], null);
  253 + }
  254 +
  255 + case BRAND_HOT_KEYWORD_SUCCESS: {
  256 + let {list} = action.payload;
  257 + return state.setIn(['search', 'isFetching'], false)
  258 + .setIn(['search', 'error'], null)
  259 + .setIn(['search', 'hot'], Immutable.fromJS(list));
  260 + }
  261 +
  262 + case BRAND_HOT_KEYWORD_FAILURE: {
  263 + return state.setIn(['search', 'isFetching'], false)
  264 + .setIn(['search', 'error'], action.payload);
  265 + }
235 } 266 }
236 267
237 return state; 268 return state;
@@ -45,4 +45,20 @@ export default class BrandService { @@ -45,4 +45,20 @@ export default class BrandService {
45 }); 45 });
46 } 46 }
47 47
  48 + async fetchHotKeyword(uid, sourcePage='iFP_SearchProList') {
  49 + return await this.api.get({
  50 + url: '',
  51 + body: {
  52 + method: 'app.search.hotBrands',
  53 + uid,
  54 + sourcePage,
  55 + }
  56 + })
  57 + .then((json) => {
  58 + return json;
  59 + })
  60 + .catch((error) => {
  61 + throw(error);
  62 + });
  63 + }
48 } 64 }