Jelajahi Sumber

add app/pages/chargeV2/Summary.js

wudebin 6 bulan lalu
induk
melakukan
785c21cb78

+ 316 - 0
Strides-SPAPP/app/pages/chargeV2/Summary.js

@@ -0,0 +1,316 @@
+/**
+ * 新版充电结算页面
+ * @邠心vbe on 2023/02/08
+ */
+import React, { Component } from 'react';
+import { View, Text, StyleSheet, Image, ScrollView, RefreshControl } from 'react-native';
+import apiCharge from '../../api/apiCharge';
+import Button from '../../components/Button';
+import Dialog from '../../components/Dialog';
+import TextView from '../../components/TextView';
+import { MyRefreshProps } from '../../components/ThemesConfig';
+import routeUtil from '../../utils/routeUtil';
+import utils from '../../utils/utils';
+import { PageList } from '../Router';
+import { ChargeStyle, TypeImage } from './Charging';
+
+export default class Summary extends Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      isActully: true,
+      refreshing: false,
+      summaryInfo: {},
+      stationInfo: {} 
+    };
+    this.canBack = false;
+  }
+
+  componentDidMount() {
+    const params = this.props.route.params;
+    if (params.chargingPk) {
+      Dialog.showProgressDialog();
+      if (params.name && params.address) {
+        this.setState({
+          chargingPk: params.chargingPk,
+          stationInfo: {
+            id: params.id,
+            name: params.name,
+            address: params.address
+          }
+        });
+        setTimeout(() => {
+          this.getSummaryData(params.chargingPk);
+        }, 5000);
+      } else if (params.action && params.action == "view") {
+        this.setState({
+          isActully: false,
+          chargingPk: params.chargingPk
+        });
+        this.getSummaryData(params.chargingPk);
+      }
+    }
+    this.props.navigation.addListener('focus', e => {
+      this.canBack = false;
+    });
+    this.props.navigation.addListener('beforeRemove', e => {
+      if (this.state.isActully && !this.canBack) {
+        this.toRating();
+        e.preventDefault();
+      }
+    });
+  }
+
+  getSummaryData(chargingPk) {
+    apiCharge.getChargeSummary({
+      chargingPk: chargingPk
+    }).then(res => {
+      Dialog.dismissLoading();
+      if (res.data) {
+        this.setState({
+          refreshing: false,
+          summaryInfo: res.data
+        });
+      }
+    }).catch((err) => {
+      Dialog.dismissLoading();
+      toastShort(err);
+      this.setState({
+        refreshing: false
+      });
+    });
+  }
+
+  onRefresh() {
+    if (this.state.chargingPk) {
+      this.setState({
+        refreshing: true
+      });
+      this.getSummaryData(this.state.chargingPk);
+    }
+  }
+
+  toRating() {
+    this.canBack = true;
+    //goBack();
+    //routeUtil.resetToHome(this.props);
+    startPage(PageList.home);
+    //startPage(PageList.rating, this.state.stationInfo);
+  }
+
+  getSummaryText(data) {
+    if (this.state.summaryInfo?.paymentType == 'Fleet Credit') {
+      return '-';
+    } else {
+      return currency + '' + (data ?? '0');
+    }
+  }
+
+  render() {
+    return (
+      <ScrollView
+        style={styles.container}
+        refreshControl={
+          <RefreshControl
+            {...MyRefreshProps()}
+            refreshing={this.state.refreshing}
+            onRefresh={() => this.onRefresh()}
+          />
+        }>
+        <View style={{height:16}}></View>
+        <View style={styles.sections}>
+          <View style={styles.formRow}>
+            <TextView style={styles.label}>{$t('wallet.labelTransactionId')}</TextView>
+            <TextView style={styles.text}>{this.state.summaryInfo.transactionPk}</TextView>
+          </View>
+          <View style={styles.formRow}>
+            <TextView style={styles.label}>{$t('wallet.labelReferenceId')}</TextView>
+            <TextView style={styles.text}>{this.state.summaryInfo.chargingPk}</TextView>
+          </View>
+          <View style={styles.formRow}>
+            <TextView style={styles.label}>{$t('wallet.labelDateTime')}</TextView>
+            <TextView style={styles.text}>{this.state.summaryInfo.dateTime}</TextView>
+          </View>
+        </View>
+        <View style={styles.sections}>
+          <TextView style={styles.formTitle}>{$t('wallet.labelYourStation')}</TextView>
+          <View style={styles.formRow}>
+            <TextView style={styles.label}>{$t('wallet.labelStationId') + this.state.summaryInfo.chargeBoxPk}</TextView>
+          </View>
+          <TextView style={styles.stationInfoText}>{this.state.summaryInfo?.boxAddress}</TextView>
+        </View> 
+
+        <View style={styles.sections2}>
+          <TextView style={styles.formTitle}>{$t('wallet.labelYourConnector')}</TextView>
+          <View style={styles.stationInfoView}>
+            <Image
+              style={ChargeStyle.infoIcon}
+              source={this.state.summaryInfo.connectorType?.indexOf('AC') >= 0 ? TypeImage.AC : TypeImage.DC}/>
+            <View style={ChargeStyle.infoGroup}>
+              <TextView style={ChargeStyle.infoText}>{this.state.summaryInfo.connectorType}</TextView>
+              <TextView style={ChargeStyle.infoTitle}>{$t('charging.labelType')}</TextView>
+            </View>
+            <View style={ChargeStyle.infoGroup}>
+              <TextView style={ChargeStyle.infoText}>{this.state.summaryInfo.connectorWattage}</TextView>
+              <TeTextViewxt style={ChargeStyle.infoTitle}>{$t('charging.labelPower')}</TeTextViewxt>
+            </View>
+            <View style={ChargeStyle.infoGroup}>
+              <TextView style={ChargeStyle.infoText}>{this.state.summaryInfo.connectorRate}</TextView>
+              <TextView style={ChargeStyle.infoTitle}>{$t('charging.labelRate')}</TextView>
+            </View>
+          </View>
+        </View> 
+
+        <View style={styles.sections}>
+          <TextView style={styles.formTitle}>{$t('wallet.labelBreakdown')}</TextView>
+          <View style={styles.formRow}>
+            <TextView style={styles.label}>{$t('wallet.labelReservationFee')}</TextView>
+            <TextView style={styles.text}>{currency}{this.state.summaryInfo.reservationFee ?? 0}</Text>
+          </View>
+          { utils.isNotEmpty(this.state.summaryInfo.idleFee) &&
+            <View style={styles.formRow}>
+              <TextView style={styles.label}>{$t('wallet.labelIdleFee')}</TextView>
+              <TextView style={styles.text}>{currency}{this.state.summaryInfo.idleFee}</Text>
+            </View>
+          }
+          <View style={styles.formRow}>
+            <TextView style={styles.label}>{$t('wallet.labelChargeTime')}</TextView>
+            <TextView style={styles.text}>{utils.hour2HHmm(this.state.summaryInfo.chargeTime)}</TextView>
+          </View>
+          <View style={styles.formRow}>
+            <TextView style={styles.label}>{$t('wallet.labelChargeDelivered')}</TextView>
+            <TextView style={styles.text}>{this.state.summaryInfo.chargeDelivered ?? 0}kWh</TextView>
+          </View>
+          <View style={styles.formRow}>
+            <TextView style={styles.label}>{$t('wallet.labelChargeRates')}</TextView>
+            <TextView style={styles.text}>{currency}{this.state.summaryInfo.chargeRates ?? '0.0'}</Text>
+          </View>
+        </View>
+
+        <View style={styles.sections}>
+          <TextView style={styles.formTitle}>{$t('wallet.labelSubtotal')}</TextView>
+          <View style={styles.formRow}>
+            <TextView style={styles.label}>{$t('wallet.labelPaymentMadeBy')}</TextView>
+            <TextView style={styles.text}>{this.state.summaryInfo.paymentType}</TextView>
+          </View>
+          <View style={styles.formRow}>
+            <TextView style={styles.label}>{$t('wallet.labelPreviousBalance')}</TextView>
+            <TextView style={styles.text}>{this.getSummaryText(this.state.summaryInfo.previousBalance)}</TextView>
+          </View>
+          <View style={styles.formRow}>
+            <TextView style={styles.label}>{$t('wallet.labelPayment')}</TextView>
+            <TextView style={styles.text}>{currency}{this.state.summaryInfo.payment ?? '0.0'}</Text>
+          </View>
+          <View style={styles.formRow}>
+            <TextView style={styles.label}>{$t('wallet.labelExchangeRate')}</TextView>
+            <TextView style={styles.text}>{this.getSummaryText(this.state.summaryInfo.exchangeRate)}</TextView>
+          </View>
+          <View style={styles.formRow}>
+            <TextView style={styles.label}>{$t('wallet.labelFinalPayment')}</TextView>
+            <TextView style={styles.text}>{this.getSummaryText(this.state.summaryInfo.finalPayment)}</TextView>
+          </View>
+          <View style={styles.formRow}>
+            <TextView style={styles.label}>{$t('wallet.labelResultingBalance')}</TextView>
+            <TextView style={styles.text}>{this.getSummaryText(this.state.summaryInfo.resultingBalance)}</TextView>
+          </View>
+        </View>
+        { this.state.isActully &&
+          <View style={styles.bottomButton}>
+            <TextView
+              style={styles.feedback}
+              onPress={() => startPage(PageList.feedback)}>{$t('wallet.linkSubmitFeedback')}</TextView>
+            <TextView style={styles.tipText}>{$t('wallet.tipsReceipt')}</TextView>
+            <Button
+              text={$t('home.done')}
+              elevation={1.5}
+              onClick={() => this.toRating()}/>
+          </View>
+        }
+      </ScrollView>
+    );
+  }
+}
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    paddingLeft: 16,
+    paddingRight: 16,
+    backgroundColor: colorLight
+  },
+  sections: {
+    borderRadius: 10,
+    marginBottom: 16,
+    backgroundColor: colorLight
+  },
+  sections2: {
+    paddingTop: 0,
+    paddingLeft: 0,
+    paddingRight: 0,
+    paddingBottom: 8,
+    borderRadius: 10,
+    marginBottom: 8,
+    backgroundColor: colorLight
+  },
+  formTitle: {
+    color: '#000',
+    fontSize: 14,
+    marginTop: -4,
+    marginBottom: 6,
+    paddingBottom: 6,
+    fontWeight: 'bold',
+    borderBottomWidth: 1,
+    borderBottomColor: '#eee'
+  },
+  formRow: {
+    paddingTop: 3,
+    paddingBottom: 3,
+    alignItems: 'center',
+    flexDirection: 'row'
+  },
+  label: {
+    flex: 1,
+    color: textPrimary,
+    fontSize: 13,
+  },
+  text: {
+    color: textPrimary,
+    fontSize: 13,
+  },
+  stationInfoView: {
+    padding: 12,
+    marginBottom: 0,
+    alignItems: 'center',
+    flexDirection: 'row',
+    justifyContent: 'space-between'
+  },
+  stationInfoText: {
+    color: '#999',
+    fontSize: 11
+  },
+  connectorView: {
+    alignItems: 'center',
+    flexDirection: 'row'
+  },
+  typeIcon: {
+    width: 36,
+    height: 36
+  },
+  feedback: {
+    color: '#12A5F9',
+    fontSize: 14,
+    textAlign: 'center',
+    marginBottom: 16,
+    ...ui.underline
+  },
+  bottomButton: {
+    marginTop: 32,
+    marginBottom: 16
+  },
+  tipText: {
+    color: textPrimary,
+    fontSize: 12,
+    textAlign: 'center',
+    marginBottom: 8
+  }
+});

+ 614 - 0
Strides-SPAPP/app/pages/chargeV2/SummaryV2.js

@@ -0,0 +1,614 @@
+/**
+ * 新版充电结算页面
+ * @邠心vbe on 2023/02/08
+ */
+import React, { Component } from 'react';
+import { View, Text, StyleSheet, ScrollView, RefreshControl } from 'react-native';
+import apiCharge from '../../api/apiCharge';
+import Button from '../../components/Button';
+import Dialog from '../../components/Dialog';
+import { MyRefreshProps } from '../../components/ThemesConfig';
+import utils from '../../utils/utils';
+import { PageList } from '../Router';
+import app from '../../../app.json';
+import TextView from '../../components/TextView';
+import Skeleton from 'react-native-reanimated-skeleton';
+
+export default class SummaryV2 extends Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      loading: true,
+      isActully: true,
+      refreshing: false,
+      summaryInfo: {
+        top: {},
+        station: {},
+        connector: {},
+        chargingFee: {},
+        idleFee: {},
+        reservationFee: {},
+        payment: {}
+      },
+      chargingPk: "",
+      isPendding: false
+    };
+    this.action = "";
+    this.canBack = false;
+  }
+
+  componentDidMount() {
+    const params = this.props.route.params;
+    if (params.chargingPk) {
+      //Dialog.showProgressDialog();
+      this.setState({
+        chargingPk: params.chargingPk
+      })
+      if (params.action && params.action == "view") {
+        this.setState({
+          isActully: false
+        });
+        setTimeout(() => {
+          this.getSummaryData(params.chargingPk);
+        }, 1000);
+      } else {
+        setTimeout(() => {
+          this.getSummaryData(params.chargingPk);
+        }, 3000);
+      }
+    }
+    if (params.action) {
+      this.action = params.action;
+    }
+    this.props.navigation.addListener('focus', e => {
+      this.canBack = false;
+    });
+    this.props.navigation.addListener('beforeRemove', e => {
+      if (this.state.isActully && !this.canBack) {
+        this.toRating();
+        e.preventDefault();
+      }
+    });
+  }
+
+  getSummaryData(chargingPk) {
+    apiCharge.getChargeSummaryV2({
+      chargingPk: chargingPk
+    }).then(res => {
+      //Dialog.dismissLoading();
+      if (res.data) {
+        this.setState({
+          loading: false,
+          refreshing: false,
+          summaryInfo: res.data,
+          isPendding: (res.data.hasSettled != true)
+        });
+      }
+    }).catch((err) => {
+      //Dialog.dismissLoading();
+      toastShort(err);
+      this.setState({
+        isPendding: true,
+        refreshing: false
+      });
+    });
+  }
+
+  onRefresh() {
+    if (this.state.chargingPk) {
+      this.setState({
+        refreshing: true
+      });
+      this.getSummaryData(this.state.chargingPk);
+    }
+  }
+
+  toRating() {
+    this.canBack = true;
+    if (this.action == "view") {
+      goBack();
+    } else {
+      //routeUtil.resetToHome(this.props);
+      startPage(PageList.home);
+      //startPage(PageList.rating, this.state.stationInfo);
+    }
+  }
+
+  toTransaction() {
+    if (this.action == "view") {
+      goBack();
+    } else {
+      startPage(PageList.wallet)
+    }
+  }
+
+  getSummaryText(data) {
+    if (this.state.summaryInfo?.paymentType == 'Fleet Credit') {
+      return '-';
+    } else {
+      return currency + '' + (data ?? '0');
+    }
+  }
+
+  getTaxTitle(title="") {
+    if (this.state.summaryInfo?.taxRate) {
+      return title.replace("$s", this.state.summaryInfo.taxRate)
+    } else {
+      return title;
+    }
+  }
+
+  isLoading(precond) {
+    return utils.isNotEmpty(precond) || this.state.loading;
+  }
+
+  getSkeletonLeft(size=3) {
+    const list = [];
+    for (let i = 0; i < size; i++) {
+      list.push({width: i % 2 ==0 ? '100%' : '70%', height: 18, marginTop: 4, marginBottom: 4, borderRadius: 3});
+    }
+    return list;
+  }
+
+  getSkeletonRight(size=3) {
+    const list = [];
+    for (let i = 0; i < size; i++) {
+      list.push({width: '100%', height: 18, marginTop: 4, marginBottom: 4, borderRadius: 3});
+    }
+    return list;
+  }
+
+  getSectionSkeleton(size) {
+    if (this.state.loading) {
+      return (
+        <View style={[styles.sections, ui.flexc]}>
+          <Skeleton
+            containerStyle={ui.flex2}
+            isLoading={this.state.loading}
+            boneColor='#eeeeee'
+            highlightColor='#f6f6f6'
+            animationType="shiver"
+            layout={this.getSkeletonLeft(size)}
+            animationDirection={'horizontalRight'}>
+            
+          </Skeleton>
+          <View style={ui.flex2}></View>
+          <Skeleton
+            containerStyle={ui.flex1}
+            isLoading={this.state.loading}
+            boneColor='#eeeeee'
+            highlightColor='#f6f6f6'
+            animationType="shiver"
+            layout={this.getSkeletonRight(size)}
+            animationDirection={'horizontalRight'}>
+            
+          </Skeleton>
+        </View>
+      )
+    } else {
+      return <></>
+    }
+  }
+
+  render() {
+    if (this.state.isPendding) {
+      return (
+        <View style={styles.container}>
+          <View style={styles.processContent}>
+            <TextView style={styles.processTitle}>{$t("receipt.processTitle")}</TextView>
+            <TextView style={styles.processText}>{$t("receipt.processMessage1")}</TextView>
+            <TextView style={styles.processText}>
+              {$t("receipt.processMessage2")}
+              <Text style={[ui.bold, ui.underline]} onPress={() => this.toTransaction()}>{$t("receipt.processMessage3")}</Text>.
+            </TextView>
+            <TextView style={styles.processText}>{$t("receipt.processMessage4")}</TextView>
+          </View>
+          <View style={styles.bottomButton}>
+            <Button
+              text={$t('home.done')}
+              elevation={1.5}
+              onClick={() => this.toRating()}/>
+          </View>
+        </View>
+      )
+    } else {
+      return (
+        <ScrollView
+          style={styles.container}
+          refreshControl={
+            <RefreshControl
+              {...MyRefreshProps()}
+              refreshing={this.state.refreshing}
+              onRefresh={() => this.onRefresh()}
+            />
+          }>
+          { this.isLoading(this.state.summaryInfo.top) &&
+            <View style={styles.headerView}>
+              { this.state.isActully && <>
+                <Skeleton
+                  isLoading={this.state.loading}
+                  boneColor='#eeeeee'
+                  highlightColor='#f6f6f6'
+                  animationType="shiver"
+                  layout={[{width: 56, height: 56, borderRadius: 56}]}
+                  animationDirection={'horizontalRight'}>
+                  <Octicons
+                    name="check-circle-fill"
+                    color={colorAccent}
+                    size={56}/>
+                </Skeleton>
+                <Skeleton
+                  isLoading={this.state.loading}
+                  boneColor='#eeeeee'
+                  highlightColor='#f6f6f6'
+                  animationType="shiver"
+                  layout={[{width: 60, height: 20, marginTop: 8, borderRadius: 3}]}
+                  animationDirection={'horizontalRight'}>
+                  <TextView style={styles.topTitle}>{$t('receipt.successful')}</TextView>
+                </Skeleton>
+                <Skeleton
+                  isLoading={this.state.loading}
+                  boneColor='#eeeeee'
+                  highlightColor='#f6f6f6'
+                  animationType="shiver"
+                  layout={[{width: 100, height: 18, marginTop: 4, marginBottom: 32, borderRadius: 3}]}
+                  animationDirection={'horizontalRight'}>
+                  <TextView style={styles.topDesc}>{$t('receipt.chargingSessionComplete')}</TextView>
+                </Skeleton>
+              </>}
+              { utils.isNotEmpty(this.state.summaryInfo.top.company) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{$t('sign.labelCompany')}:</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.top.company}</TextView>
+                </View>
+              }
+              { utils.isNotEmpty(this.state.summaryInfo.top.registrationNo) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{$t('receipt.labelRegistrationNo')}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.top.registrationNo}</TextView>
+                </View>
+              }
+              <View style={styles.formRow}>
+                <Skeleton
+                  containerStyle={ui.flex1}
+                  isLoading={this.state.loading}
+                  boneColor='#eeeeee'
+                  highlightColor='#f6f6f6'
+                  animationType="shiver"
+                  layout={this.getSkeletonLeft()}
+                  animationDirection={'horizontalRight'}>
+                  
+                </Skeleton>
+                <View style={ui.flex2}></View>
+                <Skeleton
+                  containerStyle={ui.flex1}
+                  isLoading={this.state.loading}
+                  boneColor='#eeeeee'
+                  highlightColor='#f6f6f6'
+                  animationType="shiver"
+                  layout={this.getSkeletonRight()}
+                  animationDirection={'horizontalRight'}>
+                  
+                </Skeleton>
+              </View>
+              { utils.isNotEmpty(this.state.summaryInfo.top.transactionId) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{$t('receipt.labelTransactionID')}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.top.transactionId}</TextView>
+                </View>
+              }
+              { utils.isNotEmpty(this.state.summaryInfo.top.referenceId) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{$t('receipt.labelReferenceID')}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.top.referenceId}</TextView>
+                </View>
+              }
+              { utils.isNotEmpty(this.state.summaryInfo.top.dateTime) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{$t('receipt.labelDateTime')}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.top.dateTime}</TextView>
+                </View>
+              }
+            </View>
+          }
+          {this.getSectionSkeleton(2)}
+          {/* <View style={styles.sections}>
+            <View style={styles.formRow}>
+              <Text style={styles.label}>{$t('wallet.labelTransactionId')}</Text>
+              <Text style={styles.text}>{this.state.summaryInfo.transactionPk}</Text>
+            </View>
+            <View style={styles.formRow}>
+              <Text style={styles.label}>{$t('wallet.labelReferenceId')}</Text>
+              <Text style={styles.text}>{this.state.summaryInfo.chargingPk}</Text>
+            </View>
+            <View style={styles.formRow}>
+              <Text style={styles.label}>{$t('wallet.labelDateTime')}</Text>
+              <Text style={styles.text}>{this.state.summaryInfo.dateTime}</Text>
+            </View>
+          </View> */}
+          { utils.isNotEmpty(this.state.summaryInfo.station) &&
+            <View style={styles.sections}>
+              <TextView style={styles.formTitle}>{$t('wallet.labelYourStation')}</TextView>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('wallet.labelStationId')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.station.stationId}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('receipt.labelSiteName')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.station.siteName ?? "-"}</TextView>
+              </View>
+            </View>
+          }
+          {this.getSectionSkeleton()}
+          { utils.isNotEmpty(this.state.summaryInfo.connector) &&
+            <View style={styles.sections}>
+              <TextView style={styles.formTitle}>{$t('wallet.labelYourConnector')}</TextView>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('charging.labelType')}:</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.connector.type}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('charging.labelPower')}:</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.connector.power}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('charging.labelRates')}:</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.connector.rates}</TextView>
+              </View>
+            </View>
+          }
+          {this.getSectionSkeleton()}
+          { utils.isNotEmpty(this.state.summaryInfo.chargingFee) &&
+            <View style={styles.sections}>
+              <TextView style={styles.formTitle}>{$t('receipt.breakdownChargingFees')}</TextView>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('wallet.labelChargeTime')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.chargingFee.chargeTime ?? "-"}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('wallet.labelChargeDelivered')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.chargingFee.chargeDelivered ?? 0}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{this.getTaxTitle($t('receipt.labelChargTransSubtotal2'))}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.chargingFee.transactionSubtotal}</TextView>
+              </View>
+            </View>
+          }
+          {this.getSectionSkeleton()}
+          { utils.isNotEmpty(this.state.summaryInfo.idleFee) &&
+            <View style={styles.sections}>
+              <TextView style={styles.formTitle}>{$t('receipt.breakdownIdlesFees')}</TextView>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('receipt.labelIdleStartTime')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.idleFee.startTime}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('receipt.labelIdleDuration')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.idleFee.duration}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{this.getTaxTitle($t('receipt.labelIdleFeeSubtotal2'))}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.idleFee.subtotal}</TextView>
+              </View>
+            </View>
+          }
+          {this.getSectionSkeleton()}
+          { utils.isNotEmpty(this.state.summaryInfo.reservationFee) &&
+            <View style={styles.sections}>
+              <TextView style={styles.formTitle}>{$t('receipt.breakdownReservationFees')}</TextView>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('receipt.labelTimeReservation')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.reservationFee.reservationTime}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('receipt.labelDurationReservation')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.reservationFee.reservationDuration}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{this.getTaxTitle($t('receipt.labelReservationFeeSubtotal2'))}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.reservationFee.reservationFeeSubtotal}</TextView>
+              </View>
+            </View>
+          }
+          {this.getSectionSkeleton(8)}
+          { utils.isNotEmpty(this.state.summaryInfo.payment) &&
+            <View style={styles.sections}>
+              <TextView style={styles.formTitle}>{$t('receipt.breakdownPayment')}</TextView>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('wallet.labelPaymentMadeBy')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.payment.paymentMadeBy ?? "-"}</TextView>
+              </View>
+              { utils.isNotEmpty(this.state.summaryInfo.payment.transactionSubtotal) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{this.getTaxTitle($t('receipt.labelChargTransSubtotal2'))}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.payment.transactionSubtotal}</TextView>
+                </View>
+              }
+              { utils.isNotEmpty(this.state.summaryInfo.payment.idleFeeSubtotal) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{this.getTaxTitle($t('receipt.labelIdleFeeSubtotal2'))}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.payment.idleFeeSubtotal}</TextView>
+                </View>
+              }
+              { utils.isNotEmpty(this.state.summaryInfo.payment.reservationFeeSubtotal) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{this.getTaxTitle($t('receipt.labelReservationFeeSubtotal2'))}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.payment.reservationFeeSubtotal}</TextView>
+                </View>
+              }
+              { utils.isNotEmpty(this.state.summaryInfo.payment.finalPayment) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>
+                    { utils.isNotEmpty(this.state.summaryInfo.payment.discountCredit)
+                    ? $t('receipt.labelAfterDiscount')
+                    : $t('receipt.labelFinalPaymentAmount')
+                    }
+                  </TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.payment.finalPayment ?? "-"}</TextView>
+                </View>
+              }
+              {/* <View style={styles.formRow}>
+                <Text style={styles.label}>{$t('wallet.labelChargeRates')}</Text>
+                <Text style={styles.text}>{currency}{this.state.summaryInfo.chargeRates ?? '0.0'}</Text>
+              </View> */}
+              { utils.isNotEmpty(this.state.summaryInfo.payment.exchangeRate) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{$t('wallet.labelExchangeRate')}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.payment.exchangeRate ?? "-"}</TextView>
+                </View>
+              }
+              {/* <View style={styles.formRow}>
+                <Text style={styles.label}>{$t('wallet.labelPreviousBalance')}</Text>
+                <Text style={styles.text}>{this.getSummaryText(this.state.summaryInfo.previousBalance)}</Text>
+              </View> */}
+              { utils.isNotEmpty(this.state.summaryInfo.payment.resultingBalance) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{$t('wallet.labelResultingBalance')}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.payment.resultingBalance ?? "-"}</TextView>
+                </View>
+              }
+              { utils.isNotEmpty(this.state.summaryInfo.payment.refundAmount) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{$t('wallet.labelRefundAmount')}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.payment.refundAmount ?? "-"}</TextView>
+                </View>
+              }
+            </View>
+          }
+          <EndView/>
+          { (this.state.isActully && utils.isNotEmpty(this.state.summaryInfo.top)) &&
+            <View style={styles.bottomButton}>
+              {/* <TextView
+                style={styles.feedback}
+                onPress={() => startPage(PageList.feedback)}>{$t('wallet.linkSubmitFeedback')}</TextView> */}
+              {/* <Text style={styles.tipText}>{$t('wallet.tipsReceipt')}</Text> */}
+              <Button
+                text={$t('home.done')}
+                elevation={1.5}
+                onClick={() => this.toRating()}/>
+            </View>
+          }
+        </ScrollView>
+      );
+    }
+  }
+}
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    paddingLeft: 16,
+    paddingRight: 16,
+    backgroundColor: colorLight
+  },
+  headerView: {
+    alignItems: 'center',
+    paddingTop: 16,
+    paddingBottom: 24
+  },
+  topTitle: {
+    color: textPrimary,
+    fontSize: 16,
+    paddingTop: 8,
+    paddingLeft: 8,
+    fontWeight: 'bold'
+  },
+  topDesc: {
+    color: textPrimary,
+    fontSize: 14,
+    marginBottom: 32
+  },
+  sections: {
+    borderRadius: 10,
+    marginBottom: 12,
+    backgroundColor: colorLight
+  },
+  sections2: {
+    paddingTop: 0,
+    paddingLeft: 0,
+    paddingRight: 0,
+    paddingBottom: 8,
+    borderRadius: 10,
+    marginBottom: 8,
+    backgroundColor: colorLight
+  },
+  formTitle: {
+    color: '#000',
+    fontSize: 14,
+    marginTop: -4,
+    marginBottom: 6,
+    paddingBottom: 6,
+    fontWeight: 'bold',
+    borderBottomWidth: 1,
+    borderBottomColor: textPrimary
+  },
+  formRow: {
+    paddingTop: 3,
+    paddingBottom: 3,
+    alignItems: 'center',
+    flexDirection: 'row'
+  },
+  label: {
+    flex: 1,
+    color: textPrimary,
+    fontSize: 13,
+  },
+  text: {
+    color: textPrimary,
+    fontSize: 12,
+    fontWeight: 'bold'
+  },
+  stationInfoView: {
+    padding: 12,
+    marginBottom: 0,
+    alignItems: 'center',
+    flexDirection: 'row',
+    justifyContent: 'space-between'
+  },
+  stationInfoText: {
+    color: '#999',
+    fontSize: 11
+  },
+  connectorView: {
+    alignItems: 'center',
+    flexDirection: 'row'
+  },
+  typeIcon: {
+    width: 36,
+    height: 36
+  },
+  feedback: {
+    color: '#12A5F9',
+    fontSize: 14,
+    textAlign: 'center',
+    marginBottom: 16,
+    ...ui.underline
+  },
+  bottomButton: {
+    marginTop: 16,
+    marginBottom: 16
+  },
+  tipText: {
+    color: textPrimary,
+    fontSize: 12,
+    textAlign: 'center',
+    marginBottom: 8
+  },
+  processContent: {
+    flex: 1,
+    justifyContent: 'center'
+  },
+  processTitle: {
+    color: textTitle,
+    fontSize: 24,
+    fontWeight: 'bold',
+    textAlign: 'center'
+  },
+  processText: {
+    color: textPrimary,
+    fontSize: 14,
+    textAlign: 'center',
+    paddingTop: 16
+  }
+});

+ 621 - 0
Strides-SPAPP/app/pages/chargeV2/SummaryV3.js

@@ -0,0 +1,621 @@
+/**
+ * V3新版充电结算页面
+ * @邠心vbe on 2023/12/22
+ */
+import React, { Component } from 'react';
+import { View, Text, StyleSheet, ScrollView, RefreshControl } from 'react-native';
+import apiCharge from '../../api/apiCharge';
+import Button from '../../components/Button';
+import Dialog from '../../components/Dialog';
+import { MyRefreshProps } from '../../components/ThemesConfig';
+import utils from '../../utils/utils';
+import { PageList } from '../Router';
+import TextView from '../../components/TextView';
+import Skeleton from 'react-native-reanimated-skeleton';
+
+export default class SummaryV3 extends Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      loading: true,
+      isActully: true,
+      refreshing: false,
+      summaryInfo: {
+        top: {},
+        station: {},
+        connector: {},
+        chargingFee: {},
+        idleFee: {},
+        reservationFee: {},
+        payment: {}
+      },
+      chargingPk: "",
+      isPendding: false
+    };
+    this.action = "";
+    this.canBack = false;
+  }
+
+  componentDidMount() {
+    const params = this.props.route.params;
+    if (params.chargingPk) {
+      //Dialog.showProgressDialog();
+      this.setState({
+        chargingPk: params.chargingPk
+      })
+      if (params.action && params.action == "view") {
+        this.setState({
+          isActully: false
+        });
+        setTimeout(() => {
+          this.getSummaryData(params.chargingPk);
+        }, 1000);
+      } else {
+        setTimeout(() => {
+          this.getSummaryData(params.chargingPk);
+        }, 3000);
+      }
+    }
+    if (params.action) {
+      this.action = params.action;
+    }
+    this.props.navigation.addListener('focus', e => {
+      this.canBack = false;
+    });
+    this.props.navigation.addListener('beforeRemove', e => {
+      if (this.state.isActully && !this.canBack) {
+        this.toRating();
+        e.preventDefault();
+      }
+    });
+  }
+
+  getSummaryData(chargingPk) {
+    apiCharge.getChargeSummaryV2({
+      chargingPk: chargingPk
+    }).then(res => {
+      //Dialog.dismissLoading();
+      if (res.data) {
+        this.setState({
+          loading: false,
+          refreshing: false,
+          summaryInfo: res.data,
+          isPendding: (res.data.hasSettled != true)
+        });
+      }
+    }).catch((err) => {
+      //Dialog.dismissLoading();
+      toastShort(err);
+      this.setState({
+        isPendding: true,
+        refreshing: false
+      });
+    });
+  }
+
+  onRefresh() {
+    if (this.state.chargingPk) {
+      this.setState({
+        refreshing: true
+      });
+      this.getSummaryData(this.state.chargingPk);
+    }
+  }
+
+  toRating() {
+    this.canBack = true;
+    if (this.action == "view") {
+      goBack();
+    } else {
+      //routeUtil.resetToHome(this.props);
+      startPage(PageList.home);
+      //startPage(PageList.rating, this.state.stationInfo);
+    }
+  }
+
+  toTransaction() {
+    if (this.action == "view") {
+      goBack();
+    } else {
+      startPage(PageList.wallet)
+    }
+  }
+
+  getSummaryText(data) {
+    if (this.state.summaryInfo?.paymentType == 'Fleet Credit') {
+      return '-';
+    } else {
+      return currency + '' + (data ?? '0');
+    }
+  }
+
+  getTaxTitle(title="") {
+    if (this.state.summaryInfo?.taxRate) {
+      return title.replace("$s", this.state.summaryInfo.taxRate)
+    } else {
+      return title;
+    }
+  }
+
+  isLoading(precond) {
+    return utils.isNotEmpty(precond) || this.state.loading;
+  }
+
+  getSkeletonLeft(size=3) {
+    const list = [];
+    for (let i = 0; i < size; i++) {
+      list.push({width: i % 2 ==0 ? '100%' : '70%', height: 18, marginTop: 4, marginBottom: 4, borderRadius: 3});
+    }
+    return list;
+  }
+
+  getSkeletonRight(size=3) {
+    const list = [];
+    for (let i = 0; i < size; i++) {
+      list.push({width: '100%', height: 18, marginTop: 4, marginBottom: 4, borderRadius: 3});
+    }
+    return list;
+  }
+
+  getSectionSkeleton(size) {
+    if (this.state.loading) {
+      return (
+        <View style={[styles.sections, ui.flexc]}>
+          <Skeleton
+            containerStyle={ui.flex2}
+            isLoading={this.state.loading}
+            boneColor='#eeeeee'
+            highlightColor='#f6f6f6'
+            animationType="shiver"
+            layout={this.getSkeletonLeft(size)}
+            animationDirection={'horizontalRight'}>
+            
+          </Skeleton>
+          <View style={ui.flex2}></View>
+          <Skeleton
+            containerStyle={ui.flex1}
+            isLoading={this.state.loading}
+            boneColor='#eeeeee'
+            highlightColor='#f6f6f6'
+            animationType="shiver"
+            layout={this.getSkeletonRight(size)}
+            animationDirection={'horizontalRight'}>
+            
+          </Skeleton>
+        </View>
+      )
+    } else {
+      return <></>
+    }
+  }
+
+  render() {
+    if (this.state.isPendding) {
+      return (
+        <View style={styles.container}>
+          <View style={styles.processContent}>
+            <TextView style={styles.processTitle}>{$t("receipt.processTitle")}</TextView>
+            <TextView style={styles.processText}>{$t("receipt.processMessage1")}</TextView>
+            <TextView style={styles.processText}>
+              {$t("receipt.processMessage2")}
+              <Text style={[ui.bold, ui.underline]} onPress={() => this.toTransaction()}>{$t("receipt.processMessage3")}</Text>.
+            </TextView>
+            <TextView style={styles.processText}>{$t("receipt.processMessage4")}</TextView>
+          </View>
+          <View style={styles.bottomButton}>
+            <Button
+              text={$t('home.done')}
+              elevation={1.5}
+              onClick={() => this.toRating()}/>
+          </View>
+        </View>
+      )
+    } else {
+      return (
+        <ScrollView
+          style={styles.container}
+          refreshControl={
+            <RefreshControl
+              {...MyRefreshProps()}
+              refreshing={this.state.refreshing}
+              onRefresh={() => this.onRefresh()}
+            />
+          }>
+          { this.isLoading(this.state.summaryInfo.top) &&
+            <View style={styles.headerView}>
+              { this.state.isActully && <>
+                <Skeleton
+                  isLoading={this.state.loading}
+                  boneColor='#eeeeee'
+                  highlightColor='#f6f6f6'
+                  animationType="shiver"
+                  layout={[{width: 56, height: 56, borderRadius: 56}]}
+                  animationDirection={'horizontalRight'}>
+                  <Octicons
+                    name="check-circle-fill"
+                    color={colorAccent}
+                    size={56}/>
+                </Skeleton>
+                <Skeleton
+                  isLoading={this.state.loading}
+                  boneColor='#eeeeee'
+                  highlightColor='#f6f6f6'
+                  animationType="shiver"
+                  layout={[{width: 60, height: 20, marginTop: 8, borderRadius: 3}]}
+                  animationDirection={'horizontalRight'}>
+                  <TextView style={styles.topTitle}>{$t('receipt.successful')}</TextView>
+                </Skeleton>
+                <Skeleton
+                  isLoading={this.state.loading}
+                  boneColor='#eeeeee'
+                  highlightColor='#f6f6f6'
+                  animationType="shiver"
+                  layout={[{width: 100, height: 18, marginTop: 4, marginBottom: 32, borderRadius: 3}]}
+                  animationDirection={'horizontalRight'}>
+                  <TextView style={styles.topDesc}>{$t('receipt.chargingSessionComplete')}</TextView>
+                </Skeleton>
+              </>}
+              { utils.isNotEmpty(this.state.summaryInfo.top.company) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{$t('sign.labelCompany')}:</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.top.company}</TextView>
+                </View>
+              }
+              { utils.isNotEmpty(this.state.summaryInfo.top.registrationNo) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{$t('receipt.labelRegistrationNo')}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.top.registrationNo}</TextView>
+                </View>
+              }
+              <View style={styles.formRow}>
+                <Skeleton
+                  containerStyle={ui.flex1}
+                  isLoading={this.state.loading}
+                  boneColor='#eeeeee'
+                  highlightColor='#f6f6f6'
+                  animationType="shiver"
+                  layout={this.getSkeletonLeft()}
+                  animationDirection={'horizontalRight'}>
+                  
+                </Skeleton>
+                <View style={ui.flex2}></View>
+                <Skeleton
+                  containerStyle={ui.flex1}
+                  isLoading={this.state.loading}
+                  boneColor='#eeeeee'
+                  highlightColor='#f6f6f6'
+                  animationType="shiver"
+                  layout={this.getSkeletonRight()}
+                  animationDirection={'horizontalRight'}>
+                  
+                </Skeleton>
+              </View>
+              { utils.isNotEmpty(this.state.summaryInfo.top.transactionId) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{$t('receipt.labelTransactionID')}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.top.transactionId}</TextView>
+                </View>
+              }
+              { utils.isNotEmpty(this.state.summaryInfo.top.referenceId) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{$t('receipt.labelReferenceID')}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.top.referenceId}</TextView>
+                </View>
+              }
+              { utils.isNotEmpty(this.state.summaryInfo.top.dateTime) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{$t('receipt.labelDateTime')}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.top.dateTime}</TextView>
+                </View>
+              }
+            </View>
+          }
+          {this.getSectionSkeleton(2)}
+          { utils.isNotEmpty(this.state.summaryInfo.station) &&
+            <View style={styles.sections}>
+              <TextView style={styles.formTitle}>{$t('wallet.labelYourStation')}</TextView>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('wallet.labelStationId')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.station.stationId}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('receipt.labelSiteName')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.station.siteName ?? "-"}</TextView>
+              </View>
+            </View>
+          }
+          {this.getSectionSkeleton()}
+          { utils.isNotEmpty(this.state.summaryInfo.connector) &&
+            <View style={styles.sections}>
+              <TextView style={styles.formTitle}>{$t('wallet.labelYourConnector')}</TextView>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('charging.labelType')}:</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.connector.type}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('charging.labelPower')}:</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.connector.power}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('charging.labelRates')}:</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.connector.rates}</TextView>
+              </View>
+            </View>
+          }
+          {this.getSectionSkeleton(1)}
+          { utils.isNotEmpty(this.state.summaryInfo.payment?.pointsReward) &&
+            <View style={styles.sections}>
+              <TextView style={styles.formTitle}>{$t('receipt.labelPointsRewards')}</TextView>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('receipt.labelPointsRewarded')}:</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.payment.pointsReward + " " + $t('points.points')}</TextView>
+              </View>
+            </View>
+          }
+          {this.getSectionSkeleton(1)}
+          { utils.isNotEmpty(this.state.summaryInfo.vouchers) &&
+            <View style={styles.sections}>
+              <TextView style={styles.formTitle}>{$t('receipt.labelVoucherUsage')}</TextView>
+              { this.state.summaryInfo.vouchers?.map((item, index) => (
+                <View style={styles.formRow} key={index}>
+                  <View style={ui.flex1}>
+                    <TextView style={styles.label}>{item.voucherName}</TextView>
+                    <TextView style={styles.voucherDesc}>{item.voucherDesc}</TextView>
+                  </View>
+                  <TextView style={styles.text}>{"(" + item.voucherCurrencySymbol + " " + item.voucherCredit + ")"}</TextView>
+                </View>)
+              )}
+            </View>
+          }
+          {this.getSectionSkeleton()}
+          { utils.isNotEmpty(this.state.summaryInfo.chargingFee) &&
+            <View style={styles.sections}>
+              <TextView style={styles.formTitle}>{$t('receipt.breakdownChargingFees')}</TextView>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('wallet.labelChargeTime')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.chargingFee.chargeTime ?? "-"}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('wallet.labelChargeDelivered')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.chargingFee.chargeDelivered ?? 0}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('receipt.labelChargTransSubtotal3')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.chargingFee.transactionSubtotal}</TextView>
+              </View>
+            </View>
+          }
+          {this.getSectionSkeleton()}
+          { utils.isNotEmpty(this.state.summaryInfo.idleFee) &&
+            <View style={styles.sections}>
+              <TextView style={styles.formTitle}>{$t('receipt.breakdownIdlesFees')}</TextView>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('receipt.labelIdleStartTime')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.idleFee.startTime}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('receipt.labelIdleDuration')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.idleFee.duration}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('receipt.labelIdleFeeSubtotal3')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.idleFee.subtotal}</TextView>
+              </View>
+            </View>
+          }
+          {this.getSectionSkeleton()}
+          { utils.isNotEmpty(this.state.summaryInfo.reservationFee) &&
+            <View style={styles.sections}>
+              <TextView style={styles.formTitle}>{$t('receipt.breakdownReservationFees')}</TextView>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('receipt.labelTimeReservation')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.reservationFee.reservationTime}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('receipt.labelDurationReservation')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.reservationFee.reservationDuration}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('receipt.labelReservationFeeSubtotal3')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.reservationFee.reservationFeeSubtotal}</TextView>
+              </View>
+            </View>
+          }
+          {this.getSectionSkeleton(8)}
+          { utils.isNotEmpty(this.state.summaryInfo.payment) &&
+            <View style={styles.sections}>
+              <TextView style={styles.formTitle}>{$t('receipt.breakdownPayment')}</TextView>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('wallet.labelPaymentMadeBy')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.payment.paymentMadeBy ?? "-"}</TextView>
+              </View>
+              { utils.isNotEmpty(this.state.summaryInfo.payment.transactionSubtotal) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{$t('receipt.labelChargTransSubtotal3')}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.payment.transactionSubtotal}</TextView>
+                </View>
+              }
+              { utils.isNotEmpty(this.state.summaryInfo.payment.idleFeeSubtotal) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{$t('receipt.labelIdleFeeSubtotal3')}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.payment.idleFeeSubtotal}</TextView>
+                </View>
+              }
+              { utils.isNotEmpty(this.state.summaryInfo.payment.reservationFeeSubtotal) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{$t('receipt.labelReservationFeeSubtotal3')}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.payment.reservationFeeSubtotal}</TextView>
+                </View>
+              }
+              { utils.isNotEmpty(this.state.summaryInfo.payment.finalPayment) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>
+                    { utils.isNotEmpty(this.state.summaryInfo.payment.discountCredit)
+                    ? $t('receipt.labelAfterDiscount')
+                    : $t('receipt.labelFinalPaymentAmount')
+                    }
+                  </TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.payment.finalPayment ?? "-"}</TextView>
+                </View>
+              }
+              { utils.isNotEmpty(this.state.summaryInfo.payment.exchangeRate) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{$t('wallet.labelExchangeRate')}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.payment.exchangeRate ?? "-"}</TextView>
+                </View>
+              }
+              { utils.isNotEmpty(this.state.summaryInfo.payment.resultingBalance) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{$t('wallet.labelResultingBalance')}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.payment.resultingBalance ?? "-"}</TextView>
+                </View>
+              }
+              { utils.isNotEmpty(this.state.summaryInfo.payment.refundAmount) &&
+                <View style={styles.formRow}>
+                  <TextView style={styles.label}>{$t('wallet.labelRefundAmount')}</TextView>
+                  <TextView style={styles.text}>{this.state.summaryInfo.payment.refundAmount ?? "-"}</TextView>
+                </View>
+              }
+            </View>
+          }
+          <EndView/>
+          { (this.state.isActully && utils.isNotEmpty(this.state.summaryInfo.top)) &&
+            <View style={styles.bottomButton}>
+              <TextView
+                style={styles.feedback}
+                onPress={() => startPage(PageList.feedback)}>{$t('wallet.linkSubmitFeedback')}</TextView>
+              {/* <Text style={styles.tipText}>{$t('wallet.tipsReceipt')}</Text> */}
+              <Button
+                text={$t('home.done')}
+                elevation={1.5}
+                onClick={() => this.toRating()}/>
+            </View>
+          }
+        </ScrollView>
+      );
+    }
+  }
+}
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    paddingLeft: 16,
+    paddingRight: 16,
+    backgroundColor: colorLight
+  },
+  headerView: {
+    alignItems: 'center',
+    paddingTop: 16,
+    paddingBottom: 24
+  },
+  topTitle: {
+    color: textPrimary,
+    fontSize: 16,
+    paddingTop: 8,
+    paddingLeft: 8,
+    fontWeight: 'bold'
+  },
+  topDesc: {
+    color: textPrimary,
+    fontSize: 14,
+    marginBottom: 32
+  },
+  sections: {
+    borderRadius: 10,
+    marginBottom: 12,
+    backgroundColor: colorLight
+  },
+  sections2: {
+    paddingTop: 0,
+    paddingLeft: 0,
+    paddingRight: 0,
+    paddingBottom: 8,
+    borderRadius: 10,
+    marginBottom: 8,
+    backgroundColor: colorLight
+  },
+  formTitle: {
+    color: '#000',
+    fontSize: 14,
+    marginTop: -4,
+    marginBottom: 6,
+    paddingBottom: 6,
+    fontWeight: 'bold',
+    borderBottomWidth: 1,
+    borderBottomColor: textPrimary
+  },
+  formRow: {
+    paddingTop: 3,
+    paddingBottom: 3,
+    alignItems: 'center',
+    flexDirection: 'row'
+  },
+  label: {
+    flex: 1,
+    color: textPrimary,
+    fontSize: 13,
+  },
+  text: {
+    color: textPrimary,
+    fontSize: 12,
+    fontWeight: 'bold'
+  },
+  stationInfoView: {
+    padding: 12,
+    marginBottom: 0,
+    alignItems: 'center',
+    flexDirection: 'row',
+    justifyContent: 'space-between'
+  },
+  stationInfoText: {
+    color: '#999',
+    fontSize: 11
+  },
+  connectorView: {
+    alignItems: 'center',
+    flexDirection: 'row'
+  },
+  typeIcon: {
+    width: 36,
+    height: 36
+  },
+  feedback: {
+    color: '#12A5F9',
+    fontSize: 14,
+    textAlign: 'center',
+    marginBottom: 16,
+    ...ui.underline
+  },
+  bottomButton: {
+    marginTop: 16,
+    marginBottom: 16
+  },
+  tipText: {
+    color: textPrimary,
+    fontSize: 12,
+    textAlign: 'center',
+    marginBottom: 8
+  },
+  processContent: {
+    flex: 1,
+    justifyContent: 'center'
+  },
+  processTitle: {
+    color: textTitle,
+    fontSize: 24,
+    fontWeight: 'bold',
+    textAlign: 'center'
+  },
+  processText: {
+    color: textPrimary,
+    fontSize: 14,
+    textAlign: 'center',
+    paddingTop: 16
+  },
+  voucherDesc: {
+    flex: 1,
+    color: textCancel,
+    fontSize: 13
+  }
+});