ソースを参照

add app/pages/vouchers/ListVoucher.js

wudebin 5 ヶ月 前
コミット
2d69ca5a6c
1 ファイル変更342 行追加0 行削除
  1. 342 0
      Strides-SPAPP/app/pages/vouchers/ListVoucher.js

+ 342 - 0
Strides-SPAPP/app/pages/vouchers/ListVoucher.js

@@ -0,0 +1,342 @@
+/**
+ * 我的代金券列表
+ * @邠心vbe on 2024/04/09
+ */
+import React, { Component } from 'react';
+import { View, Text, StyleSheet, RefreshControl, FlatList, Pressable } from 'react-native';
+import { MyRefreshProps } from '../../components/ThemesConfig';
+import TextView from '../../components/TextView';
+import ViewRedeem from './ViewRedeem';
+import VoucherType from './VoucherType';
+import apiVoucher from '../../api/apiVoucher';
+import { PageList } from '../Router';
+import app from '../../../app.json';
+import VbeSkeleton from '../../components/VbeSkeleton';
+
+export default class ListVoucher 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.getMyVouchers({
+      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);
+    }
+  }
+
+  getColorByStatus(status) {
+    let color = colorAccent;
+    switch (status) {
+      case "Used":
+      case "Expired":
+        color = "#434343";
+        break;
+      case "Expiring":
+        color = "#ED3F3F"
+        break;
+    }
+    return color;
+  }
+
+  changeType(type) {
+    this.setState({
+      voucherType: type
+    });
+    this.getDataList();
+  }
+
+  toDetailPage(item) {
+    startPage(PageList.voucherDetails, {id: item.voucherId});
+  }
+
+  listItem = ({item, index, separators}) => {
+    return (
+      <Pressable
+        style={styles.itemView}
+        onPress={() => this.toDetailPage(item)}>
+        <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}>{$t("voucher.expiresOn") + item.expiresOn}</TextView>
+          { !app.isLumiWhitelabel && <>
+            <View style={styles.rightDash}></View>
+            <View style={styles.topTikDot}></View>
+            <View style={styles.bottomTikDot}></View>
+          </> }
+        </View>
+        <TextView
+          style={[
+            styles.statusButton, {
+              color: this.getColorByStatus(item.userVoucherStatus),
+              borderColor: this.getColorByStatus(item.userVoucherStatus)
+            }
+          ]}>
+          {item.userVoucherStatus}
+        </TextView>
+      </Pressable>
+    )
+  }
+
+  topView = (props) => {
+    return (
+      <View>
+        <ViewRedeem
+          userInfo={this.state.userInfo}
+          onChange={() => this.onRefresh()}/>
+        <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.userVoucherId}
+        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, 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
+  },
+  statusButton: {
+    color: colorAccent,
+    padding: 5,
+    minWidth: 70,
+    fontSize: 12,
+    marginRight: 4,
+    textAlign: 'center',
+    borderWidth: 1,
+    borderColor: colorAccent,
+    borderRadius: 6,
+    textTransform: 'uppercase',
+    backgroundColor: colorLight
+  },
+  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'
+  }
+})