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.
381 lines
10 KiB
381 lines
10 KiB
import React, { useState, useEffect } from "react"; |
|
import { |
|
View, |
|
Text, |
|
StyleSheet, |
|
TextInput, |
|
TouchableOpacity, |
|
Image, |
|
ActivityIndicator, |
|
Modal, |
|
SafeAreaView, |
|
BackHandler, |
|
Alert |
|
} from "react-native"; |
|
import fontSize from "../../utils/fontsizeUtils"; |
|
import BackIcon from "../../components/BackIcon"; |
|
import {payApi} from "../../services/api/payApi"; |
|
import { useNavigation } from "@react-navigation/native"; |
|
import { NativeStackNavigationProp } from "@react-navigation/native-stack"; |
|
|
|
interface PhoneNumberInputModalProps { |
|
isVisible: boolean; |
|
onClose: () => void; |
|
paymentParams: { |
|
originalAmount: number; |
|
amount: number; |
|
currency: string; |
|
payment_method: string; |
|
selectedPriceLabel: string; |
|
onCloses?: () => void; |
|
} | null; |
|
onSubmit: (phoneNumber: string) => Promise<void>; |
|
onCloses?: () => void; |
|
} |
|
|
|
type RootStackParamList = { |
|
Pay: { payUrl: string }; |
|
} |
|
|
|
const PhoneNumberInputModal = ({ |
|
isVisible, |
|
onClose, |
|
paymentParams, |
|
onSubmit, |
|
onCloses, |
|
}: PhoneNumberInputModalProps) => { |
|
const [phoneNumber, setPhoneNumber] = useState(""); |
|
const [isSubmitting, setIsSubmitting] = useState(false); |
|
const navigation = |
|
useNavigation<NativeStackNavigationProp<RootStackParamList>>(); |
|
useEffect(() => { |
|
const backAction = () => { |
|
if (isVisible) { |
|
onClose(); |
|
return true; |
|
} |
|
return false; |
|
}; |
|
|
|
const backHandler = BackHandler.addEventListener( |
|
"hardwareBackPress", |
|
backAction |
|
); |
|
|
|
return () => backHandler.remove(); |
|
}, [isVisible, onClose]); |
|
|
|
const handlePaySubmit = async () => { |
|
if (!paymentParams) return; |
|
setIsSubmitting(true) |
|
const data = { |
|
amount: paymentParams.amount, |
|
currency: paymentParams.currency, |
|
payment_method: paymentParams.payment_method, |
|
} |
|
|
|
payApi.initiateRecharge(data).then((res) => { |
|
console.log(res); |
|
|
|
// 成功后关闭所有模态窗口 |
|
onClose(); |
|
if (onCloses) { |
|
onCloses(); |
|
} |
|
|
|
navigation.navigate("Pay", { |
|
payUrl: res.payment.payment_url, |
|
}); |
|
|
|
setIsSubmitting(false) |
|
}).catch((err) => { |
|
Alert.alert("Error", '支付失败,请重试'); |
|
setIsSubmitting(false) |
|
}) |
|
}; |
|
|
|
return ( |
|
<Modal |
|
visible={isVisible} |
|
animationType="slide" |
|
transparent={true} |
|
onRequestClose={onClose} |
|
presentationStyle="overFullScreen" |
|
> |
|
<SafeAreaView style={styles.modalContainer}> |
|
<View style={styles.modalContent}> |
|
<View style={styles.header}> |
|
<Text style={styles.title}>Recharger</Text> |
|
<TouchableOpacity onPress={onClose} style={styles.backButton}> |
|
<Text style={styles.backButtonText}> |
|
<BackIcon size={fontSize(18)} /> |
|
</Text> |
|
</TouchableOpacity> |
|
</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 || ""} |
|
</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> |
|
|
|
{/* 电话号码输入 */} |
|
|
|
{paymentParams?.payment_method === "mobile_money" && ( |
|
<> |
|
<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> |
|
</Modal> |
|
); |
|
}; |
|
|
|
const styles = StyleSheet.create({ |
|
modalContainer: { |
|
flex: 1, |
|
backgroundColor: "rgba(0, 0, 0, 0.5)", |
|
justifyContent: "center", |
|
alignItems: "center", |
|
}, |
|
modalContent: { |
|
height: "80%", |
|
width: "100%", |
|
backgroundColor: "#fff", |
|
borderTopLeftRadius: 10, |
|
borderTopRightRadius: 10, |
|
marginTop: "auto", |
|
}, |
|
header: { |
|
flexDirection: "row", |
|
justifyContent: "center", |
|
alignItems: "center", |
|
padding: 24, |
|
paddingBottom: 0, |
|
position: "relative", |
|
marginTop: 20, |
|
marginBottom: 20, |
|
}, |
|
title: { |
|
fontSize: 24, |
|
fontWeight: "700", |
|
textTransform: "capitalize", |
|
color: "black", |
|
position: "absolute", |
|
left: 0, |
|
right: 0, |
|
textAlign: "center", |
|
}, |
|
backButton: { |
|
position: "absolute", |
|
left: 24, |
|
zIndex: 1, |
|
}, |
|
backButtonText: { |
|
fontSize: fontSize(14), |
|
color: "#007AFF", |
|
fontWeight: "500", |
|
}, |
|
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 PhoneNumberInputModal;
|
|
|