ソースを参照

add app/pages/vouchers/ListPoints.js

wudebin 5 ヶ月 前
コミット
29c8b1148a
1 ファイル変更405 行追加0 行削除
  1. 405 0
      Strides-SPAPP/app/pages/vouchers/ListPoints.js

+ 405 - 0
Strides-SPAPP/app/pages/vouchers/ListPoints.js

@@ -0,0 +1,405 @@
+/**
+ * 购买代金券列表
+ * @邠心vbe on 2024/04/09
+ */
+import React, { Component } from 'react';
+import { View, Text, StyleSheet, RefreshControl, FlatList } from 'react-native';
+import ViewRedeem from './ViewRedeem';
+import apiVoucher from '../../api/apiVoucher';
+import { MyRefreshProps } from '../../components/ThemesConfig';
+import TextView from '../../components/TextView';
+import Button from '../../components/Button';
+import Dialog from '../../components/Dialog';
+import VoucherType from './VoucherType';
+import app from '../../../app.json';
+import VbeSkeleton from '../../components/VbeSkeleton';
+
+export default class ListPoints extends Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      loading: true,
+      userInfo: {},
+      dataList: [],
+      voucherType: "",
+      hasMore: true,
+      refreshing: false,
+      loadingList: ["","","",""]
+    };
+  }
+
+  componentDidMount() {
+    this.props.navigation.addListener('focus', () => {
+      this.refreshUserInfo();
+      this.getDataList();
+    });
+  }
+
+  onRefresh() {
+    this.setState({
+      refreshing: true
+    })
+    this.refreshUserInfo();
+    this.getDataList();
+  }
+
+  refreshUserInfo() {
+    getUserInfo(info => {
+      this.setState({
+        userInfo: info
+      });
+    }, true);
+  }
+
+  getDataList(lastId="") {
+    apiVoucher.getDealVouchers({
+      lastVoucherId: lastId,
+      voucherType: this.state.voucherType
+    }).then(res => {
+      if (res.data) {
+        if (lastId) {
+          if (res.data.length > 0) {
+            const list = this.state.dataList;
+            this.setState({
+              dataList: list.concat(res.data)
+            });
+          } else {
+            this.setState({
+              hasMore: false
+            })
+          }
+        } else {
+          this.setState({
+            dataList: res.data,
+            hasMore: res.data.length >= 10
+          });
+        }
+      } else {
+        this.setState({
+          dataList: []
+        });
+      }
+    }).catch(err => {
+      toastShort(err)
+    }).finally(() => {
+      this.setState({
+        loading: false,
+        refreshing: false
+      });
+    });
+  }
+
+  getDataListPage() {
+    if (this.state.dataList.length > 0 && this.state.hasMore) {
+      const last = this.state.dataList[this.state.dataList.length-1]
+      this.getDataList(last.voucherId);
+    }
+  }
+
+  confirmPurchase(item) {
+    let msg = "" + $t("voucher.confirmPurchase");
+    if (item.purchasePoints) {
+      msg = msg.replace("{value}", item.purchasePoints);
+    } else {
+      msg = msg.replace("{value}", "0");
+    }
+    Dialog.showDialog({
+      title: $t("voucher.purchaseVoucher"),
+      message: msg,
+      ok: $t("nav.confirm"),
+      callback: btn => {
+        if (btn == Dialog.BUTTON_OK) {
+          this.onPurchase(item)
+        }
+      }
+    })
+  }
+
+  onPurchase(item) {
+    Dialog.showProgressDialog();
+    apiVoucher.purchaseVoucher({
+      voucherId: item.voucherId
+    }).then(res => {
+      Dialog.dismissLoading();
+      if (res.msg) {
+        setTimeout(() => {
+          Dialog.showDialog({
+            title: $t("voucher.purchaseVoucher"),
+            message: res.msg,
+            showCancel: false
+          })
+        }, 500);
+      }
+      setTimeout(() => {
+        this.refreshUserInfo();
+      }, 2000)
+    }).catch(err => {
+      Dialog.dismissLoading();
+      if (err.err) {
+        setTimeout(() => {
+          Dialog.showDialog({
+            title: $t("voucher.vouchers"),
+            message: err.err,
+            showCancel: false
+          })
+        }, 500);
+      }
+    })
+  }
+
+  changeType(type) {
+    this.setState({
+      voucherType: type
+    });
+    this.getDataList();
+  }
+
+  listItem = ({item, index, separators}) => {
+    return (
+      <View
+        style={styles.itemView}>
+        <View style={styles.itemBox}></View>
+        <View style={styles.itemContent}>
+          <TextView style={styles.voucherTitle} numberOfLines={1}>{item.voucherName}</TextView>
+          <TextView style={styles.voucherDesc} numberOfLines={2}>{item.voucherDesc}</TextView>
+          <TextView style={styles.expireDate} numberOfLines={1}>{$t("voucher.expiresOn") + item.expiresOn}</TextView>
+          { !app.isLumiWhitelabel && <>
+            <View style={styles.rightDash}></View>
+            <View style={styles.topTikDot}></View>
+            <View style={styles.bottomTikDot}></View>
+          </> }
+        </View>
+        { item.purchasePoints > 0
+        ? <Button
+            viewStyle={styles.purchaseButton}
+            borderRadius={6}
+            onClick={() => this.confirmPurchase(item)}>
+            <TextView
+              style={styles.getForText}>
+              {$t("voucher.btnGetFor")}
+            </TextView>
+            <TextView
+              style={styles.getValueText}>
+              {item.purchasePoints}
+              {$t("voucher.btnPoints")}
+            </TextView>
+          </Button>
+        : <Button
+            style={styles.claimeButton}
+            viewStyle={styles.claimeButtonView}
+            textStyle={styles.claimeButtonText}
+            text={$t("voucher.btnClaimed")}
+            onClick={() => this.onPurchase(item)}/>
+        }
+      </View>
+    )
+  }
+
+  topView = (props) => {
+    return (
+      <View>
+        <ViewRedeem
+          userInfo={this.state.userInfo}/>
+        <VoucherType
+          type={this.state.voucherType}
+          onChange={type => this.changeType(type)}
+        />
+      </View>
+    )
+  }
+
+  bottomView = () => {
+    if (this.state.dataList.length > 0 && !this.state.hasMore) {
+      return (<Text style={styles.noMore}>{$t('voucher.noMore')}</Text>)
+    } else {
+      return null
+    }
+  }
+
+  render() {
+    if (this.state.loading) {
+      return (
+        <View style={styles.container}>
+          <VbeSkeleton
+            style={{}}
+            layout={[
+              {width: '100%', height: 42, borderRadius: 10},
+              {width: '40%', height: 18, marginTop: 16}
+            ]}
+            animationDirection={"horizontalRight"}
+          />
+          <EndView/>
+          { this.state.loadingList.map((item, index) =>
+            <View style={styles.loadingView} key={index}>
+              <VbeSkeleton
+                style={ui.flex1}
+                layout={[
+                  {width: '50%', height: 18},
+                  {width: '90%', height: 12, marginTop: 8},
+                  {width: '40%', height: 12, marginTop: 4}
+                ]}
+                animationDirection={"horizontalRight"}
+              />
+              <VbeSkeleton
+                style={{width: 56}}
+                layout={[
+                  {width: 56, height: 30, borderRadius: 30}
+                ]}
+                animationDirection={"horizontalRight"}
+              />
+            </View>
+          )}
+        </View>
+      )
+    }
+    return (
+      <FlatList
+        style={styles.container}
+        data={this.state.dataList}
+        renderItem={this.listItem}
+        ListHeaderComponent={this.topView}
+        keyExtractor={item => item.voucherId}
+        onEndReached={() => this.getDataListPage()}
+        onEndReachedThreshold={0.3}
+        ListEmptyComponent={<Text style={styles.noData}>{$t('voucher.noData')}</Text>}
+        ListFooterComponent={this.bottomView}
+        refreshControl={
+          <RefreshControl
+            {...MyRefreshProps()}
+            refreshing={this.state.refreshing}
+            onRefresh={() => this.onRefresh()}
+          />
+        }/>
+    );
+  }
+}
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    padding: 16
+  },
+  itemView: {
+    marginTop: 16,
+    borderRadius: 4,
+    alignItems: 'center',
+    flexDirection: 'row',
+    backgroundColor: colorLight,
+    ...$padding(0, 20, 0, 16)
+  },
+  itemBox: {
+    top: 0,
+    left: 0,
+    right: 0,
+    bottom: 0,
+    borderWidth: 1,
+    borderColor: '#DADADA',
+    borderRadius: 4,
+    position: 'absolute'
+  },
+  itemContent: {
+    flex: 1,
+    marginRight: 16,
+    paddingTop: 8,
+    paddingRight: 16,
+    paddingBottom: 8,
+    overflow: 'hidden'
+  },
+  rightDash: {
+    top: 0,
+    right: 6,
+    bottom: 0,
+    position: 'absolute',
+    borderStyle: 'dashed',
+    borderRightWidth: 1,
+    borderRightColor: '#DADADA'
+  },
+  topTikDot: {
+    top: -8,
+    right: 0,
+    width: 13,
+    height: 14,
+    borderWidth: 1,
+    borderColor: '#DADADA',
+    borderRadius: 30,
+    position: 'absolute',
+    backgroundColor: pageBackground
+  },
+  bottomTikDot: {
+    bottom: -8,
+    right: 0,
+    width: 13,
+    height: 14,
+    borderWidth: 1,
+    borderColor: '#DADADA',
+    borderRadius: 30,
+    position: 'absolute',
+    backgroundColor: pageBackground
+  },
+  voucherTitle: {
+    color: textPrimary,
+    fontSize: 16,
+    fontWeight: 'bold'
+  },
+  voucherDesc: {
+    color: textPrimary,
+    fontSize: 12,
+    paddingTop: 2,
+    paddingBottom: 4
+  },
+  expireDate: {
+    color: textCancel,
+    fontSize: 12
+  },
+  purchaseButton: {
+    padding: 4,
+    minWidth: 75,
+    marginRight: 4,
+    alignItems: 'center'
+  },
+  claimeButton: {
+    borderWidth: 1,
+    borderColor: colorAccent,
+    borderRadius: 6,
+    backgroundColor: colorLight
+  },
+  claimeButtonView: {
+    padding: 8,
+    minWidth: 73,
+    alignItems: 'center'
+  },
+  claimeButtonText: {
+    color: colorAccent,
+    fontSize: 12,
+    fontWeight: 'bold'
+  },
+  getForText: {
+    color: textLight,
+    fontSize: 12,
+    fontWeight: 'bold'
+  },
+  getValueText: {
+    color: textLight,
+    fontSize: 10
+  },
+  noData: {
+    color: textPlacehoder,
+    fontSize: 14,
+    padding: 20,
+    marginTop: 16,
+    textAlign: 'center'
+  },
+  noMore: {
+    color: textPlacehoder,
+    fontSize: 14,
+    padding: 16,
+    marginBottom: 16,
+    textAlign: 'center'
+  },
+  loadingView: {
+    paddingTop: 16,
+    paddingBottom: 16,
+    alignItems: 'center',
+    flexDirection: 'row'
+  }
+})