Details.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. /**
  2. * 充电桩详情页
  3. * @邠心vbe on 2021/03/24
  4. */
  5. import React, { Component } from 'react';
  6. import { Image, Pressable, RefreshControl, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
  7. import Modal from 'react-native-modal';
  8. import apiStation from '../../api/apiStation';
  9. import { ModalProps } from '../../components/BottomModal';
  10. import { MyRefreshProps } from '../../components/ThemesConfig';
  11. import { StationBack } from '../../components/Toolbar';
  12. import utils from '../../utils/utils';
  13. import Charge from './Charge';
  14. import Explore from './Explore';
  15. import { LoginDialog } from './InfoDialog';
  16. import Provider from './Provider';
  17. import { QRResult } from './QRScan';
  18. import Reserve from './Reserve';
  19. import SiteInfo from './SiteInfo';
  20. export default class Details extends Component {
  21. constructor(props) {
  22. super(props);
  23. this.state = {
  24. showTab: true,
  25. tabIndex: 1,
  26. tabView: [{
  27. title: 'Site Information'
  28. }, {
  29. title: 'Charge'
  30. }, /*{
  31. title: 'Reserve'
  32. }*/],
  33. refreshId: 0,
  34. refreshing: false,
  35. showContent: false,
  36. showLoginDialog: false,
  37. stationInfo: {}
  38. }
  39. }
  40. componentDidMount() {
  41. this.props.navigation.addListener('beforeRemove', (e) => {
  42. this.hideDialog();
  43. });
  44. this.props.navigation.addListener('focus', () => {
  45. if (this.isHide && this.state.showContent) {
  46. this.updateStationInfo();
  47. } else {
  48. //this.canShowLoginDialog();
  49. }
  50. this.isHide = false;
  51. });
  52. this.props.navigation.addListener('blur', () => {
  53. this.isHide = true;
  54. });
  55. const params = this.props.route.params;
  56. if (params.action && params.stationInfo) {
  57. this.action = params.action
  58. this.setState({
  59. stationInfo: params.stationInfo
  60. });
  61. this.canShowLoginDialog();
  62. }
  63. }
  64. componentDidUpdate() {
  65. var act = this.props.route.params.action;
  66. if (act !== this.state.action) {
  67. this.setState({
  68. action: act,
  69. refreshId: this.state.refreshId + 1
  70. });
  71. if (act == 'qr') {
  72. this.setState({
  73. tabIndex: 1
  74. })
  75. }
  76. }
  77. }
  78. componentWillUnmount() {
  79. QRResult.clearResult();
  80. }
  81. canShowLoginDialog() {
  82. if (isLogin()) {
  83. this.setState({
  84. showContent: true
  85. });
  86. //if (this.action !== 'view')
  87. this.updateStationInfo();
  88. if (this.action == 'qr') {
  89. this.setState({
  90. tabIndex: 1
  91. })
  92. }
  93. } else {
  94. this.setState({
  95. showLoginDialog: true
  96. });
  97. }
  98. }
  99. hideDialog(close) {
  100. this.setState({
  101. showLoginDialog: false
  102. });
  103. if (close) {
  104. goBack();
  105. }
  106. }
  107. updateStationInfo() {
  108. navigator.geolocation.getCurrentPosition(location => {
  109. let params = {
  110. lat: location.coords.latitude,
  111. lng: location.coords.longitude,
  112. sitePk: this.state.stationInfo.id
  113. }
  114. apiStation.getStationRate(params).then(res => {
  115. if (res.data.sitePk) {
  116. var info = utils.getSiteInfo(res.data);
  117. this.setState({
  118. refreshing: false,
  119. stationInfo: info,
  120. refreshId: this.state.refreshId + 1
  121. });
  122. }
  123. }).catch(err => {
  124. toastLong(err);
  125. this.setState({
  126. refreshing: false
  127. })
  128. });
  129. });
  130. }
  131. getAvailable(type) {
  132. const all = this.state.stationInfo.allConnector;
  133. if (all) {
  134. if (type == 'box') {
  135. return all.boxAvailable + '/' + all.boxAll;
  136. } else {
  137. return all.available + '/' + all.all;
  138. }
  139. } else {
  140. return '0/0';
  141. }
  142. }
  143. onRefresh() {
  144. this.setState({
  145. refreshing: true
  146. });
  147. this.updateStationInfo();
  148. }
  149. onEnterStation() {
  150. this.setState({
  151. refreshId: this.state.refreshId + 1
  152. }, () => this.changeTab(1));
  153. }
  154. changeTab(index) {
  155. this.setState({
  156. tabIndex: index
  157. });
  158. }
  159. render() {
  160. return (
  161. <>
  162. <ScrollView
  163. style={styles.container}
  164. keyboardShouldPersistTaps={'handled'}
  165. refreshControl={
  166. <RefreshControl
  167. {...MyRefreshProps}
  168. refreshing={this.state.refreshing}
  169. onRefresh={() => this.onRefresh()}
  170. />
  171. }>
  172. <View style={styles.headerView}>
  173. <StationBack />
  174. <View style={styles.summaryView}>
  175. <Image
  176. style={{
  177. width: 50,
  178. height: 50,
  179. marginTop: 8
  180. }}
  181. source={require('../../images/charge/icon-station-no.png')}/>
  182. <View style={styles.stationInfo}>
  183. <Text
  184. style={styles.stationName}
  185. ellipsizeMode='tail'
  186. numberOfLines={1}>{this.state.stationInfo?.name}</Text>
  187. {/* <Text style={styles.stationAddress}>{this.state.stationInfo?.address}</Text> */}
  188. <Provider
  189. color='#333'
  190. providers={this.state.stationInfo?.serviceProvider}/>
  191. </View>
  192. <TouchableOpacity
  193. style={styles.directView}
  194. onPress={() => {
  195. utils.directMaps(this.state.stationInfo.latitude, this.state.stationInfo.longitude, this.state.stationInfo.address);
  196. }}>
  197. <MaterialIcons
  198. name='directions'
  199. size={32}
  200. color={colorPrimary}/>
  201. <Text style={styles.lengthText}>{this.state.stationInfo.distance}</Text>
  202. </TouchableOpacity>
  203. </View>
  204. <View style={styles.chargingInfo}>
  205. <View style={styles.available}>
  206. <Image
  207. style={{
  208. width: 16,
  209. height: 16,
  210. marginRight: 8
  211. }}
  212. source={require('../../images/charge/icon-type-stops.png')}/>
  213. <Text style={{
  214. color: '#333',
  215. fontSize: 14
  216. }}>Available {this.getAvailable('box')}</Text>
  217. </View>
  218. <Text style={styles.available2}/>
  219. <View style={styles.available}>
  220. <Image
  221. style={{
  222. width: 17,
  223. height: 17,
  224. marginRight: 8
  225. }}
  226. source={require('../../images/charge/icon-type-interfaces.png')}/>
  227. <Text style={{
  228. color: '#333',
  229. fontSize: 14
  230. }}>Available {this.getAvailable('inc')}</Text>
  231. </View>
  232. </View>
  233. </View>
  234. <View style={styles.tabContainer}>
  235. { this.state.showContent &&
  236. <>
  237. { this.state.showTab &&
  238. <View style={styles.tabView}>
  239. { this.state.tabView.map((view, index) => {
  240. return (
  241. <Pressable
  242. key={index}
  243. style={[
  244. styles.tabPress,
  245. index == 0 && styles.tabPress0,
  246. index == this.state.tabIndex && styles.active
  247. ]}
  248. onPress={() => {
  249. this.changeTab(index)
  250. }}
  251. android_ripple={ripple}>
  252. <Text
  253. style={[
  254. styles.tabText,
  255. index == this.state.tabIndex && styles.active,
  256. { borderLeftWidth: index > 0 ? 1 : 0 }
  257. ]}
  258. numberOfLines={1}>{view.title}</Text>
  259. </Pressable>
  260. );
  261. })
  262. }
  263. </View>
  264. }
  265. <View style={styles.tabContent}>
  266. <SiteInfo
  267. style={this.state.tabIndex == 0 ? styles.tabActive : styles.tabInactive}
  268. stationInfo={this.state.stationInfo}
  269. refreshId={this.state.refreshId}/>
  270. <Charge
  271. style={this.state.tabIndex == 1 ? styles.tabActive : styles.tabInactive}
  272. visible={this.state.tabIndex == 1}
  273. stationInfo={this.state.stationInfo}
  274. refreshId={this.state.refreshId}
  275. onCharge={() =>
  276. this.setState({
  277. tabIndex: 1
  278. })
  279. }/>
  280. { this.state.stationInfo.rateList !== undefined &&
  281. <Reserve
  282. style={this.state.tabIndex == 2 ? styles.tabActive : styles.tabInactive}
  283. visible={this.state.tabIndex == 2}
  284. refreshId={this.state.refreshId}
  285. stationInfo={this.state.stationInfo}
  286. onRefresh={() => this.updateStationInfo()}
  287. onReserve={() => this.changeTab(2)}
  288. onEnterStation={() => this.onEnterStation()}
  289. />
  290. }
  291. {/* <Explore style={this.state.tabIndex == 2 ? styles.tabActive : styles.tabInactive}/> */}
  292. </View>
  293. </>
  294. }
  295. </View>
  296. </ScrollView>
  297. <Modal
  298. isVisible={this.state.showLoginDialog}
  299. onBackButtonPress={() => this.hideDialog(true)}
  300. onBackdropPress={() => this.hideDialog()}
  301. {...ModalProps}>
  302. <LoginDialog
  303. onHide={() => this.hideDialog()}
  304. onClose={() => this.hideDialog(true)} />
  305. </Modal>
  306. </>
  307. )
  308. }
  309. }
  310. const styles = StyleSheet.create({
  311. container: {
  312. ...StyleSheet.absoluteFillObject,
  313. backgroundColor: 'white'
  314. },
  315. headerView: {
  316. paddingTop: 16,
  317. paddingLeft: 16,
  318. paddingRight: 16,
  319. paddingBottom: 32,
  320. backgroundColor: colorThemes
  321. },
  322. summaryView: {
  323. paddingBottom: 16,
  324. flexDirection: 'row',
  325. },
  326. stationInfo: {
  327. flex: 1,
  328. paddingLeft: 16,
  329. paddingRight: 16
  330. },
  331. stationName: {
  332. color: '#333',
  333. fontSize: 20,
  334. fontWeight: 'bold',
  335. paddingBottom: 2
  336. },
  337. stationAddress: {
  338. color: '#333',
  339. fontSize: 12,
  340. },
  341. directView: {
  342. zIndex: 2,
  343. paddingTop: 4,
  344. alignItems: 'center',
  345. },
  346. lengthText: {
  347. color: '#333',
  348. fontSize: 12,
  349. paddingTop: 2
  350. },
  351. chargingInfo: {
  352. zIndex: 2,
  353. alignItems: 'center',
  354. borderColor: 'white',
  355. borderTopWidth: 1,
  356. flexDirection: 'row'
  357. },
  358. available: {
  359. flex: 1,
  360. padding: 16,
  361. alignItems: 'center',
  362. flexDirection: 'row',
  363. justifyContent: 'center'
  364. },
  365. available2: {
  366. color: '#333',
  367. fontSize: 14,
  368. borderLeftWidth: 1.5,
  369. borderLeftColor: 'white',
  370. },
  371. tabContainer: {
  372. flex: 1,
  373. paddingTop: 14,
  374. marginTop: -32,
  375. backgroundColor: 'white',
  376. borderTopLeftRadius: 20,
  377. borderTopRightRadius: 20
  378. },
  379. tabView: {
  380. marginTop: 8,
  381. marginLeft: 16,
  382. marginRight: 16,
  383. borderRadius: 8,
  384. overflow: 'hidden',
  385. alignItems: 'center',
  386. flexDirection: 'row',
  387. borderWidth: 1,
  388. borderColor: '#eee',
  389. borderBottomWidth: 2
  390. },
  391. tabPress: {
  392. flex: 1,
  393. paddingTop: 12,
  394. paddingBottom: 12,
  395. marginRight: 1
  396. },
  397. tabPress0: {
  398. flex: 1.2
  399. },
  400. tabText: {
  401. color: '#333',
  402. fontSize: 15,
  403. marginLeft: -1,
  404. textAlign: 'center',
  405. borderLeftColor: '#eee'
  406. },
  407. active: {
  408. color: '#fff',
  409. backgroundColor: colorPrimary
  410. },
  411. tabContent: {
  412. flex: 1
  413. },
  414. tabActive: {
  415. display: 'flex'
  416. },
  417. tabInactive: {
  418. display: 'none'
  419. }
  420. })