Search.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /**
  2. * 搜索页
  3. * @邠心vbe on 2021/04/12
  4. */
  5. import React, { Component } from 'react';
  6. import { View, Text, StyleSheet, TextInput, FlatList, Pressable, Linking, Image } from 'react-native';
  7. import apiStation from '../../api/apiStation';
  8. import TextRadius from '../../components/TextRadius';
  9. import utils from '../../utils/utils';
  10. import Provider from '../charge/Provider';
  11. import { PageList } from '../Router';
  12. export default class Search extends Component {
  13. constructor(props) {
  14. super(props);
  15. this.state = {
  16. isSearch: false,
  17. searchResult: [{id:0}]
  18. };
  19. }
  20. componentDidMount() {
  21. this.getGeoLocation();
  22. }
  23. getGeoLocation() {
  24. navigator.geolocation.getCurrentPosition(location => {
  25. let latlng = {
  26. lat: location.coords.latitude,
  27. lng: location.coords.longitude
  28. }
  29. this.searchStation(latlng);
  30. }, error => {
  31. console.warn("getGeoLocation", error);
  32. });
  33. }
  34. searchStation(latlng) {
  35. this.setState({
  36. isSearch: true
  37. });
  38. latlng.siteName = this.searchWorld
  39. apiStation.searchStation(latlng).then(res => {
  40. if (res.data.sites) {
  41. const list = [];
  42. res.data.sites.forEach(item => {
  43. list.push({
  44. id: item.sitePk,
  45. name: item.siteName,
  46. address: item.siteAddress,
  47. latitude: item.locationLatitude,
  48. longitude: item.locationLongitude,
  49. acConnector: item.acConnector,
  50. allConnector: item.allConnector,
  51. dcConnector: item.dcConnector,
  52. siteType: item.siteType,
  53. distance: utils.getDistance(item.distance),
  54. serviceProvider: item.serviceProvider
  55. });
  56. });
  57. this.setState({
  58. isSearch: false,
  59. searchResult: list
  60. });
  61. }
  62. }).catch(err => {
  63. console.log('err', err);
  64. this.setState({
  65. isSearch: false,
  66. searchResult: []
  67. });
  68. });
  69. }
  70. intoStation(info) {
  71. startPage(PageList.chargeDetail, {stationInfo: info, action: 'search'});
  72. }
  73. listItem = ({item, index, separators}) => {
  74. if (item.id) {
  75. return (
  76. <View
  77. style={styles.itemView}
  78. key={index}>
  79. <Pressable
  80. style={styles.stationInfo}
  81. onPress={() => this.intoStation(item)}>
  82. <View style={styles.nameView}>
  83. <Text style={styles.stationName}>{item.name}</Text>
  84. { item.allConnector && item.allConnector.available > 0 &&
  85. <TextRadius style={[styles.infoStatus, styles.available]}>Available</TextRadius>
  86. }
  87. </View>
  88. <Provider providers={item.serviceProvider}/>
  89. <Text style={styles.stationAddress}>{item.address}</Text>
  90. <View style={styles.connectView}>
  91. <ConnectType {...item.acConnector}/>
  92. <ConnectType {...item.dcConnector}/>
  93. </View>
  94. </Pressable>
  95. <Pressable
  96. style={styles.directView}
  97. onPress={() => {
  98. utils.directMaps(item.latitude, item.longitude, item.address);
  99. }}>
  100. <MaterialIcons
  101. name='directions'
  102. size={32}
  103. color={colorAccent}/>
  104. <Text style={styles.distanceText}>{item.distance}</Text>
  105. </Pressable>
  106. </View>
  107. );
  108. } else {
  109. return null;
  110. }
  111. }
  112. render() {
  113. return (
  114. <View style={styles.container}>
  115. <View style={styles.searchView}>
  116. <Feather
  117. name={'search'}
  118. size={20}
  119. color={'#999'}/>
  120. <TextInput
  121. style={styles.searchInput}
  122. autoFocus={true}
  123. maxLength={50}
  124. numberOfLines={1}
  125. returnKeyType={'search'}
  126. clearButtonMode={'while-editing'}
  127. placeholder='Search using location name or service provider'
  128. placeholderTextColor={textPlacehoder}
  129. onChangeText={text => {
  130. this.searchWorld = text;
  131. }}
  132. onSubmitEditing={() => {
  133. this.getGeoLocation();
  134. }}/>
  135. </View>
  136. { this.state.isSearch
  137. ? <View style={styles.searchingView}>
  138. <Image
  139. style={styles.seachingIcon}
  140. source={require('../../images/icon/loading.gif')}/>
  141. </View>
  142. : <FlatList
  143. style={styles.listView}
  144. data={this.state.searchResult}
  145. renderItem={this.listItem}
  146. keyExtractor={item => item.id}
  147. ListEmptyComponent={<Text style={styles.noResult}>No search result</Text>}
  148. />
  149. }
  150. </View>
  151. );
  152. }
  153. }
  154. export const ConnectType = ({type, available, all}) => {
  155. if (type) {
  156. return (
  157. <View style={styles.connectType}>
  158. <Text style={styles.typeLabel}>{type}</Text>
  159. <Text style={styles.typeContent}><Text style={styles.typeBold}>{available}</Text>/{all}</Text>
  160. </View>
  161. );
  162. } else {
  163. return null;
  164. }
  165. }
  166. const styles = StyleSheet.create({
  167. container: {
  168. flex: 1,
  169. backgroundColor: 'white'
  170. },
  171. searchView: {
  172. marginTop: 16,
  173. marginLeft: 16,
  174. marginRight: 16,
  175. marginBottom: 8,
  176. paddingLeft: 16,
  177. paddingRight: 16,
  178. borderRadius: 60,
  179. alignItems: 'center',
  180. flexDirection: 'row',
  181. backgroundColor: '#F5F5F5'
  182. },
  183. searchInput: {
  184. flex: 1,
  185. color: '#333',
  186. ...$padding(6, 8),
  187. fontSize: 15,
  188. marginLeft: 4,
  189. },
  190. searchingView: {
  191. padding: 16,
  192. alignItems: 'center'
  193. },
  194. seachingIcon: {
  195. width: 60,
  196. height: 60
  197. },
  198. noResult: {
  199. color: '#999',
  200. fontSize: 14,
  201. padding: 20,
  202. textAlign: 'center',
  203. },
  204. listView: {
  205. flex: 1
  206. },
  207. itemView: {
  208. alignItems: 'center',
  209. flexDirection: 'row',
  210. borderBottomWidth: 1,
  211. borderBottomColor: '#eee'
  212. },
  213. stationInfo: {
  214. flex: 1,
  215. padding: 16
  216. },
  217. nameView: {
  218. paddingTop: 3,
  219. alignItems: 'center',
  220. flexDirection: 'row'
  221. },
  222. stationName: {
  223. color: '#333',
  224. fontSize: 18,
  225. fontWeight: 'bold'
  226. },
  227. stationAddress: {
  228. color: '#666',
  229. fontSize: 14,
  230. paddingBottom: 8
  231. },
  232. infoStatus: {
  233. fontSize: 10,
  234. paddingTop: 3,
  235. paddingLeft: 8,
  236. paddingRight: 8,
  237. paddingBottom: 3,
  238. borderRadius: 5,
  239. marginLeft: 12,
  240. },
  241. selected: {
  242. color: '#333',
  243. backgroundColor: colorAccent
  244. },
  245. available: {
  246. color: 'white',
  247. backgroundColor: '#90DB0A'
  248. },
  249. unavailable: {
  250. color: '#999',
  251. fontSize: 10.5,
  252. paddingTop: 7,
  253. paddingLeft: 9,
  254. paddingRight: 9,
  255. paddingBottom: 7,
  256. backgroundColor: '#CCC'
  257. },
  258. connectView: {
  259. paddingTop: 4,
  260. paddingBottom: 4,
  261. alignItems: 'center',
  262. flexDirection: 'row'
  263. },
  264. connectType: {
  265. borderWidth: 1,
  266. borderColor: '#333',
  267. borderRadius: 3,
  268. marginRight: 16,
  269. alignItems: 'center',
  270. flexDirection: 'row',
  271. },
  272. typeLabel: {
  273. color: '#fff',
  274. fontSize: 12,
  275. paddingTop: 2,
  276. paddingLeft: 10,
  277. paddingRight: 10,
  278. paddingBottom: 2,
  279. backgroundColor: '#333'
  280. },
  281. typeContent: {
  282. color: '#333',
  283. fontSize: 12,
  284. paddingLeft: 10,
  285. paddingRight: 6,
  286. },
  287. typeBold: {
  288. fontSize: 14,
  289. fontWeight: 'bold'
  290. },
  291. directView: {
  292. zIndex: 1,
  293. paddingTop: 4,
  294. paddingRight: 16,
  295. alignItems: 'center'
  296. },
  297. distanceText: {
  298. color: '#333',
  299. fontSize: 12,
  300. paddingTop: 2
  301. },
  302. });