From 497d9810f83eb6dea4d6080846c58a822d086684 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 22 May 2025 15:35:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=85=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/locales/en/translation.json | 3 + app/locales/fr/translation.json | 3 + app/screens/BalanceScreen/BalanceScreen.tsx | 244 ++++++++++++------- app/screens/BalanceScreen/RechargeScreen.tsx | 5 +- app/screens/previewOrder/PaymentMethod.tsx | 86 ++++--- app/screens/previewOrder/perviewOrder.tsx | 4 +- app/screens/productStatus/OrderDatails.tsx | 10 +- app/services/api/payApi.ts | 23 ++ 8 files changed, 243 insertions(+), 135 deletions(-) diff --git a/app/locales/en/translation.json b/app/locales/en/translation.json index 05829e0..9354432 100644 --- a/app/locales/en/translation.json +++ b/app/locales/en/translation.json @@ -401,5 +401,8 @@ "pay": "PAY", "payment_failed": "Payment failed, please try again" } + }, + "pay":{ + "payment_Insufficient": "Insufficient balance" } } \ No newline at end of file diff --git a/app/locales/fr/translation.json b/app/locales/fr/translation.json index 02790f9..7884191 100644 --- a/app/locales/fr/translation.json +++ b/app/locales/fr/translation.json @@ -397,5 +397,8 @@ "pay": "PAYER", "payment_failed": "Paiement échoué, veuillez réessayer" } + }, + "pay":{ + "payment_Insufficient": "Solde insuffisant" } } \ No newline at end of file diff --git a/app/screens/BalanceScreen/BalanceScreen.tsx b/app/screens/BalanceScreen/BalanceScreen.tsx index 24d4f0e..3fb9039 100644 --- a/app/screens/BalanceScreen/BalanceScreen.tsx +++ b/app/screens/BalanceScreen/BalanceScreen.tsx @@ -1,5 +1,6 @@ // 余额管理 -import React, { useState, useEffect } from "react"; + +import React, { useState, useCallback, useRef } from "react"; import { View, Text, @@ -11,7 +12,11 @@ import { SafeAreaView, StatusBar, Platform, + FlatList, + ActivityIndicator, } from "react-native"; +import { useFocusEffect } from "@react-navigation/native"; + import fontSize from "../../utils/fontsizeUtils"; import widthUtils from "../../utils/widthUtils"; import { useNavigation } from "@react-navigation/native"; @@ -20,7 +25,7 @@ import { RootStackParamList } from "../../navigation/types"; import RechargeScreen from "./RechargeScreen"; import BackIcon from "../../components/BackIcon"; import useUserStore from "../../store/user"; -import { rechargeHistory, payApi } from "../../services/api/payApi"; +import { Transaction, payApi } from "../../services/api/payApi"; import { useTranslation } from "react-i18next"; type BalanceScreenNavigationProp = NativeStackNavigationProp< @@ -33,7 +38,11 @@ export const BalanceScreen = () => { const { user } = useUserStore(); const navigation = useNavigation(); const [isModalVisible, setIsModalVisible] = useState(false); - const [rechargeHistory, setRechargeHistory] = useState([]); + const [rechargeHistory, setRechargeHistory] = useState([]); + const [currentPage, setCurrentPage] = useState(1); + const [loading, setLoading] = useState(false); + const [hasMore, setHasMore] = useState(true); + const pageSize = 10; const handleOpenModal = () => { setIsModalVisible(true); @@ -43,13 +52,84 @@ export const BalanceScreen = () => { setIsModalVisible(false); }; - useEffect(() => { - const fetchRechargeHistory = async () => { - const response = await payApi.getRechargeHistory(); - setRechargeHistory(response); - }; - fetchRechargeHistory(); - }, []); + 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 }) => ( + + + + + {item.type} + + + {item.amount} {item.currency} + + + + + {item.timestamp} + + + {item.type} + + + + + ); + + const renderFooter = () => { + if (!loading) return null; + return ( + + + + ); + }; return ( @@ -62,98 +142,76 @@ export const BalanceScreen = () => { > - {t('balance.screen.title')} + {t("balance.screen.title")} - - - - - - - - {t('balance.screen.balance_card')} - - - - - - - - {user?.balance} - + + item.transaction_id.toString()} + onEndReached={handleLoadMore} + onEndReachedThreshold={0.5} + ListFooterComponent={renderFooter} + ListHeaderComponent={() => ( + + + + - - - {t('balance.screen.total_balance')} ({user?.currency}) + + + {t("balance.screen.balance_card")} - {/* - - 50,000 - - Bientôt expiré (FCFA) - + + + + + + + + {user?.balance} + - - 2025-05-09 - Date limite + + + {t("balance.screen.total_balance")} ({user?.currency}) + - */} + + + + + {t("balance.screen.recharge_now")} + + + - - - - {t('balance.screen.recharge_now')} - - - - - - {t('balance.screen.balance_detail')} - - {rechargeHistory.map((item) => ( - - {/* Repeated Transaction Details */} - - - - {item.payment_method} - - - {item.amount} {item.currency} - - - - - {item.create_time} - - - {item.transaction_id} - - - - {/* Additional transaction panels can be added here */} - - ))} + + + + {t("balance.screen.balance_detail")} + + - - - + )} + /> + { }); payApi.getCountryPaymentMethods().then((res) => { - setPaymentMethods(res.current_country_methods); + const currentCountryMethods = res.current_country_methods.filter( + (method) => method.key !== "balance" + ); + setPaymentMethods(currentCountryMethods); }); }, []); diff --git a/app/screens/previewOrder/PaymentMethod.tsx b/app/screens/previewOrder/PaymentMethod.tsx index 15b58f6..fa1214c 100644 --- a/app/screens/previewOrder/PaymentMethod.tsx +++ b/app/screens/previewOrder/PaymentMethod.tsx @@ -97,6 +97,8 @@ const PaymentMethodItem = ({ isPaypalExpanded?: boolean; }) => { const { t } = useTranslation(); + const { user } = useUserStore(); + return ( @@ -111,8 +113,8 @@ const PaymentMethodItem = ({ {t("balance.recharge.balance_remaining") || "Balance remaining"} {"\n"} - {useUserStore().user.balance} - {useUserStore().user.currency} + {user.balance} + {user.currency} ) : ( @@ -458,7 +460,7 @@ export const PaymentMethod = () => { createOrderData.items = items; createOrderData.payment_method = selectedPayment; createOrderData.total_amount = - selectedPayment === "Paypal" + selectedPayment === "paypal" ? convertedAmount.reduce( (acc, item) => acc + item.converted_amount, 0 @@ -471,7 +473,7 @@ export const PaymentMethod = () => { ).toFixed(2) ); createOrderData.actual_amount = - selectedPayment === "Paypal" + selectedPayment === "paypal" ? convertedAmount.reduce( (acc, item) => acc + item.converted_amount, 0 @@ -484,15 +486,15 @@ export const PaymentMethod = () => { ).toFixed(2) ); createOrderData.currency = - selectedPayment === "Paypal" ? selectedCurrency : user.currency; + selectedPayment === "paypal" ? selectedCurrency : user.currency; createOrderData.domestic_shipping_fee = - selectedPayment === "Paypal" + selectedPayment === "paypal" ? convertedAmount.find( (item) => item.item_key === "domestic_shipping_fee" )?.converted_amount || 0 : orderData?.domestic_shipping_fee; createOrderData.shipping_fee = - selectedPayment === "Paypal" + selectedPayment === "paypal" ? convertedAmount.find((item) => item.item_key === "shipping_fee") ?.converted_amount || 0 : orderData?.shipping_fee; @@ -502,7 +504,7 @@ export const PaymentMethod = () => { pay_method: selectedPayment, offline_payment: currentTab === "offline" ? 0 : 1, all_price: - selectedPayment === "Paypal" + selectedPayment === "paypal" ? convertedAmount.reduce( (acc, item) => acc + item.converted_amount, 0 @@ -564,9 +566,9 @@ export const PaymentMethod = () => { data: res, payMethod: selectedPayment, currency: - selectedPayment === "Paypal" ? selectedCurrency : user.currency, + selectedPayment === "paypal" ? selectedCurrency : user.currency, amount: - selectedPayment === "Paypal" + selectedPayment === "paypal" ? convertedAmount.reduce( (acc, item) => acc + item.converted_amount, 0 @@ -731,12 +733,12 @@ export const PaymentMethod = () => { {t("payment.product_total")} - {selectedPayment === "Paypal" + {selectedPayment === "paypal" ? convertedAmount.find( (item) => item.item_key === "total_amount" )?.converted_amount || 0 : previewOrder?.total_amount || 0}{" "} - {selectedPayment === "Paypal" + {selectedPayment === "paypal" ? selectedCurrency === "USD" ? "USD" : "EUR" @@ -748,12 +750,12 @@ export const PaymentMethod = () => { {t("payment.domestic_shipping")} - {selectedPayment === "Paypal" + {selectedPayment === "paypal" ? convertedAmount.find( (item) => item.item_key === "domestic_shipping_fee" )?.converted_amount || 0 : orderData?.domestic_shipping_fee || 0}{" "} - {selectedPayment === "Paypal" + {selectedPayment === "paypal" ? selectedCurrency === "USD" ? "USD" : "EUR" @@ -765,12 +767,12 @@ export const PaymentMethod = () => { {t("payment.international_shipping")} - {selectedPayment === "Paypal" + {selectedPayment === "paypal" ? convertedAmount.find( (item) => item.item_key === "shipping_fee" )?.converted_amount || 0 : orderData?.shipping_fee || 0}{" "} - {selectedPayment === "Paypal" + {selectedPayment === "paypal" ? selectedCurrency === "USD" ? "USD" : "EUR" @@ -791,7 +793,7 @@ export const PaymentMethod = () => { > {t("payment.total")} - {selectedPayment === "Paypal" && + {selectedPayment === "paypal" && selectedCurrency !== user.currency && ( { )} - {selectedPayment === "Paypal" && + {selectedPayment === "paypal" && selectedCurrency === user.currency && ( { )} - {selectedPayment !== "Paypal" && ( + {selectedPayment !== "paypal" && ( { - + {/* {t("order.preview.order_amount")} {route.params.amount || "N/A"} {route.params.data.currency} @@ -219,7 +219,7 @@ export const PreviewOrder = () => { ).toFixed(2) || "N/A"}{" "} {route.params.data.currency} - + */} {/* Order Summary Section */} diff --git a/app/screens/productStatus/OrderDatails.tsx b/app/screens/productStatus/OrderDatails.tsx index c8c3ea7..e6ad941 100644 --- a/app/screens/productStatus/OrderDatails.tsx +++ b/app/screens/productStatus/OrderDatails.tsx @@ -285,6 +285,8 @@ export const OrderDetails = () => { navigation.navigate("Pay", { payUrl: res.payment_url, }); + }else{ + Alert.alert(t("error"), t("pay.payment_failed")); } }) .catch((err) => { @@ -622,22 +624,22 @@ export const OrderDetails = () => { */} - {/* + {t("order.platform_shipping")} {orderDetails.domestic_shipping_fee} - */} - {/* + + {t("order.international_shipping")} {orderDetails.shipping_fee} - */} + {t("order.total")} diff --git a/app/services/api/payApi.ts b/app/services/api/payApi.ts index fc0e860..8550bf7 100644 --- a/app/services/api/payApi.ts +++ b/app/services/api/payApi.ts @@ -89,6 +89,24 @@ export interface RechargeRecommendAmountResponse { currency: string; } + + export interface Transaction { + transaction_id: string; + type: "order_payment"; // Assuming 'order_payment' is the only possible type for this dataset + amount: number; + currency: string; + description: string; + timestamp: string; // Could also be `Date` if you plan to parse it immediately + related_order_no: string; +} + +export interface TransactionsResponse { + items: Transaction[]; + total: number; + page: number; + page_size: number; +} + export const payApi = { // 获取当前国家支付方式 getCountryPaymentMethods: () => { @@ -124,4 +142,9 @@ export const payApi = { getRechargeRecommendAmount: () => { return apiService.get('/api/recharge/recommended-amounts/'); }, + + // 获取流水 + getTransactionHistory: (page:number,page_size:number) => { + return apiService.get(`/api/users/me/transactions/?page=${page}&page_size=${page_size}`); + }, };