Details.js 11 KB

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