|
|
@@ -0,0 +1,359 @@
|
|
|
+/**
|
|
|
+ * 新版支付方式选择器
|
|
|
+ * @邠心vbe on 2021/04/13
|
|
|
+ */
|
|
|
+import React, { Component } from 'react';
|
|
|
+import { View, StyleSheet, Pressable, ScrollView } from 'react-native';
|
|
|
+import BottomModal from '../../components/BottomModal';
|
|
|
+import BadgeSelectItem from '../../components/BadgeSelectItem';
|
|
|
+import { ChargeStyle } from './Charging';
|
|
|
+import { PAYTYPE, PaymentIcon } from '../payment/PaymentConfig';
|
|
|
+import Skeleton from "react-native-reanimated-skeleton";
|
|
|
+import TextView from '../../components/TextView';
|
|
|
+import apiCharge from '../../api/apiCharge';
|
|
|
+import Button from '../../components/Button';
|
|
|
+import Dialog from '../../components/Dialog';
|
|
|
+import app from '../../../app.json';
|
|
|
+import utils from '../../utils/utils';
|
|
|
+import VbeSkeleton from '../../components/VbeSkeleton';
|
|
|
+
|
|
|
+export default class PaymentListV2 extends Component {
|
|
|
+ constructor(props) {
|
|
|
+ super(props);
|
|
|
+ this.state = {
|
|
|
+ visible: false,
|
|
|
+ isSelect: true,
|
|
|
+ options: [],
|
|
|
+ selectIndex: 0,
|
|
|
+ selectOptions: {},
|
|
|
+ isloading: true,
|
|
|
+ delayTimes: 1738080000000
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ componentDidMount() {
|
|
|
+ this.getPaymentOptions();
|
|
|
+ this.setState({
|
|
|
+ isSelect: (this.props.isSelect || true)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ componentDidUpdate() {
|
|
|
+ if (this.props.isSelect != undefined && this.state.isSelect !== this.props.isSelect) {
|
|
|
+ this.setState({
|
|
|
+ isSelect: this.props.isSelect
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ getPaymentOptions() {
|
|
|
+ if (utils.isEmpty(this.props.chargeBoxId)) {
|
|
|
+ setTimeout(() => {
|
|
|
+ this.getPaymentOptions();
|
|
|
+ }, 1000);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ apiCharge.getPaymentTypeOptions({
|
|
|
+ chargeBoxId: this.props.chargeBoxId
|
|
|
+ }).then(res => {
|
|
|
+ if (utils.isNotEmpty(res.data)) {
|
|
|
+ if (this.props.payType && this.props.payType.code) {
|
|
|
+ this.setState({
|
|
|
+ options: res.data,
|
|
|
+ isloading: false
|
|
|
+ }, () => {
|
|
|
+ for (let i = 0; i < res.data.length; i++) {
|
|
|
+ let type = res.data[i];
|
|
|
+ if (type.code == this.props.payType.code) {
|
|
|
+ this.changeMethod(i);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ let time = new Date().getTime();
|
|
|
+ if (time > this.state.delayTimes) {
|
|
|
+ this.setDataToChargEco(res.data);
|
|
|
+ } else {
|
|
|
+ this.setDataToDefault(res.data);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }).catch(err => {
|
|
|
+
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ setDataToDefault(list) {
|
|
|
+ let index = 0;
|
|
|
+ for (let i = 0; i < list.length; i++) {
|
|
|
+ let type = list[i];
|
|
|
+ if (type.def) {
|
|
|
+ index = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.setState({
|
|
|
+ options: list,
|
|
|
+ isloading: false
|
|
|
+ }, () => {
|
|
|
+ this.changeMethod(index);
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ setDataToChargEco(list) {
|
|
|
+ let index = 0;
|
|
|
+ let hasDef = false;
|
|
|
+ for (let i = 0; i < list.length; i++) {
|
|
|
+ let type = list[i];
|
|
|
+ if (type.code == "fleet_group_wallet" || type.code == "fleet_individual_wallet") {
|
|
|
+ index = i;
|
|
|
+ type.def = true;
|
|
|
+ hasDef = true;
|
|
|
+ } else {
|
|
|
+ type.def = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!hasDef) {
|
|
|
+ for (let i = 0; i < list.length; i++) {
|
|
|
+ let type = list[i];
|
|
|
+ if (type.def) {
|
|
|
+ index = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.setState({
|
|
|
+ options: list,
|
|
|
+ isloading: false
|
|
|
+ }, () => {
|
|
|
+ this.changeMethod(index);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ showDialog(visible) {
|
|
|
+ if (this.state.isSelect) {
|
|
|
+ this.setState({
|
|
|
+ visible: visible
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ changeMethod(index) {
|
|
|
+ const type = this.state.options[index];
|
|
|
+ this.setState({
|
|
|
+ selectIndex: index,
|
|
|
+ selectOptions: type
|
|
|
+ }, () => {
|
|
|
+ if (this.props.onMethodChange) {
|
|
|
+ this.props.onMethodChange(this.state.selectOptions);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ setDefault() {
|
|
|
+ const code = this.state.selectOptions?.code;
|
|
|
+ if (code && !this.state.selectOptions.def) {
|
|
|
+ Dialog.showProgressDialog();
|
|
|
+ apiCharge.setDefaultPaymentType({
|
|
|
+ defaultPaymentMethod: code
|
|
|
+ }).then(res => {
|
|
|
+ toastShort("success");
|
|
|
+ this.getPaymentOptions();
|
|
|
+ }).catch(err => {
|
|
|
+ toastShort(err)
|
|
|
+ }).finally(() => {
|
|
|
+ Dialog.dismissLoading();
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ render() {
|
|
|
+ return (
|
|
|
+ <View>
|
|
|
+ <BadgeSelectItem
|
|
|
+ style={this.props.style ?? ChargeStyle.stationInfoView}
|
|
|
+ borderColor={this.props.borderColor}
|
|
|
+ checked={false}
|
|
|
+ onPress={() => this.showDialog(true)}>
|
|
|
+ { app.charge.version >= 4
|
|
|
+ ? <MaterialIcons
|
|
|
+ name="wallet"
|
|
|
+ size={32}
|
|
|
+ color={textPrimary}/>
|
|
|
+ : <PaymentIcon
|
|
|
+ method={"WALLET"}
|
|
|
+ checked={true}
|
|
|
+ size={35}/>
|
|
|
+ }
|
|
|
+ { (this.state.isSelect && this.state.options.length > 1) &&
|
|
|
+ <TextView style={styles.numberDot}>{this.state.options.length}</TextView>
|
|
|
+ }
|
|
|
+ <View style={styles.paymentView}>
|
|
|
+ { this.state.isloading
|
|
|
+ ? <VbeSkeleton
|
|
|
+ style={ui.flex1}
|
|
|
+ viewStyle={ui.flexc}
|
|
|
+ isLoading={this.state.isloading}
|
|
|
+ animationType="pulse"
|
|
|
+ layout={[{width: '60%', height: 20, marginLeft: 10}]}
|
|
|
+ animationDirection={"horizontalRight"}/>
|
|
|
+ : <TextView
|
|
|
+ style={styles.valueText}
|
|
|
+ ellipsizeMode="middle"
|
|
|
+ numberOfLines={1}>{this.state.selectOptions?.name}</TextView>
|
|
|
+ }
|
|
|
+ { this.state.isloading
|
|
|
+ ? <VbeSkeleton
|
|
|
+ style={ui.flex1}
|
|
|
+ viewStyle={ui.flexc}
|
|
|
+ isLoading={this.state.isloading}
|
|
|
+ animationType="pulse"
|
|
|
+ layout={[{width: '60%', height: 20, marginLeft: 20}]}
|
|
|
+ animationDirection={"horizontalRight"}/>
|
|
|
+ : <TextView
|
|
|
+ style={styles.paymentText}
|
|
|
+ ellipsizeMode="middle"
|
|
|
+ numberOfLines={1}>{this.state.selectOptions?.desc}</TextView>
|
|
|
+ }
|
|
|
+ </View>
|
|
|
+ { this.state.selectOptions?.def &&
|
|
|
+ <TextView style={styles.textDefault}>Default</TextView>
|
|
|
+ }
|
|
|
+ { this.state.isSelect &&
|
|
|
+ <Lucide
|
|
|
+ name={"chevron-right"}
|
|
|
+ size={24}
|
|
|
+ color={colorCancel}
|
|
|
+ />
|
|
|
+ }
|
|
|
+ </BadgeSelectItem>
|
|
|
+ <BottomModal
|
|
|
+ visible={this.state.visible}
|
|
|
+ onHide={() => this.showDialog(false)}>
|
|
|
+ <View style={styles.dialogContent}>
|
|
|
+ <TextView style={styles.titleText}>Payment Methods</TextView>
|
|
|
+ <ScrollView style={styles.paymentList}>
|
|
|
+ { this.state.options.map((item, index) => (
|
|
|
+ <Pressable
|
|
|
+ key={index}
|
|
|
+ style={styles.itemPayment}
|
|
|
+ onPress={() => this.changeMethod(index)}>
|
|
|
+ <View style={ui.flex1}>
|
|
|
+ <TextView style={styles.labelText}>{item.name}</TextView>
|
|
|
+ <TextView style={styles.descText}>{item.desc}</TextView>
|
|
|
+ </View>
|
|
|
+ { item.def &&
|
|
|
+ <TextView style={styles.tagDefault}>Default</TextView>
|
|
|
+ }
|
|
|
+ <MaterialCommunityIcons
|
|
|
+ name={index == this.state.selectIndex ? "radiobox-marked" : "radiobox-blank"}
|
|
|
+ size={24}
|
|
|
+ color={index == this.state.selectIndex ? colorPrimary : textPrimary}
|
|
|
+ />
|
|
|
+ </Pressable>
|
|
|
+ ))
|
|
|
+ }
|
|
|
+ </ScrollView>
|
|
|
+ <EndView/><EndView/>
|
|
|
+ <View style={ui.flexc}>
|
|
|
+ <Button
|
|
|
+ style={styles.defButton}
|
|
|
+ text={"Set Default"}
|
|
|
+ onClick={() => this.setDefault()}/>
|
|
|
+ <EndView half/>
|
|
|
+ <Button
|
|
|
+ style={ui.flex1}
|
|
|
+ text={"Confirm"}
|
|
|
+ onClick={() => this.showDialog(false)}/>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ </BottomModal>
|
|
|
+ </View>
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const styles = StyleSheet.create({
|
|
|
+ paymentView: {
|
|
|
+ flex: 1,
|
|
|
+ flexWrap: 'wrap',
|
|
|
+ alignItems: 'center',
|
|
|
+ flexDirection: 'row',
|
|
|
+ justifyContent: 'space-around'
|
|
|
+ },
|
|
|
+ dialogContent: {
|
|
|
+ padding: 16
|
|
|
+ },
|
|
|
+ paymentList: {
|
|
|
+ height: $vh(50)
|
|
|
+ },
|
|
|
+ titleText: {
|
|
|
+ fontSize: 16,
|
|
|
+ fontWeight: 'bold',
|
|
|
+ paddingBottom: 18
|
|
|
+ },
|
|
|
+ valueText: {
|
|
|
+ flex: 1,
|
|
|
+ color: textPrimary,
|
|
|
+ fontSize: 14,
|
|
|
+ fontWeight: 'bold',
|
|
|
+ paddingLeft: 16
|
|
|
+ },
|
|
|
+ paymentText: {
|
|
|
+ flex: 1,
|
|
|
+ color: textSecondary,
|
|
|
+ fontSize: 12,
|
|
|
+ paddingLeft: 8,
|
|
|
+ paddingRight: 16,
|
|
|
+ textAlign: 'center'
|
|
|
+ },
|
|
|
+ labelText: {
|
|
|
+ color: textPrimary,
|
|
|
+ fontSize: 15,
|
|
|
+ fontWeight: 'bold'
|
|
|
+ },
|
|
|
+ descText: {
|
|
|
+ color: colorAccent,
|
|
|
+ fontSize: 14,
|
|
|
+ paddingTop: 2
|
|
|
+ },
|
|
|
+ itemPayment: {
|
|
|
+ paddingTop: 8,
|
|
|
+ paddingBottom: 8,
|
|
|
+ alignItems: 'center',
|
|
|
+ flexDirection: 'row'
|
|
|
+ },
|
|
|
+ tagDefault: {
|
|
|
+ color: textLight,
|
|
|
+ fontSize: 12,
|
|
|
+ borderRadius: 4,
|
|
|
+ ...$padding(4, 8),
|
|
|
+ marginRight: 12,
|
|
|
+ backgroundColor: colorAccent
|
|
|
+ },
|
|
|
+ textDefault: {
|
|
|
+ color: colorAccent,
|
|
|
+ fontSize: 12,
|
|
|
+ marginRight: 8,
|
|
|
+ fontWeight: 'bold'
|
|
|
+ },
|
|
|
+ defButton: {
|
|
|
+ flex: 1,
|
|
|
+ backgroundColor: colorPrimary
|
|
|
+ },
|
|
|
+ numberDot: {
|
|
|
+ top: 10,
|
|
|
+ left: app.charge.version >= 4 ? 32 : 35,
|
|
|
+ width: 16,
|
|
|
+ height: 16,
|
|
|
+ color: textButton,
|
|
|
+ fontSize: 10,
|
|
|
+ fontWeight: 'bold',
|
|
|
+ borderRadius: 32,
|
|
|
+ position: 'absolute',
|
|
|
+ alignItems: 'center',
|
|
|
+ justifyContent: 'center',
|
|
|
+ backgroundColor: app.charge.version >= 4 ? colorAccent : "#FF2622"
|
|
|
+ }
|
|
|
+})
|