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.

1784 lines
54 KiB

// 支付组件
import React, { useState, useEffect, useCallback } from "react";
import {
View,
Text,
StyleSheet,
ScrollView,
Image,
TouchableOpacity,
SafeAreaView,
ActivityIndicator,
Alert,
TextInput,
Linking,
Platform,
Clipboard,
} from "react-native";
import fontSize from "../utils/fontsizeUtils";
import widthUtils from "../utils/widthUtils";
import CircleOutlineIcon from "../components/CircleOutlineIcon";
import CloseIcon from "../components/CloseIcon";
import CheckIcon from "../components/CheckIcon";
import BackIcon from "../components/BackIcon";
// 添加导航相关导入
import { useNavigation } from '@react-navigation/native';
import { navigationRef } from "../navigation/RootNavigation";
// 添加API服务
import { payApi } from "../services/api/payApi";
interface RechargeScreenProps {
onClose: () => void;
}
const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
const [selectedPrice, setSelectedPrice] = useState("500,000");
const [selectedOperator, setSelectedOperator] = useState<string | null>(null);
const [activeTab, setActiveTab] = useState(0);
const [showBlankPage, setShowBlankPage] = useState(false);
// 添加货币转换相关状态
const [isConverting, setIsConverting] = useState(false);
// 指定导航类型为any
const navigation = useNavigation<any>();
const [convertedAmount, setConvertedAmount] = useState<{
converted_amount: number;
item_key: string;
original_amount: number;
}[]>([]);
const [currentCurrency, setCurrentCurrency] = useState("USD");
const [phoneNumber, setPhoneNumber] = useState('22660962235');
const [isSubmitting, setIsSubmitting] = useState(false);
const [paymentParams, setPaymentParams] = useState<{
originalAmount: number;
amount: number;
currency: string;
payment_method: string;
selectedPriceLabel: string;
} | null>(null);
const handlePriceSelect = (price: string) => {
setSelectedPrice(price);
// 如果当前已选择了货币转换,则重新计算转换后的金额
if (selectedOperator === "currency" && currentCurrency !== "FCFA") {
handleCurrencyConversion(price, currentCurrency);
}
};
const handleOperatorSelect = (operator: string) => {
setSelectedOperator(operator === selectedOperator ? null : operator);
// 如果选择了货币支付方式,立即进行货币转换
if (operator === "currency" && operator !== selectedOperator) {
// 触发货币转换,使用默认的USD
handleCurrencySelect("USD");
}
};
const handleBackButton = () => {
setShowBlankPage(false);
};
const handleButtonClick = () => {
if (selectedOperator) {
// 准备支付参数,方便后续发送
const params = {
originalAmount: parseFloat(selectedPrice.replace(/,/g, '')),
amount: parseFloat(selectedPrice.replace(/,/g, '')),
currency: "FCFA",
payment_method: "",
selectedPriceLabel: selectedPrice + " FCFA" // 选择的充值面额
};
// 根据selectedOperator确定支付方式
if (selectedOperator === "orange") {
params.payment_method = "Orange Money";
} else if (selectedOperator === "mtn") {
params.payment_method = "MTN MoMo";
} else if (selectedOperator === "balance") {
params.payment_method = "Balance";
} else if (selectedOperator === "currency") {
// 当选择了货币转换时
params.payment_method = "paypal";
params.currency = currentCurrency; // 使用选择的货币
// 使用转换后的金额,如果有
if (convertedAmount.length > 0) {
const convertedTotal = convertedAmount.find(item => item.item_key === 'total_amount');
if (convertedTotal) {
params.amount = convertedTotal.converted_amount;
}
}
}
// 保存支付参数
setPaymentParams(params);
// 打印支付信息
console.log("Payment Information:");
console.log("Selected Recharge Amount:", params.selectedPriceLabel);
console.log("Original Amount:", params.originalAmount, "FCFA");
console.log("Converted Amount:", params.amount);
console.log("Currency:", params.currency);
console.log("Payment Method:", params.payment_method);
setShowBlankPage(true);
}
};
// 提取一个专门用于货币转换的函数
const handleCurrencyConversion = (price: string, currency: string) => {
setIsConverting(true);
// 格式化金额,去除逗号
const amount = parseFloat(price.replace(/,/g, ''));
// 如果金额为0或无效,则不进行转换
if (!amount || isNaN(amount)) {
console.warn("Invalid amount for currency conversion");
setIsConverting(false);
return;
}
console.log(`Converting ${amount} FCFA to ${currency}...`);
// 调用货币转换API
const data = {
from_currency: 'FCFA',
to_currency: currency,
amounts: {
total_amount: amount,
domestic_shipping_fee: 0,
shipping_fee: 0,
},
};
payApi.convertCurrency(data)
.then((res) => {
if (res && res.converted_amounts_list && res.converted_amounts_list.length > 0) {
console.log("Conversion successful:", res.converted_amounts_list);
setConvertedAmount(res.converted_amounts_list);
} else {
console.error("Conversion response invalid:", res);
// 使用近似汇率作为备用
const fallbackRate = currency === "USD" ? 580.0 : 655.96; // 1 USD = 580 FCFA, 1 EUR = 655.96 FCFA
const convertedValue = amount / fallbackRate;
setConvertedAmount([{
converted_amount: convertedValue,
item_key: 'total_amount',
original_amount: amount
}]);
if (Platform.OS === 'web') {
console.warn("Using fallback conversion rate due to API error");
} else {
Alert.alert("Info", "Taux de conversion approximatif utilisé");
}
}
})
.catch((error) => {
console.error("Currency conversion failed:", error);
// 使用近似汇率作为备用
const fallbackRate = currency === "USD" ? 580.0 : 655.96;
const convertedValue = amount / fallbackRate;
setConvertedAmount([{
converted_amount: convertedValue,
item_key: 'total_amount',
original_amount: amount
}]);
if (Platform.OS === 'web') {
console.warn("Using fallback conversion rate due to API error");
} else {
Alert.alert("Info", "Taux de conversion approximatif utilisé");
}
})
.finally(() => {
setIsConverting(false);
});
};
// 修改货币选择函数,调用通用的转换函数
const handleCurrencySelect = (currency: string) => {
setCurrentCurrency(currency);
handleCurrencyConversion(selectedPrice, currency);
};
// 处理支付URL的函数
const openPaymentURL = useCallback((url: string) => {
console.log("Opening payment URL:", url);
// 判断运行平台
if (Platform.OS === 'web') {
try {
// Web平台首先尝试通过window.location跳转
// 保存当前URL作为回调地址,以便支付完成后返回
const currentUrl = window.location.href;
sessionStorage.setItem('payment_return_url', currentUrl);
// 尝试多种方式打开支付链接
// 方式1:直接修改当前窗口location
window.location.href = url;
// 方式2:如果直接跳转不生效,尝试打开新窗口
setTimeout(() => {
// 检查是否已经跳转
if (window.location.href === currentUrl) {
console.log("Direct navigation did not work, trying popup window...");
const newWindow = window.open(url, '_blank', 'noopener,noreferrer');
if (!newWindow || newWindow.closed || typeof newWindow.closed === 'undefined') {
console.warn("Popup blocked or failed to open. Trying iframe method.");
// 方式3:尝试使用iframe
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.src = url;
document.body.appendChild(iframe);
// 显示手动跳转提示
alert(`La page de paiement n'a pas pu s'ouvrir automatiquement. Veuillez cliquer sur OK pour essayer à nouveau.`);
window.location.href = url;
}
}
}, 1000);
} catch (error) {
console.error("Failed to open payment URL on web:", error);
// 最后尝试
try {
window.open(url, '_self');
} catch (e) {
console.error("All payment URL opening methods failed:", e);
alert(`Impossible d'ouvrir la page de paiement. URL: ${url}`);
}
}
} else {
// 移动平台使用Linking打开
Linking.canOpenURL(url).then(supported => {
if (supported) {
Linking.openURL(url).catch(err => {
console.error("Error opening URL with Linking:", err);
// 尝试使用WebView组件导航
if (navigationRef.current) {
navigationRef.current.navigate('Pay', { payUrl: url });
} else {
Alert.alert(
"Erreur",
"Impossible d'ouvrir la page de paiement. Veuillez réessayer.",
[
{
text: "Réessayer",
onPress: () => Linking.openURL(url)
},
{ text: "Annuler" }
]
);
}
});
} else {
console.error("Cannot open URL: " + url);
Alert.alert(
"Erreur",
"Cette URL ne peut pas être ouverte. Veuillez contacter le support technique.",
[
{
text: "Copier l'URL",
onPress: () => {
Clipboard.setString(url);
Alert.alert("Info", "URL copiée dans le presse-papiers");
}
},
{ text: "Fermer" }
]
);
}
}).catch(err => {
console.error("Couldn't check if URL can be opened:", err);
Alert.alert("Erreur", "Impossible de vérifier si l'URL peut être ouverte");
});
}
}, []);
// 更新处理支付提交的函数
const handlePaySubmit = async () => {
if (!paymentParams) {
if (Platform.OS === 'web') {
alert("Veuillez sélectionner un mode de paiement");
} else {
Alert.alert("Erreur", "Veuillez sélectionner un mode de paiement");
}
return;
}
// 验证电话号码(添加更严格的验证)
if (!phoneNumber || phoneNumber.length < 8) {
if (Platform.OS === 'web') {
alert("Veuillez entrer un numéro de téléphone valide (au moins 8 chiffres)");
} else {
Alert.alert("Erreur", "Veuillez entrer un numéro de téléphone valide (au moins 8 chiffres)");
}
return;
}
// 显示提交中状态
setIsSubmitting(true);
try {
// 准备请求数据,添加电话号码
const rechargeData = {
amount: paymentParams.amount,
currency: paymentParams.currency,
payment_method: paymentParams.payment_method,
phone: phoneNumber // 注意:如果后端API不支持此参数,可能需要调整
};
console.log("Submitting recharge request:", rechargeData);
// 调用充值接口(使用可选链避免错误)
const response = await payApi.initiateRecharge(rechargeData);
console.log("Recharge response:", response);
if (response && response.success) {
const paymentInfo = response.payment;
// 存储交易ID,以便后续查询
if (Platform.OS === 'web') {
sessionStorage.setItem('recharge_transaction_id', paymentInfo.transaction_id || '');
sessionStorage.setItem('recharge_id', response.recharge_id?.toString() || '');
}
// 检查是否有支付URL
if (paymentInfo && paymentInfo.payment_url) {
// 记录重要信息到控制台
console.log("Transaction ID:", paymentInfo.transaction_id);
console.log("Recharge ID:", response.recharge_id);
console.log("Payment URL:", paymentInfo.payment_url);
// 打开支付页面
navigation.navigate("Pay", {
payUrl: paymentInfo.payment_url,
});
// Web平台添加额外提示,因为可能会被浏览器拦截
if (Platform.OS === 'web') {
setTimeout(() => {
alert(`Si la page de paiement ne s'ouvre pas automatiquement, veuillez cliquer sur le bouton "Continuer" pour procéder au paiement. Vous pouvez également copier ce lien: ${paymentInfo.payment_url}`);
}, 1500);
}
} else {
// 没有支付URL但交易成功的情况
if (Platform.OS === 'web') {
alert("Votre recharge a été traitée avec succès!");
onClose(); // 关闭充值页面
} else {
Alert.alert(
"Succès",
"Votre recharge a été traitée avec succès!",
[{ text: "OK", onPress: onClose }]
);
}
}
} else {
// 处理失败情况,显示错误消息
const errorMessage = response?.msg || "Une erreur s'est produite lors du traitement de la recharge. Veuillez réessayer.";
if (Platform.OS === 'web') {
alert(errorMessage);
} else {
Alert.alert("Erreur", errorMessage);
}
}
} catch (error) {
// 处理异常
console.error("Recharge error:", error);
let errorMessage = "Une erreur s'est produite lors du traitement de la recharge. Veuillez réessayer.";
// 尝试从错误对象中提取更具体的错误信息
if (error instanceof Error) {
errorMessage = error.message || errorMessage;
}
if (Platform.OS === 'web') {
alert(errorMessage);
} else {
Alert.alert("Erreur", errorMessage);
}
} finally {
// 无论成功失败,都取消提交状态
setIsSubmitting(false);
}
};
return (
<SafeAreaView style={styles.safeArea}>
<View style={showBlankPage ? styles.mainContainer1 : styles.mainContainer}>
<View style={styles.header}>
<Text style={styles.title}>Recharger</Text>
{!showBlankPage && (
<TouchableOpacity onPress={onClose} style={styles.closeButton}>
<CloseIcon size={fontSize(15)} />
</TouchableOpacity>
)}
{showBlankPage && (
<TouchableOpacity onPress={handleBackButton} style={styles.backButton}>
<Text style={styles.backButtonText}>
<BackIcon size={fontSize(18)}/>
</Text>
</TouchableOpacity>
)}
</View>
{!showBlankPage ? (
<>
<ScrollView contentContainerStyle={styles.scrollContent}>
<View style={styles.container2}>
<View style={styles.amountRechargeContainer}>
<Text style={styles.rechargePromptTextStyle}>
Choisissez ou entrez le montant à recharger
</Text>
</View>
</View>
{/* 金额选择 */}
<View style={styles.priceGroup}>
<View style={styles.row}>
<TouchableOpacity
style={[
styles.priceBoxBlue,
selectedPrice === "500,000"
? styles.priceBoxSelected
: styles.priceBoxUnselected,
]}
onPress={() => handlePriceSelect("500,000")}
>
<Text
style={[
styles.priceTextBlue,
selectedPrice === "500,000"
? styles.priceTextSelected
: styles.priceTextUnselected,
]}
>
500,000
</Text>
<Text
style={[
styles.currencyTextBlue,
selectedPrice === "500,000"
? styles.currencyTextSelected
: styles.currencyTextUnselected,
]}
>
FCFA
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[
styles.priceBoxWhite,
selectedPrice === "1000,000"
? styles.priceBoxSelected
: styles.priceBoxUnselected,
]}
onPress={() => handlePriceSelect("1000,000")}
>
<Text
style={[
styles.priceText,
selectedPrice === "1000,000"
? styles.priceTextSelected
: styles.priceTextUnselected,
]}
>
1000,000
</Text>
<Text
style={[
styles.currencyText,
selectedPrice === "1000,000"
? styles.currencyTextSelected
: styles.currencyTextUnselected,
]}
>
FCFA
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[
styles.priceBoxWhite,
selectedPrice === "2000,000"
? styles.priceBoxSelected
: styles.priceBoxUnselected,
]}
onPress={() => handlePriceSelect("2000,000")}
>
<Text
style={[
styles.priceText,
selectedPrice === "2000,000"
? styles.priceTextSelected
: styles.priceTextUnselected,
]}
>
2000,000
</Text>
<Text
style={[
styles.currencyText,
selectedPrice === "2000,000"
? styles.currencyTextSelected
: styles.currencyTextUnselected,
]}
>
FCFA
</Text>
</TouchableOpacity>
</View>
<View style={styles.row}>
<TouchableOpacity
style={[
styles.priceBoxWhite,
selectedPrice === "3000,000"
? styles.priceBoxSelected
: styles.priceBoxUnselected,
]}
onPress={() => handlePriceSelect("3000,000")}
>
<Text
style={[
styles.priceText,
selectedPrice === "3000,000"
? styles.priceTextSelected
: styles.priceTextUnselected,
]}
>
3000,000
</Text>
<Text
style={[
styles.currencyText,
selectedPrice === "3000,000"
? styles.currencyTextSelected
: styles.currencyTextUnselected,
]}
>
FCFA
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[
styles.priceBoxWhite,
selectedPrice === "5000,000"
? styles.priceBoxSelected
: styles.priceBoxUnselected,
]}
onPress={() => handlePriceSelect("5000,000")}
>
<Text
style={[
styles.priceText,
selectedPrice === "5000,000"
? styles.priceTextSelected
: styles.priceTextUnselected,
]}
>
5000,000
</Text>
<Text
style={[
styles.currencyText,
selectedPrice === "5000,000"
? styles.currencyTextSelected
: styles.currencyTextUnselected,
]}
>
FCFA
</Text>
</TouchableOpacity>
</View>
</View>
{/* 支付方式标题 */}
<View style={styles.section}>
<Text style={styles.subtitle}>Choisissez votre mode de paiement</Text>
</View>
{/* Tab Bar */}
<View style={styles.tabContainer}>
<TouchableOpacity
style={[styles.tab, activeTab === 0 && styles.activeTab]}
onPress={() => setActiveTab(0)}
>
<Text style={[styles.tabText, activeTab === 0 && styles.activeTabText]}>
Mode de paiement
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.tab, activeTab === 1 && styles.activeTab]}
onPress={() => setActiveTab(1)}
>
<Text style={[styles.tabText, activeTab === 1 && styles.activeTabText]}>
Autre
</Text>
</TouchableOpacity>
</View>
{/* Tab Content */}
{activeTab === 0 ? (
<>
<View style={styles.operatorCard}>
<View
style={{
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
}}
>
<View style={{ flexDirection: "row", alignItems: "center" }}>
<Image
source={require("../../assets/img/image_cb840273.png")}
style={styles.operatorImage}
/>
<Text style={styles.orangeText}>
Nous ne supportons que{"\n"}les opérateurs affichés.
</Text>
</View>
<TouchableOpacity onPress={() => handleOperatorSelect("orange")}>
<View style={styles.checkboxContainer}>
<CircleOutlineIcon
size={fontSize(24)}
strokeColor={
selectedOperator === "orange" ? "#007efa" : undefined
}
fillColor={
selectedOperator === "orange" ? "#007efa" : undefined
}
/>
{selectedOperator === "orange" && (
<View style={styles.checkmarkContainer}>
<CheckIcon size={fontSize(12)} color="#FFFFFF" />
</View>
)}
</View>
</TouchableOpacity>
</View>
<View style={styles.iconRow}>
<Image
source={require("../../assets/img/image_7337a807.png")}
style={styles.operatorIcon}
/>
<Image
source={require("../../assets/img/image_96b927ad.png")}
style={styles.operatorIcon}
/>
<Image
source={require("../../assets/img/image_1fee7e8b.png")}
style={styles.operatorIcon}
/>
</View>
</View>
<View style={styles.cardContainer}>
<View style={styles.iconRow}>
<Image
source={require("../../assets/img/image_13d56c9.png")}
style={styles.operatorImage}
/>
</View>
{/* 右侧圆圈图标 */}
<TouchableOpacity onPress={() => handleOperatorSelect("mtn")}>
<View style={styles.checkboxContainer}>
<CircleOutlineIcon
size={fontSize(24)}
strokeColor={selectedOperator === "mtn" ? "#007efa" : undefined}
fillColor={selectedOperator === "mtn" ? "#007efa" : undefined}
/>
{selectedOperator === "mtn" && (
<View style={styles.checkmarkContainer}>
<CheckIcon size={fontSize(12)} color="#FFFFFF" />
</View>
)}
</View>
</TouchableOpacity>
</View>
<View style={styles.balanceInfoContainer}>
<View style={styles.leftInfo}>
<View style={styles.blueBox}>
{/* 圆形图标(左边) */}
<Image
source={require("../../assets/img/余额 icon.png")}
style={styles.operatorImage}
/>
</View>
<Text style={styles.balanceText}>
Vous avez encore un solde{"\n"}de 650,000 FCFA
</Text>
</View>
{/* 圆形图标(右边) */}
<TouchableOpacity onPress={() => handleOperatorSelect("balance")}>
<View style={styles.checkboxContainer}>
<CircleOutlineIcon
size={fontSize(24)}
strokeColor={
selectedOperator === "balance" ? "#007efa" : undefined
}
fillColor={selectedOperator === "balance" ? "#007efa" : undefined}
/>
{selectedOperator === "balance" && (
<View style={styles.checkmarkContainer}>
<CheckIcon size={fontSize(12)} color="#FFFFFF" />
</View>
)}
</View>
</TouchableOpacity>
</View>
<View style={styles.currencyContainer}>
<View style={styles.currencyRow}>
<Image
source={require("../../assets/img/image_8786995c.png")}
style={styles.currencyImage}
/>
<TouchableOpacity onPress={() => handleOperatorSelect("currency")}>
<View style={styles.checkboxContainer}>
<CircleOutlineIcon
size={fontSize(24)}
strokeColor={
selectedOperator === "currency" ? "#007efa" : undefined
}
fillColor={
selectedOperator === "currency" ? "#007efa" : undefined
}
/>
{selectedOperator === "currency" && (
<View style={styles.checkmarkContainer}>
<CheckIcon size={fontSize(12)} color="#FFFFFF" />
</View>
)}
</View>
</TouchableOpacity>
</View>
{selectedOperator === "currency" && (
<>
<Text style={styles.subtitle}>Choisissez la devise</Text>
<View style={styles.row}>
<TouchableOpacity
style={currentCurrency === "USD" ? styles.currencyButtonActive : styles.currencyButtonInactive}
onPress={() => handleCurrencySelect("USD")}
>
<Text style={currentCurrency === "USD" ? styles.buttonTextWhite : styles.buttonTextDark}>USD</Text>
</TouchableOpacity>
<TouchableOpacity
style={currentCurrency === "EUR" ? styles.currencyButtonActive : styles.currencyButtonInactive}
onPress={() => handleCurrencySelect("EUR")}
>
<Text style={currentCurrency === "EUR" ? styles.buttonTextWhite : styles.buttonTextDark}>EUR</Text>
</TouchableOpacity>
</View>
{isConverting ? (
<View style={{flexDirection: 'row', alignItems: 'center', marginTop: 16}}>
<ActivityIndicator size="small" color="#ff5100" />
<Text style={{...styles.totalText, marginLeft: 10}}>Converting...</Text>
</View>
) : (
<Text style={styles.totalText}>
Total: {convertedAmount.length > 0
? `${currentCurrency === "USD" ? "$" : "€"}${convertedAmount.find(item => item.item_key === 'total_amount')?.converted_amount.toFixed(2) || '0.00'}`
: `$${(parseFloat(selectedPrice.replace(/,/g, '')) / 580).toFixed(2)}`}
</Text>
)}
</>
)}
</View>
<View style={styles.cardContainer}>
<View style={styles.iconRow}>
<Image
source={require("../../assets/img/image_4e72f054.png")}
style={styles.operatorImage1}
/>
</View>
{/* 右侧圆圈图标 */}
<TouchableOpacity onPress={() => handleOperatorSelect("mtn")}>
<View style={styles.checkboxContainer}>
<CircleOutlineIcon
size={fontSize(24)}
strokeColor={selectedOperator === "mtn" ? "#007efa" : undefined}
fillColor={selectedOperator === "mtn" ? "#007efa" : undefined}
/>
{selectedOperator === "mtn" && (
<View style={styles.checkmarkContainer}>
<CheckIcon size={fontSize(12)} color="#FFFFFF" />
</View>
)}
</View>
</TouchableOpacity>
</View>
</>
) : (
<View style={styles.outerContainer}>
<View style={styles.flexContainer}>
<View style={styles.imageContainer}>
<Image
source={require('../../assets/img/image_c6aa9539.png')}
style={styles.imageStyle}
resizeMode="cover"
/>
</View>
<View style={styles.verticalAlignEndContent}>
<View style={styles.svgContainer}>
<TouchableOpacity onPress={() => handleOperatorSelect("mtn")}>
<View style={styles.checkboxContainer}>
<CircleOutlineIcon
size={fontSize(24)}
strokeColor={selectedOperator === "mtn" ? "#007efa" : undefined}
fillColor={selectedOperator === "mtn" ? "#007efa" : undefined}
/>
{selectedOperator === "mtn" && (
<View style={styles.checkmarkContainer}>
<CheckIcon size={fontSize(12)} color="#FFFFFF" />
</View>
)}
</View>
</TouchableOpacity>
</View>
</View>
</View>
<View style={styles.flexContainer}>
<View style={styles.imageContainer}>
<Image
source={require('../../assets/img/Global 1.png')}
style={styles.imageStyle}
resizeMode="cover"
/>
</View>
<View style={styles.verticalAlignEndContent}>
<View style={styles.svgContainer}>
<TouchableOpacity onPress={() => handleOperatorSelect("mtn")}>
<View style={styles.checkboxContainer}>
<CircleOutlineIcon
size={fontSize(24)}
strokeColor={selectedOperator === "mtn" ? "#007efa" : undefined}
fillColor={selectedOperator === "mtn" ? "#007efa" : undefined}
/>
{selectedOperator === "mtn" && (
<View style={styles.checkmarkContainer}>
<CheckIcon size={fontSize(12)} color="#FFFFFF" />
</View>
)}
</View>
</TouchableOpacity>
</View>
</View>
</View>
</View>
)}
</ScrollView>
{/* 操作按钮 - 固定在底部 */}
<View style={styles.actionButtonsContainer}>
<View style={styles.actionButtons}>
<TouchableOpacity style={styles.cancelButton} onPress={onClose}>
<Text style={styles.buttonTextDark}>Annuler</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.confirmButton} onPress={handleButtonClick}>
<Text style={styles.buttonTextWhite}>Confirmer</Text>
</TouchableOpacity>
</View>
</View>
</>
) : (
<View style={styles.paymentConfirmContainer}>
{/* 充值金额信息 */}
<View style={styles.paymentSummaryCard}>
<Text style={styles.paymentSummaryTitle}>Résumé de la recharge</Text>
<View style={styles.paymentSummaryRow}>
<Text style={styles.paymentSummaryLabel}>Montant:</Text>
<Text style={styles.paymentSummaryValue}>
{paymentParams?.selectedPriceLabel || selectedPrice + " FCFA"}
</Text>
</View>
{paymentParams?.currency !== "FCFA" && (
<View style={styles.paymentSummaryRow}>
<Text style={styles.paymentSummaryLabel}>Montant converti:</Text>
<Text style={styles.paymentSummaryValueHighlight}>
{paymentParams?.currency === "USD" ? "$" : "€"}
{paymentParams?.amount.toFixed(2) || "0.00"}
</Text>
</View>
)}
<View style={styles.paymentSummaryRow}>
<Text style={styles.paymentSummaryLabel}>Méthode de paiement:</Text>
<Text style={styles.paymentSummaryValue}>
{paymentParams?.payment_method || "Non sélectionné"}
</Text>
</View>
</View>
{/* 电话号码输入 */}
<View style={styles.phoneInputContainer}>
<Text style={styles.phoneInputLabel}>Numéro de téléphone</Text>
<View style={styles.phoneInputWrapper}>
<View style={styles.countryCodeContainer}>
<Text style={styles.countryCodeText}>+89</Text>
</View>
<TextInput
style={styles.phoneInput}
value={phoneNumber}
onChangeText={setPhoneNumber}
keyboardType="phone-pad"
placeholder="Entrez votre numéro"
placeholderTextColor="#999"
/>
</View>
</View>
{/* 支持的运营商 */}
<View style={styles.supportedOperatorsContainer}>
<Text style={styles.supportedOperatorsTitle}>Opérateurs pris en charge</Text>
<View style={styles.operatorsRow}>
<Image
source={require("../../assets/img/image_7337a807.png")}
style={styles.operatorSmallIcon}
/>
<Image
source={require("../../assets/img/image_96b927ad.png")}
style={styles.operatorSmallIcon}
/>
<Image
source={require("../../assets/img/image_1fee7e8b.png")}
style={styles.operatorSmallIcon}
/>
</View>
</View>
{/* 支付按钮 */}
<TouchableOpacity
style={[styles.payButton, isSubmitting && styles.payButtonDisabled]}
onPress={handlePaySubmit}
disabled={isSubmitting}
>
{isSubmitting ? (
<ActivityIndicator size="small" color="#fff" />
) : (
<Text style={styles.payButtonText}>
PAYER {paymentParams?.currency === "FCFA"
? paymentParams.originalAmount.toLocaleString() + " " + paymentParams.currency
: (paymentParams?.currency === "USD"
? "$" + paymentParams?.amount.toFixed(2)
: paymentParams?.amount.toFixed(2) + " €")
}
</Text>
)}
</TouchableOpacity>
</View>
)}
</View>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
safeArea: {
flex: 1,
backgroundColor: "#f0f0f0",
},
mainContainer: {
flex: 1,
backgroundColor: "#f0f0f0",
borderTopLeftRadius: 10,
borderTopRightRadius: 10,
},
mainContainer1: {
flex: 1,
backgroundColor: "#fff",
borderTopLeftRadius: 10,
borderTopRightRadius: 10,
},
header: {
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
padding: 24,
paddingBottom: 0,
position: "relative",
marginTop: 20,
marginBottom: 20,
},
scrollContent: {
padding: 24,
paddingTop: 0,
},
container: {
padding: 24,
backgroundColor: "#f0f0f0",
borderTopLeftRadius: 10,
borderTopRightRadius: 10,
},
title: {
fontSize: 24,
fontWeight: "700",
textTransform: "capitalize",
color: "black",
position: "absolute",
left: 0,
right: 0,
textAlign: "center",
},
section: {
marginTop: 44,
},
subtitle: {
fontSize: 16,
fontWeight: "700",
color: "black",
textTransform: "capitalize",
marginBottom: 12,
},
priceGroup: {
marginTop: 10,
},
row: {
flexDirection: "row",
justifyContent: "flex-start",
marginTop: 15,
},
priceBoxBlue: {
width: "30%",
backgroundColor: "#edf2fa",
borderColor: "#002fa7",
borderWidth: 1,
borderRadius: 5,
paddingVertical: 9,
paddingHorizontal: 22,
alignItems: "center",
marginRight: "5%",
},
priceBoxWhite: {
width: "30%",
backgroundColor: "white",
borderRadius: 5,
paddingVertical: 9,
paddingHorizontal: 22,
alignItems: "center",
marginRight: "5%",
},
priceTextBlue: {
fontSize: fontSize(16),
fontWeight: "700",
color: "#002fa7",
},
currencyTextBlue: {
fontSize: fontSize(10),
color: "#002fa7",
marginTop: 1,
},
priceText: {
fontSize: fontSize(16),
fontWeight: "700",
color: "#333",
},
currencyText: {
fontSize: fontSize(10),
color: "#7f7e7e",
marginTop: 1,
},
operatorCard: {
backgroundColor: "white",
padding: 16,
borderRadius: 5,
marginTop: 18,
},
operatorImage: {
width: 80,
height: 30,
resizeMode: "contain",
},
operatorImage1: {
width: 228,
height: 30,
resizeMode: "contain",
},
orangeText: {
color: "#ff5100",
fontSize: fontSize(12),
fontWeight: "500",
marginLeft: 12,
},
iconRow: {
flexDirection: "row",
gap: 10,
},
operatorIcon: {
width: 60,
height: 22,
resizeMode: "contain",
},
currencyContainer: {
backgroundColor: "white",
padding: 10,
borderRadius: 5,
marginTop: 20,
},
currencyRow: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
paddingRight:6
},
currencyImage: {
width: 80,
height: 30,
resizeMode: "contain",
},
radioCircle: {
width: 24,
height: 24,
borderRadius: 12,
borderWidth: 2,
borderColor: "#007AFF",
},
currencyButtonActive: {
backgroundColor: "#002fa7",
borderRadius: 18,
width: widthUtils(36, 100).width,
height: widthUtils(36, 100).height,
justifyContent: "center",
alignItems: "center",
},
currencyButtonInactive: {
backgroundColor: "#eeeeee",
borderRadius: 18,
width: widthUtils(36, 100).width,
height: widthUtils(36, 100).height,
justifyContent: "center",
alignItems: "center",
marginLeft: 10,
},
buttonTextWhite: {
color: "white",
fontWeight: "600",
},
buttonTextDark: {
color: "black",
fontWeight: "500",
},
totalText: {
marginTop: 16,
fontWeight: "900",
fontSize: fontSize(16),
color: "#ff5100",
},
actionButtonsContainer: {
padding: 24,
paddingTop: 0,
backgroundColor: "#f0f0f0",
},
actionButtons: {
flexDirection: "row",
justifyContent: "space-between",
padding: 10,
},
cancelButton: {
backgroundColor: "white",
borderRadius: 25,
width: widthUtils(50, 160).width,
height: widthUtils(50, 160).height,
justifyContent: "center",
alignItems: "center",
borderColor: "#ccc",
borderWidth: 1,
},
confirmButton: {
backgroundColor: "#002fa7",
borderRadius: 25,
width: widthUtils(50, 160).width,
height: widthUtils(50, 160).height,
justifyContent: "center",
alignItems: "center",
},
balanceInfoContainer: {
flexDirection: "row",
backgroundColor: "white",
borderRadius: 5,
paddingHorizontal: 16,
height: 50,
alignItems: "center",
justifyContent: "space-between",
marginTop: 14,
},
leftInfo: {
flexDirection: "row",
alignItems: "center",
flex: 1,
},
blueBox: {
flexDirection: "row",
backgroundColor: "#3955f6",
paddingHorizontal: 7,
paddingLeft: 6,
alignItems: "center",
borderRadius: 4,
},
saleText: {
fontSize: 16,
fontFamily: "Timmana",
color: "white",
marginLeft: 4,
},
balanceText: {
marginLeft: 17,
fontSize: fontSize(11),
lineHeight: 14,
fontWeight: "500",
color: "#333333",
},
cardContainer: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
backgroundColor: "white",
borderRadius: 5,
paddingHorizontal: 16,
height: 50,
marginTop: 15,
},
imageSmall: {
width: widthUtils(30, 24).width,
height: widthUtils(30, 24).height,
resizeMode: "contain",
},
imageLarge: {
width: widthUtils(26, 44).width,
height: widthUtils(26, 44).height,
resizeMode: "contain",
},
emptyBox: {
backgroundColor: "transparent",
borderWidth: 0,
},
container1: {
flexDirection: "row",
gap: 10,
alignItems: "center",
marginTop: 10,
},
button: {
width: widthUtils(36, 190).width,
height: widthUtils(36, 190).height,
borderRadius: 18,
justifyContent: "center",
alignItems: "center",
},
buttonActive: {
backgroundColor: "#002fa7",
},
buttonInactive: {
backgroundColor: "#fdfefe",
},
textActive: {
color: "white",
fontWeight: "600",
fontSize: fontSize(15),
},
textInactive: {
color: "black",
fontSize: fontSize(15),
},
priceBoxSelected: {
backgroundColor: "#edf2fa",
borderColor: "#002fa7",
borderWidth: 1,
},
priceBoxUnselected: {
backgroundColor: "white",
borderColor: "#dddddd",
borderWidth: 1,
},
priceTextSelected: {
color: "#002fa7",
},
priceTextUnselected: {
color: "#333",
},
currencyTextSelected: {
color: "#002fa7",
},
currencyTextUnselected: {
color: "#7f7e7e",
},
closeButton: {
padding: 5,
position: "absolute",
right: 24,
zIndex: 1,
},
checkboxContainer: {
position: "relative",
width: fontSize(24),
height: fontSize(24),
},
checkmarkContainer: {
position: "absolute",
top: 0,
left: 0,
right: 0,
bottom: 0,
justifyContent: "center",
alignItems: "center",
},
container2: {
width: '100%',
marginTop: 20,
},
amountRechargeContainer: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: 60,
backgroundColor: 'white',
borderRadius: 5,
},
rechargePromptTextStyle: {
flex: 0,
padding: 0,
margin: 0,
fontSize: 14,
lineHeight: 14,
color: '#747474',
// Note: PingFang SC font might not be available by default in React Native
// You may need to load custom fonts using expo-font or other methods
},
tabContainer: {
flexDirection: 'row',
backgroundColor: 'white',
borderRadius: 5,
marginTop: 10,
padding: 5,
},
tab: {
flex: 1,
paddingVertical: 10,
alignItems: 'center',
borderRadius: 5,
},
activeTab: {
backgroundColor: '#002fa7',
},
tabText: {
fontSize: fontSize(14),
color: '#333',
fontWeight: '500',
},
activeTabText: {
color: 'white',
fontWeight: '600',
},
emptyTab: {
backgroundColor: 'white',
borderRadius: 5,
padding: 20,
marginTop: 10,
alignItems: 'center',
justifyContent: 'center',
height: 200,
},
emptyTabText: {
color: '#666',
fontSize: fontSize(14),
},
outerContainer: {
width: '100%',
},
flexContainer: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-start',
height: 50,
paddingRight: 16,
paddingLeft: 16,
backgroundColor: 'white',
borderRadius: 5,
marginTop: 18,
},
imageContainer: {
width: '26.54%',
},
imageStyle: {
width: 80,
height: 30,
borderWidth: 0,
},
verticalAlignEndContent: {
flexDirection: 'column',
alignItems: 'flex-end',
width: '73.46%',
},
svgContainer: {
width: 24,
height: 24,
},
backButton: {
position: "absolute",
left: 24,
zIndex: 1,
},
backButtonText: {
fontSize: fontSize(14),
color: "#007AFF",
fontWeight: "500",
},
blankPage: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#f0f0f0",
},
blankPageText: {
fontSize: fontSize(16),
color: "#666",
},
paymentSection2: {
paddingTop: 24,
paddingRight: 20,
paddingBottom: 333,
paddingLeft: 20,
backgroundColor: 'white',
borderTopLeftRadius: 10,
borderTopRightRadius: 10,
},
paymentSectionContainer: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-start',
width: '100%',
},
paymentSection: {
width: '8.48%',
paddingRight: 15,
},
svgContainer1: {
width: 18,
height: 18,
},
paymentSection1: {
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'flex-start',
width: '91.52%',
paddingRight: 33,
},
paymentHeadingStyle: {
padding: 0,
margin: 0,
fontSize: 24,
lineHeight: 22,
color: 'black',
textTransform: 'capitalize',
fontFamily: 'Montserrat-Bold',
},
transactionSummaryContainer1: {
width: '100%',
},
transactionSummaryContainer: {
width: '100%',
paddingRight: 15,
paddingLeft: 15,
backgroundColor: 'linear-gradient(90deg, rgba(206, 229, 255, 1) 0%, rgba(238, 244, 255, 1) 100%',
borderRadius: 5,
},
flexContainerWithImages: {
flexDirection: 'row',
alignItems: 'flex-start',
justifyContent: 'flex-start',
},
imageContainerStyled: {
width: 99,
height: 36,
borderWidth: 0,
},
imageContainerWithBorder: {
width: 135,
height: 140,
marginLeft: 141,
borderWidth: 0,
},
amountContainer: {
width: '100%',
paddingTop: 8,
paddingRight: 11,
paddingBottom: 10,
paddingLeft: 11,
marginTop: -83,
backgroundColor: 'white',
borderWidth: 1,
borderRadius: 5,
},
amountLabel: {
padding: 0,
margin: 0,
fontSize: 12,
color: '#7f7e7e',
fontFamily: 'PingFangSC-Medium',
},
amountContainer1: {
flexDirection: 'row',
alignItems: 'flex-start',
justifyContent: 'flex-start',
marginTop: 1,
},
priceHeading: {
padding: 0,
paddingBottom: 5,
margin: 0,
fontSize: 24,
lineHeight: 22,
color: '#161616',
fontFamily: 'Montserrat-Bold',
},
priceLabel: {
padding: 0,
paddingTop: 5,
margin: 0,
marginLeft: 3,
fontSize: 12,
color: '#7f7e7e',
fontFamily: 'PingFangSC-Medium',
},
mobileInfoSection: {
width: '100%',
marginTop: 30,
},
mobileNumberSection: {
width: '100%',
},
mobileNumberLabel: {
padding: 0,
margin: 0,
fontSize: 14,
lineHeight: 18,
color: 'black',
fontFamily: 'PingFangSC-Regular',
},
infoCard: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-start',
width: '100%',
height: 50,
paddingRight: 12,
paddingLeft: 12,
marginTop: 12,
borderWidth: 1,
borderColor: '#d8d8d8',
borderRadius: 25,
},
flexRowWithIcon: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-start',
},
maskedImageWithText: {
width: 20,
height: 12,
borderWidth: 0,
},
highlightText: {
padding: 0,
margin: 0,
marginLeft: 3,
fontSize: 16,
lineHeight: 22,
color: '#1c284e',
fontFamily: 'PingFangSC-Semibold',
},
svgContainer2: {
width: 12,
height: 12,
marginLeft: 12,
},
verticalDivider: {
width: 1,
height: 30,
marginLeft: 8.5,
borderLeftWidth: 1,
borderColor: '#b1b1b1',
},
statisticText: {
padding: 0,
margin: 0,
marginLeft: 19.5,
fontSize: 16,
lineHeight: 22,
color: '#1c284e',
fontFamily: 'PingFangSC-Semibold',
},
mobileOperatorsContainer: {
width: '100%',
marginTop: 20,
},
operatorSupportContainer: {
flexDirection: 'row',
gap: 10,
alignItems: 'center',
justifyContent: 'flex-start',
marginTop: 12,
},
imageContainerWithBorder1: {
width: 70,
height: 26,
borderWidth: 0,
},
blueBoxContainer: {
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'flex-start',
width: '100%',
marginTop: 50,
backgroundColor: '#002fa7',
borderRadius: 25,
},
paymentNotice1: {
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
height: 50,
},
paymentNotice: {
padding: 0,
margin: 0,
fontSize: 16,
color: 'white',
fontFamily: 'Montserrat-Bold',
},
paymentConfirmContainer: {
flex: 1,
padding: 20,
backgroundColor: "#fff",
},
paymentSummaryCard: {
backgroundColor: "#f5f9ff",
borderRadius: 10,
padding: 20,
marginBottom: 20,
},
paymentSummaryTitle: {
fontSize: fontSize(18),
fontWeight: "700",
marginBottom: 15,
color: "#333",
},
paymentSummaryRow: {
flexDirection: "row",
justifyContent: "space-between",
marginBottom: 10,
},
paymentSummaryLabel: {
fontSize: fontSize(14),
color: "#666",
},
paymentSummaryValue: {
fontSize: fontSize(14),
fontWeight: "500",
color: "#333",
},
paymentSummaryValueHighlight: {
fontSize: fontSize(14),
fontWeight: "600",
color: "#ff5100",
},
phoneInputContainer: {
marginBottom: 20,
},
phoneInputLabel: {
fontSize: fontSize(16),
fontWeight: "500",
marginBottom: 10,
color: "#333",
},
phoneInputWrapper: {
flexDirection: "row",
borderWidth: 1,
borderColor: "#ddd",
borderRadius: 25,
overflow: "hidden",
},
countryCodeContainer: {
backgroundColor: "#f5f5f5",
paddingHorizontal: 15,
justifyContent: "center",
borderRightWidth: 1,
borderRightColor: "#ddd",
},
countryCodeText: {
fontSize: fontSize(16),
color: "#333",
},
phoneInput: {
flex: 1,
height: 50,
paddingHorizontal: 15,
fontSize: fontSize(16),
color: "#333",
},
supportedOperatorsContainer: {
marginBottom: 30,
},
supportedOperatorsTitle: {
fontSize: fontSize(16),
fontWeight: "500",
marginBottom: 10,
color: "#333",
},
operatorsRow: {
flexDirection: "row",
alignItems: "center",
},
operatorSmallIcon: {
width: 70,
height: 26,
resizeMode: "contain",
marginRight: 15,
},
payButton: {
backgroundColor: "#002fa7",
borderRadius: 25,
height: 50,
justifyContent: "center",
alignItems: "center",
marginTop: 20,
},
payButtonDisabled: {
backgroundColor: "#8da0d4",
opacity: 0.7,
},
payButtonText: {
color: "white",
fontSize: fontSize(16),
fontWeight: "700",
},
});
export default RechargeScreen;