Explorar o código

add app/pages/chargeV2/TabReserve.js

wudebin hai 6 meses
pai
achega
7850f5475f
Modificáronse 1 ficheiros con 552 adicións e 0 borrados
  1. 552 0
      Strides-SPAPP/app/pages/chargeV2/TabReserve.js

+ 552 - 0
Strides-SPAPP/app/pages/chargeV2/TabReserve.js

@@ -0,0 +1,552 @@
+/**
+ * 新版充电预定页面
+ * @邠心vbe on 2023/02/06
+ */
+ import React, { Component } from 'react'
+ import { Image, RefreshControl, ScrollView, StyleSheet, Text, View } from 'react-native'
+ import Button from '../../components/Button';
+ import { ChargeStyle, EnterStationDialog, TypeImage } from './Charging';
+ import apiCharge from '../../api/apiCharge';
+ import Dialog from '../../components/Dialog';
+ import { PageList } from '../Router';
+ import { CancelReserveDialog } from './InfoDialog';
+import PagerUtil from './PagerUtil';
+import BadgeSelectItem from '../../components/BadgeSelectItem';
+import TextView from '../../components/TextView';
+import { MyRefreshProps } from '../../components/ThemesConfig';
+import { QRResult } from '../charge/QRScan';
+import { PagerList } from './ChargeAdapter';
+
+export default class TabReserve extends Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      total: 0,
+      leftId: 0,
+      refreshing: false,
+      checkIndex: -1,
+      available: false,
+      showReserve: false,
+      stationInfo: {},
+      checkConnector: {},
+      userReserve: {},
+      timeLeft: '',
+      showCancelDialog: false,
+      showStationDialog: false
+    };
+  }
+
+  componentDidMount() {
+    PagerUtil.addOnRefresh(this);
+    this.onRefresh();
+  }
+
+  onRefresh() {
+    console.log("Reserve刷新", this.props.route.name);
+    this.setState({
+      refreshing: false,
+      stationInfo: PagerUtil.getStationInfo()
+    }, () => this.init());
+  }
+
+  onPullRefresh() {
+    this.setState({
+      refreshing: true
+    })
+    PagerUtil.setBackRefreshing();
+  }
+
+  init() {
+    this.stopCountdown(true);
+    if (this.state.stationInfo.rateList && this.state.stationInfo.rateList.length > 0) {
+      for (var i = 0; i < this.state.stationInfo.rateList.length; i++) {
+        const item = this.state.stationInfo.rateList[i]
+        if (item.available) {
+          this.setState({
+            checkIndex: i,
+            checkConnector: item,
+          })
+          break;
+        }
+      }
+      this.setState({
+        total: this.state.stationInfo.rateList.length,
+        showReserve: this.state.stationInfo.enableReservation ? true : false
+      })
+      this.getReserve();
+      //this.refreshAvailable();
+    } else {
+      this.setState({
+        showReserve: false
+      })
+    }
+  }
+
+  //刷新可用充电接口
+  refreshAvailable() {
+    const info = this.state.stationInfo
+    const all = info?.allConnector;
+    /*if (info.siteType == 'Private') {
+      this.setState({
+        isPrivate: true
+      })
+    }*/
+    if (all) {
+      this.setState({
+        available: !all.available > 0
+      });
+    }
+  }
+
+  checkChange(index) {
+    if (this.state.checkIndex !== index) {
+      this.setState({
+        checkIndex: index,
+        checkConnector: this.state.stationInfo.rateList[index],
+      })
+    }
+  }
+
+  getAvailable(type) {
+    let count = type;
+    if (typeof type === 'string') {
+      count = type == "AC" ? this.state.stationInfo.acConnector :  this.state.stationInfo.dcConnector;
+    }
+    if (count) {
+      return count.available + '/' + count.all;
+    } else {
+      return '0/0';
+    }
+  }
+
+  getReserve() {
+    apiCharge.getUserReserve(this.state.stationInfo.id).then(res => {
+      if (res.data.reservePk && res.data.reserveEndTimeTimestamp > 0) {
+        this.setState({
+          userReserve: res.data
+        }, () => this.startCountdown());
+      } else {
+        this.stopCountdown();
+      }
+    }).catch((err) => {
+      this.stopCountdown();
+    });
+  }
+
+  onReserve() {
+    if (this.state.checkConnector?.chargeTypePk) {
+      Dialog.showProgressDialog();
+      apiCharge.reserveCharge({
+        sitePk: this.state.stationInfo.id,
+        chargeTypePk: this.state.checkConnector.chargeTypePk
+      }).then(res => {
+        Dialog.dismissLoading();
+        toastShort($t('charging.reservedSuccess'));
+        PagerUtil.setBackRefreshing();
+        this.getReserve();
+      }).catch((err) => {
+        Dialog.dismissLoading();
+        toastShort(err)
+      });
+    } else {
+      toastShort($t('charging.plsSelectConnnector'))
+    }
+  }
+
+  onCancel() {
+    if (this.state.userReserve.reservePk) {
+      Dialog.showProgressDialog();
+      apiCharge.cancelReserve(this.state.userReserve.reservePk).then(res => {
+        Dialog.dismissLoading();
+        PagerUtil.setBackRefreshing();
+        toastShort($t('common.cancelSuccess'));
+        this.getReserve();
+      }).catch((err) => {
+        Dialog.dismissLoading();
+        toastShort(err)
+      });
+    }
+  }
+
+  cancelReserve() {
+    // this.setState({
+    //   showCancelDialog: true
+    // });
+    Dialog.showDialog({
+      title: $t('charging.cancelReservation'),
+      message: $t('charging.confirmCancelReservation'),
+      ok: $t('nav.yes'),
+      cancel: $t('nav.no'),
+      callback: (btn => {
+        if (btn == "ok") {
+          this.onCancel();
+        }
+      })
+    })
+  }
+
+  startCountdown() {
+    if (this.state.userReserve.reserveEndTimeTimestamp > 0) {
+      if (!QRResult.haveResult()) {
+        PagerUtil.onReserve(this.props);
+      }
+      const leftId = this.state.leftId;
+      this.countdown(leftId);
+    } else {
+      this.stopCountdown(false, true);
+    }
+  }
+
+  countdown(leftId) {
+    if (leftId != this.state.leftId) {
+      console.log(leftId, this.state.leftId);
+      return;
+    }
+    const now = new Date().getTime();
+    let left = this.state.userReserve.reserveEndTimeTimestamp - now;
+    let s = 0, m = 0, h = 0;
+    if (left > 1000) {
+      s = left / 1000;
+      if (s > 60) {
+        m = s / 60;
+        s = s % 60;
+        if (m > 60) {
+          h = m / 60;
+          m = m % 60;
+        }
+      }
+    } else {
+      this.stopCountdown(false, true)
+    }
+    this.setState({
+      timeLeft: this.formatNumber(h) + ' : ' + this.formatNumber(m) + ' : ' + this.formatNumber(s)
+    });
+    setTimeout(() => {
+      this.countdown(leftId);
+    }, 1000);
+  }
+
+  formatNumber(ins) {
+    const num = parseInt(ins)
+    if (num > 0) {
+      if (num < 10) {
+        return '0' + num;
+      } else {
+        return num;
+      }
+    } else {
+      return '00';
+    }
+  }
+
+  stopCountdown(just, refresh) {
+    if (just) {
+      this.setState({
+        leftId: this.state.leftId + 1
+      });
+    } else {
+      this.setState({
+        leftId: this.state.leftId + 1,
+        userReserve: {}
+      });
+    }
+    if (refresh) {
+      PagerUtil.setBackRefreshing();
+    }
+  }
+
+  enterStatioinId() {
+    PagerUtil.onEnterStation(this.props);
+    setTimeout(() => {
+      PagerUtil.setRefreshing(PagerList.tabCharge)
+    }, 300);
+  }
+
+  render() {
+    return (
+      <ScrollView
+        style={ui.flex1}
+        keyboardShouldPersistTaps={isIOS ? 'never' : 'handled'}
+        contentContainerStyle={$padding(0, 16)}
+        refreshControl={
+          <RefreshControl
+            {...MyRefreshProps()}
+            refreshing={this.state.refreshing}
+            onRefresh={() => this.onPullRefresh()}
+          />
+        }>
+        { this.state.showReserve
+        ? (
+          this.state.userReserve.reservePk
+            ? this.countdownView()
+            : this.reserveView()
+          )
+        : <View style={[{height: $vh(50)}, ui.flexvc]}>
+            <TextView style={{color: textPrimary, fontSize: 14}}>{$t('charging.unallowReservation')}</TextView>
+          </View>
+        }
+        <CancelReserveDialog
+          visible={this.state.showCancelDialog}
+          onClose={confirm => {
+            this.setState({
+              showCancelDialog: false
+            });
+            if (confirm) {
+              this.onCancel();
+            }
+          }}/>
+        <EnterStationDialog
+          visible={this.state.showStationDialog}
+          stationId={this.state.stationInfo.id}
+          onConfirm={() => this.enterStatioinId()}
+          onClose={() => {
+            this.setState({
+              showStationDialog: false
+            });
+          }}
+        />
+      </ScrollView>
+    );
+  }
+
+  //预定页面
+  reserveView() {
+    return (
+      <>
+      <View style={{minHeight: $vht(75)}}>
+        <TextView style={styles.title}>{$t('charging.chooseConnector')}</TextView>
+        { this.state.total > 0
+          ? this.state.stationInfo.rateList.map((item, index) => {
+            const _type = item.type?.indexOf('AC') >= 0 ? 'AC' : 'DC';
+            return (
+              <BadgeSelectItem
+                key={index}
+                style={ChargeStyle.stationInfoView}
+                onPress={() => {
+                    if (item.available) {
+                      this.checkChange(index)
+                    }
+                  }
+                }
+                checked={index == this.state.checkIndex}>
+                {/* <SelectableIcon selected={index == this.state.checkIndex}>
+                  
+                </SelectableIcon> */}
+                <Image
+                  style={ChargeStyle.infoIcon}
+                  source={_type == "AC" ? TypeImage.AC : TypeImage.DC}/>
+                <View style={ChargeStyle.infoGroup}>
+                  <TextView style={ChargeStyle.infoText}>{item.type}</TextView>
+                  <TextView style={ChargeStyle.infoTitle}>{$t('charging.labelType')}</TextView>
+                </View>
+                <View style={ChargeStyle.infoGroup}>
+                  <TextView style={ChargeStyle.infoText}>{item.power}</TextView>
+                  <TextView style={ChargeStyle.infoTitle}>{$t('charging.labelPower')}</TextView>
+                </View>
+                <View style={ChargeStyle.infoGroup}>
+                  <TextView style={ChargeStyle.infoText}>{this.getAvailable(_type)}</TextView>
+                  <TextView style={ChargeStyle.infoTitle}>{$t('charging.labelAvailableTotal')}</TextView>
+                </View>
+                <View style={ChargeStyle.infoGroup}>
+                  { item?.connectorCount?.available > 0
+                    ? <TextView style={[ChargeStyle.infoStatus, ChargeStyle.statusAvailable]}>{$t('charging.statusAvailable')}</TextView>
+                    : <TextView style={[ChargeStyle.infoStatus, ChargeStyle.statusUnavailable]}>{$t('charging.statusUnavailable')}</TextView>
+                  }
+                  <TextView style={ChargeStyle.infoTitle}>{$t('charging.labelStatus')}</TextView>
+                </View>
+                {/* index == this.state.checkIndex
+                  ? <Text style={[ChargeStyle.infoStatus, ChargeStyle.statusSelected]}>Selected</Text>
+                  : (item.available
+                    ? <TextView style={[ChargeStyle.infoStatus, ChargeStyle.statusAvailable]}>Available</TextView>
+                    : <TextView style={[ChargeStyle.infoStatus, ChargeStyle.statusUnavailable]}>Unavailable</TextView>
+                  )
+                */}
+              </BadgeSelectItem>
+            )
+          }) : null
+        }
+        { this.state.checkConnector.available
+          ? <>
+              <TextView style={styles.title}>{$t('charging.chooseRate')}</TextView>
+              <BadgeSelectItem
+                style={ChargeStyle.stationInfoView}
+                checked={true}>
+                <Image 
+                  style={ChargeStyle.infoIcon}
+                  source={require('../../images/charge/ic-type-rate.png')}/>
+                <TextView style={ChargeStyle.rateText}>{$t('charging.labelRate')}</TextView>
+                <TextView style={[ChargeStyle.ratePrice]}>{this.state.checkConnector.rates}</TextView>
+                <Text></Text>
+                {/* <Text style={[ChargeStyle.infoStatus, ChargeStyle.statusSelected]}>Selected</Text> */}
+              </BadgeSelectItem>
+            </>
+          : <View style={{height: 60}}></View>
+        }
+
+        {/* <Text style={styles.title}>Choose Payment Method</Text>
+        <Payment refreshId={this.state.refreshId}/> */}
+      </View>
+      <Button
+        style={styles.buttonView}
+        elevation={1.5}
+        text={$t('charging.btnReserve')}
+        disabled={this.state.available}
+        onClick={() => this.onReserve()}
+      />
+      </>
+    )
+  }
+
+  //倒计时页面
+  countdownView() {
+    let info = this.state.userReserve.siteRate
+    return (
+      <>
+        <View style={{minHeight: $vht(80)}}>
+          <TextView style={styles.title}>Your Selection</TextView>
+          { info &&
+            <View>
+              <BadgeSelectItem
+                style={ChargeStyle.stationInfoView}
+                checked={true}>
+                <Image
+                  style={ChargeStyle.infoIcon}
+                  source={info.type?.indexOf('AC') >= 0 ? TypeImage.AC : TypeImage.DC}/>
+                <View style={ChargeStyle.infoGroup}>
+                  <TextView style={ChargeStyle.infoText}>{info.type}</TextView>
+                  <TextView style={ChargeStyle.infoTitle}>{$t('charging.labelType')}</TextView>
+                </View>
+                <View style={ChargeStyle.infoGroup}>
+                  <TextView style={ChargeStyle.infoText}>{info.power}</TextView>
+                  <TextView style={ChargeStyle.infoTitle}>{$t('charging.labelPower')}</TextView>
+                </View>
+                <View style={ChargeStyle.infoGroup}>
+                  <TextView style={ChargeStyle.infoBoldNumber}>{this.getAvailable(info.connectorCount)}</TextView>
+                  <TextView style={ChargeStyle.infoTitle}>{$t('charging.labelAvailableTotal')}</TextView>
+                </View>
+                <Text></Text>
+                {/* <SelectableIcon selected={true}/> */}
+              </BadgeSelectItem>
+              <BadgeSelectItem
+                checked={true}
+                style={ChargeStyle.stationInfoView}>
+                <Image 
+                  style={ChargeStyle.infoIcon}
+                  source={require('../../images/charge/ic-type-rate.png')}/>
+                <TextView style={ChargeStyle.rateText}>{$t('charging.labelRate')}</TextView>
+                <TextView style={[ChargeStyle.ratePrice]}>{info.rates}</TextView>
+                <Text></Text>
+                {/* <SelectableIcon selected={true}/> */}
+              </BadgeSelectItem>
+            </View>
+          }
+          <TextView style={styles.timeleftText}>{$t('charging.reserveTimeLeft')}</TextView>
+          <View style={styles.timeleftView}>
+            <TextView style={styles.timeleft}>{this.state.timeLeft}</TextView>
+          </View>
+          <View style={styles.cancelView}>
+            <Button
+              text={$t('charging.btnCancelReservation')}
+              textColor={textButton}
+              style={styles.cancelButton}
+              viewStyle={styles.cancelButtonView}
+              onClick={() => this.cancelReserve()}
+            />
+          </View>
+
+          {/* <Text style={styles.title}>Choose Payment Method</Text>
+          <Payment refreshId={this.state.refreshId}/> */}
+        </View>
+        <View style={styles.buttonGroup}>
+          <Button
+            style={styles.buttonLeft}
+            text={$t('charging.scanQR')}
+            disabled={this.state.available}
+            onClick={() => {
+              PagerUtil.onInnerScanQR();
+              startPage(PageList.scanqr, {actionDetail: false, id: this.state.stationInfo.id});
+            }}/>
+          <Button
+            style={styles.buttonRight}
+            text={$t('charging.enterStationId')}
+            disabled={this.state.available}
+            onClick={() => {
+              this.setState({
+                showStationDialog: true
+              });
+              //startPage(PageList.summary)
+            }
+          }/>
+        </View>
+      </> 
+    )
+  }
+}
+
+const styles = StyleSheet.create({
+  title: {
+    color: '#000',
+    fontSize: 15,
+    fontWeight: 'bold',
+    paddingTop: 16,
+    paddingBottom: 16
+  },
+  listView: {
+    padding: 8,
+    borderRadius: 8,
+    backgroundColor: '#F5F5F5'
+  },
+  buttonView: {
+    marginTop: 32,
+    marginBottom: 16
+  },
+  timeleftText: {
+    color: '#000',
+    fontSize: 16,
+    fontWeight: 'bold',
+    paddingTop: 16,
+    paddingBottom: 8,
+    textAlign: 'center'
+  },
+  timeleftView: {
+    alignItems: 'center',
+    justifyContent: 'center',
+    marginBottom: 16
+  },
+  timeleft: {
+    color: '#FF2E00',
+    fontSize: 18,
+    fontWeight: 'bold'
+  },
+  cancelView: {
+    paddingTop: 8,
+    paddingBottom: 8
+  },
+  cancelButton: {
+    borderRadius: 10,
+    backgroundColor: '#ED4A4A'
+  },
+  cancelButtonView: {
+    flex: 1,
+    height: 48,
+    paddingLeft: 16,
+    paddingRight: 16,
+    alignItems: 'center',
+    flexDirection: 'row'
+  },
+  buttonGroup: {
+    marginTop: 16,
+    marginBottom: 24,
+    alignItems: 'center',
+    flexDirection: 'row'
+  },
+  buttonLeft: {
+    flex: 1,
+    elevation: 1.5,
+  },
+  buttonRight: {
+    flex: 1,
+    marginLeft: 16,
+    elevation: 1.5
+  },
+})