You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

477 lines
12 KiB

2 months ago
// 余额管理
3 weeks ago
import React, { useState, useCallback, useRef } from "react";
3 weeks ago
import {
View,
Text,
StyleSheet,
Image,
ScrollView,
TouchableOpacity,
Modal,
SafeAreaView,
StatusBar,
Platform,
3 weeks ago
FlatList,
ActivityIndicator,
3 weeks ago
} from "react-native";
3 weeks ago
import { useFocusEffect } from "@react-navigation/native";
3 weeks ago
import fontSize from "../../utils/fontsizeUtils";
import widthUtils from "../../utils/widthUtils";
import { useNavigation } from "@react-navigation/native";
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { RootStackParamList } from "../../navigation/types";
import RechargeScreen from "./RechargeScreen";
import BackIcon from "../../components/BackIcon";
import useUserStore from "../../store/user";
3 weeks ago
import { Transaction, payApi } from "../../services/api/payApi";
3 weeks ago
import { useTranslation } from "react-i18next";
2 months ago
type BalanceScreenNavigationProp = NativeStackNavigationProp<
RootStackParamList,
3 weeks ago
"Balance"
2 months ago
>;
export const BalanceScreen = () => {
3 weeks ago
const { t } = useTranslation();
const { user } = useUserStore();
2 months ago
const navigation = useNavigation<BalanceScreenNavigationProp>();
const [isModalVisible, setIsModalVisible] = useState(false);
3 weeks ago
const [rechargeHistory, setRechargeHistory] = useState<Transaction[]>([]);
const [currentPage, setCurrentPage] = useState(1);
const [loading, setLoading] = useState(false);
const [hasMore, setHasMore] = useState(true);
const pageSize = 10;
2 months ago
const handleOpenModal = () => {
setIsModalVisible(true);
};
const handleCloseModal = () => {
setIsModalVisible(false);
};
3 weeks ago
const fetchRechargeHistory = async (page: number, refresh = false) => {
if (loading || (!hasMore && !refresh)) return;
try {
setLoading(true);
const response = await payApi.getTransactionHistory(page, pageSize);
if (response.items.length < pageSize) {
setHasMore(false);
}
if (refresh) {
setRechargeHistory(response.items);
} else {
setRechargeHistory(prev => [...prev, ...response.items]);
}
setCurrentPage(page);
} catch (error) {
console.error("Failed to fetch transaction history:", error);
} finally {
setLoading(false);
}
};
const handleLoadMore = () => {
if (!loading && hasMore) {
fetchRechargeHistory(currentPage + 1);
}
};
useFocusEffect(
useCallback(() => {
fetchRechargeHistory(1, true);
}, [])
);
const renderTransactionItem = ({ item }: { item: Transaction }) => (
<View style={styles.transactionHistoryList} key={item.transaction_id}>
<View style={styles.transactionDetailsPanel}>
<View style={styles.transactionDetailsRow}>
<Text style={styles.transactionDescriptionBold}>
{item.type}
</Text>
<Text
style={[
styles.transactionAmountDisplay,
{
color:
Number(item.amount) < 0
? "#0035a4"
: "#ff5217",
},
]}
>
{item.amount} {item.currency}
</Text>
</View>
<View style={styles.transactionInfoRow}>
<Text style={styles.transactionDate}>
{item.timestamp}
</Text>
<Text style={styles.shipmentReference}>
{item.type}
</Text>
</View>
</View>
</View>
);
const renderFooter = () => {
if (!loading) return null;
return (
<View style={styles.loaderContainer}>
<ActivityIndicator size="small" color="#FF8000" />
</View>
);
};
2 months ago
return (
<SafeAreaView style={styles.safeArea}>
<StatusBar barStyle="dark-content" backgroundColor="#fff" />
<View style={styles.safeAreaContent}>
<View style={styles.header}>
<TouchableOpacity
style={styles.backButton}
onPress={() => navigation.goBack()}
>
<BackIcon size={fontSize(22)} />
</TouchableOpacity>
3 weeks ago
<Text style={styles.headerTitle}>{t("balance.screen.title")}</Text>
<View style={styles.placeholder} />
</View>
3 weeks ago
3 weeks ago
<View style={styles.container}>
<FlatList
data={rechargeHistory}
renderItem={renderTransactionItem}
keyExtractor={(item) => item.transaction_id.toString()}
onEndReached={handleLoadMore}
onEndReachedThreshold={0.5}
ListFooterComponent={renderFooter}
ListHeaderComponent={() => (
<View style={styles.balanceCard}>
<View style={styles.sunriseGradientContainer}>
<View style={styles.timeContainer}>
<View style={styles.timeContainer2}></View>
2 months ago
</View>
3 weeks ago
<View style={styles.balanceWidget}>
<Text style={styles.balanceText}>
{t("balance.screen.balance_card")}
3 weeks ago
</Text>
3 weeks ago
<Image
source={require("../../../assets/img/image_11d1b9c.png")}
style={styles.balanceImage}
/>
</View>
</View>
<View style={styles.balanceDetailsContainer}>
<View style={styles.totalBalanceCard}>
<View style={styles.cardContainer}>
<View style={styles.financialInfoContainer}>
<Text style={styles.largeBlackText}>{user?.balance}</Text>
<View style={styles.svgContainer}></View>
2 months ago
</View>
3 weeks ago
<View style={styles.totalSoldInfoContainer}>
<Text style={styles.totalSoldeText}>
{t("balance.screen.total_balance")} ({user?.currency})
</Text>
2 months ago
</View>
3 weeks ago
</View>
<View
style={[
styles.buttonContainer,
{ backgroundColor: "#FF8000", alignSelf: "center" },
]}
>
<TouchableOpacity
style={styles.button}
onPress={handleOpenModal}
>
<Text style={styles.buttonText}>
{t("balance.screen.recharge_now")}
</Text>
</TouchableOpacity>
</View>
2 months ago
</View>
3 weeks ago
3 weeks ago
<View style={styles.transactionDetailsContainer}>
<View style={styles.balanceDetailContainer}>
<Text style={styles.balanceDetailTitle}>
{t("balance.screen.balance_detail")}
</Text>
</View>
2 months ago
</View>
</View>
</View>
3 weeks ago
)}
/>
</View>
3 weeks ago
<Modal
animationType="slide"
transparent={true}
visible={isModalVisible}
onRequestClose={handleCloseModal}
>
<View style={styles.modalContainer}>
<View style={styles.modalContent}>
<RechargeScreen onClose={handleCloseModal} />
</View>
2 months ago
</View>
</Modal>
</View>
</SafeAreaView>
2 months ago
);
};
const styles = StyleSheet.create({
safeArea: {
flex: 1,
3 weeks ago
backgroundColor: "#fff",
},
safeAreaContent: {
flex: 1,
paddingTop: 0,
},
2 months ago
container: {
flex: 1,
3 weeks ago
backgroundColor: "#f0f0f0",
2 months ago
},
header: {
3 weeks ago
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
paddingHorizontal: 15,
paddingVertical: 10,
3 weeks ago
backgroundColor: "white",
2 months ago
borderBottomWidth: 1,
3 weeks ago
borderBottomColor: "#f0f0f0",
2 months ago
},
backButton: {
padding: 5,
},
headerTitle: {
2 months ago
fontSize: fontSize(18),
3 weeks ago
fontWeight: "600",
textAlign: "center",
},
placeholder: {
width: widthUtils(24, 24).width,
2 months ago
},
balanceCard: {
3 weeks ago
display: "flex",
flexDirection: "column",
width: "100%",
backgroundColor: "#f0f0f0",
2 months ago
},
sunriseGradientContainer: {
3 weeks ago
backgroundColor:
"linear-gradient(180deg, rgba(255, 119, 0, 1) 0%, rgba(255, 77, 0, 1) 100%)",
flexDirection: "column",
alignItems: "stretch",
2 months ago
},
timeContainer: {
height: widthUtils(43, 43).height,
paddingTop: 21,
},
timeContainer2: {
3 weeks ago
flexDirection: "row",
justifyContent: "space-between",
2 months ago
},
timeContainer1: {
3 weeks ago
flexDirection: "row",
justifyContent: "center",
2 months ago
},
timeDisplay: {
fontSize: fontSize(17),
3 weeks ago
fontWeight: "bold",
color: "white",
2 months ago
},
timeIndicatorContainer: {
width: widthUtils(10, 124).width,
height: widthUtils(10, 124).height,
},
timeDisplayContainer: {
3 weeks ago
width: widthUtils(13, 153).width,
height: widthUtils(13, 153).height,
2 months ago
},
balanceWidget: {
3 weeks ago
flexDirection: "row",
justifyContent: "space-between",
2 months ago
padding: 9,
},
balanceText: {
fontSize: fontSize(32),
3 weeks ago
fontWeight: "bold",
color: "white",
2 months ago
},
balanceImage: {
width: widthUtils(139, 139).width,
height: widthUtils(139, 139).height,
},
balanceDetailsContainer: {
marginTop: -53,
3 weeks ago
flexDirection: "column",
2 months ago
},
totalBalanceCard: {
paddingLeft: 20,
paddingRight: 20,
paddingTop: 20,
},
cardContainer: {
3 weeks ago
backgroundColor: "white",
2 months ago
borderRadius: 10,
padding: 20,
3 weeks ago
shadowColor: "rgba(186, 186, 186, 0.25)",
2 months ago
shadowOffset: { width: 2, height: 4 },
shadowOpacity: 0.7,
},
financialInfoContainer: {
3 weeks ago
flexDirection: "row",
justifyContent: "space-between",
2 months ago
},
largeBlackText: {
fontSize: fontSize(36),
3 weeks ago
fontWeight: "bold",
color: "black",
2 months ago
},
svgContainer: {
width: widthUtils(24, 24).width,
height: widthUtils(24, 24).height,
3 weeks ago
color: "#019847",
2 months ago
},
totalSoldInfoContainer: {
marginTop: 7,
},
totalSoldeText: {
fontSize: fontSize(14),
3 weeks ago
color: "#7c7c7c",
2 months ago
},
totalBalanceInfoContainer: {
3 weeks ago
flexDirection: "row",
justifyContent: "space-between",
2 months ago
marginTop: 22,
},
verticalCenteredTextBox: {
3 weeks ago
flexDirection: "column",
justifyContent: "center",
width: "54.21%",
2 months ago
},
highlightedText: {
fontSize: fontSize(20),
3 weeks ago
fontWeight: "bold",
color: "#fe1e00",
2 months ago
},
expirationInfo: {
fontSize: fontSize(14),
3 weeks ago
color: "#7c7c7c",
2 months ago
},
deadlineInfoContainer: {
3 weeks ago
flexDirection: "column",
justifyContent: "center",
width: "45.79%",
2 months ago
},
deadlineText: {
fontSize: fontSize(20),
3 weeks ago
fontWeight: "bold",
color: "black",
2 months ago
},
transactionDetailsContainer: {
paddingLeft: 20,
paddingRight: 20,
paddingBottom: 20,
},
balanceDetailContainer: {
marginTop: 37,
},
balanceDetailTitle: {
fontSize: fontSize(20),
3 weeks ago
fontWeight: "bold",
color: "black",
2 months ago
marginBottom: 10,
},
transactionDetailsContainer1: {
3 weeks ago
flexDirection: "column",
2 months ago
},
transactionHistoryList: {
3 weeks ago
flexDirection: "column",
2 months ago
},
transactionDetailsPanel: {
3 weeks ago
flexDirection: "column",
2 months ago
padding: 15.5,
borderBottomWidth: 1,
3 weeks ago
borderBottomColor: "#dddddd",
borderStyle: "dashed",
backgroundColor: "#FFFFFF",
2 months ago
},
transactionDetailsRow: {
3 weeks ago
flexDirection: "row",
justifyContent: "space-between",
2 months ago
},
transactionDescriptionBold: {
fontSize: fontSize(15),
3 weeks ago
fontWeight: "bold",
color: "black",
2 months ago
},
transactionAmountDisplay: {
fontSize: fontSize(24),
3 weeks ago
fontWeight: "bold",
2 months ago
},
transactionInfoRow: {
3 weeks ago
flexDirection: "row",
justifyContent: "space-between",
2 months ago
marginTop: 7,
},
transactionDate: {
fontSize: fontSize(13),
3 weeks ago
color: "#7f7e7e",
2 months ago
},
shipmentReference: {
fontSize: fontSize(13),
3 weeks ago
color: "#353029",
2 months ago
},
buttonContainer: {
borderRadius: 25,
width: widthUtils(50, 300).width,
height: widthUtils(50, 300).height,
3 weeks ago
justifyContent: "center",
alignItems: "center",
2 months ago
marginTop: 30,
},
button: {
3 weeks ago
width: "100%",
height: "100%",
justifyContent: "center",
alignItems: "center",
2 months ago
borderRadius: 25,
},
buttonText: {
fontSize: fontSize(16),
3 weeks ago
fontWeight: "600",
color: "white",
textAlign: "center",
2 months ago
},
modalContainer: {
flex: 1,
3 weeks ago
backgroundColor: "rgba(0, 0, 0, 0.5)",
justifyContent: "flex-end",
2 months ago
},
modalContent: {
3 weeks ago
height: "90%",
backgroundColor: "#FFFFFF",
2 months ago
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
},
3 weeks ago
loaderContainer: {
paddingVertical: 20,
alignItems: 'center',
justifyContent: 'center',
},
2 months ago
});