|
|
|
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";
|
|
|
|
import { useTranslation } from "react-i18next";
|
|
|
|
|
|
|
|
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 { t } = useTranslation();
|
|
|
|
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", t('balance.phone_modal.payment_failed'));
|
|
|
|
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}>{t('balance.phone_modal.title')}</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}>
|
|
|
|
{t('balance.phone_modal.recharge_summary')}
|
|
|
|
</Text>
|
|
|
|
|
|
|
|
<View style={styles.paymentSummaryRow}>
|
|
|
|
<Text style={styles.paymentSummaryLabel}>{t('balance.phone_modal.amount')}</Text>
|
|
|
|
<Text style={styles.paymentSummaryValue}>
|
|
|
|
{paymentParams?.selectedPriceLabel || ""}
|
|
|
|
</Text>
|
|
|
|
</View>
|
|
|
|
|
|
|
|
{paymentParams?.currency !== "FCFA" && (
|
|
|
|
<View style={styles.paymentSummaryRow}>
|
|
|
|
<Text style={styles.paymentSummaryLabel}>
|
|
|
|
{t('balance.phone_modal.converted_amount')}
|
|
|
|
</Text>
|
|
|
|
<Text style={styles.paymentSummaryValueHighlight}>
|
|
|
|
{paymentParams?.currency === "USD" ? "$" : "€"}
|
|
|
|
{paymentParams?.amount.toFixed(2) || "0.00"}
|
|
|
|
</Text>
|
|
|
|
</View>
|
|
|
|
)}
|
|
|
|
|
|
|
|
<View style={styles.paymentSummaryRow}>
|
|
|
|
<Text style={styles.paymentSummaryLabel}>
|
|
|
|
{t('balance.phone_modal.payment_method')}
|
|
|
|
</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}>
|
|
|
|
{t('balance.phone_modal.phone_number')}
|
|
|
|
</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={t('balance.phone_modal.enter_phone')}
|
|
|
|
placeholderTextColor="#999"
|
|
|
|
/>
|
|
|
|
</View>
|
|
|
|
</View>
|
|
|
|
|
|
|
|
<View style={styles.supportedOperatorsContainer}>
|
|
|
|
<Text style={styles.supportedOperatorsTitle}>
|
|
|
|
{t('balance.phone_modal.supported_operators')}
|
|
|
|
</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}>
|
|
|
|
{t('balance.phone_modal.pay')}{" "}
|
|
|
|
{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;
|