|
@@ -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'
|
|
|
|
|
+ }
|
|
|
|
|
+})
|