import React, { useState, useEffect } from "react"; import { View, Text, TouchableOpacity, StyleSheet, ScrollView, Image, Alert, ActivityIndicator, } from "react-native"; import { payApi, PaymentMethodsResponse } from "../../services/api/payApi"; import fontSize from "../../utils/fontsizeUtils"; import BackIcon from "../../components/BackIcon"; import { useNavigation, NavigationProp } from "@react-navigation/native"; import widthUtils from "../../utils/widthUtils"; import useOrderStore from "../../store/order"; import useCreateOrderStore from "../../store/createOrder"; import { useRoute, RouteProp } from "@react-navigation/native"; import useUserStore from "../../store/user"; import { createOrderDataType } from "../../types/createOrder"; import { ordersApi, OrderData, CreateOrderRequest, Order, } from "../../services/api/orders"; // Define route params type type PaymentMethodRouteParams = { freight_forwarder_address_id?: number; }; // Define the root navigation params type RootStackParamList = { PreviewOrder: {data:Order,payMethod:string,currency:string,amount:number}; Pay: { order_id: string }; ShippingFee: { freight_forwarder_address_id?: number }; PaymentMethod: { freight_forwarder_address_id?: number }; PreviewAddress: undefined; AddressList: undefined; // Add other routes as needed }; interface PaymentOption { id: string; label: string; icon: string; value?: string | string[]; } interface PaymentTab { id: string; label: string; options: PaymentOption[]; } const PaymentMethodItem = ({ option, isSelected, onSelect, selectedCurrency, onSelectCurrency, exchangeRates, totalAmount, convertedAmount, isConverting, }: { option: PaymentOption; isSelected: boolean; onSelect: () => void; selectedCurrency?: string; onSelectCurrency?: (currency: string) => void; exchangeRates?: { usd: number; eur: number; }; totalAmount?: number; convertedAmount?: number; isConverting?: boolean; }) => ( {option.icon} {option.label} {Array.isArray(option.value) && option.value.length > 0 && ( {option.value.map((op: string) => ( {op} ))} )} {/* Show currency selector directly under PayPal when selected */} {isSelected && option.label === "Paypal" && selectedCurrency && onSelectCurrency && exchangeRates && totalAmount && ( )} ); // Currency selector component interface CurrencySelectorProps { selectedCurrency: string; onSelectCurrency: (currency: string) => void; exchangeRates: { usd: number; eur: number; }; totalAmount: number; convertedAmount?: number; isConverting?: boolean; } const CurrencySelector = ({ selectedCurrency, onSelectCurrency, exchangeRates, totalAmount, convertedAmount = 0, isConverting = false, }: CurrencySelectorProps) => ( Select Currency onSelectCurrency("USD")} > USD onSelectCurrency("EUR")} > EUR {!isConverting && ( {selectedCurrency === "USD" ? "$" : "€"}{convertedAmount} )} {isConverting && ( )} ); export const PaymentMethod = () => { const [tabs, setTabs] = useState([ { id: "online", label: "Online Payment", options: [], }, { id: "offline", label: "Offline Payment", options: [], }, ]); const [currentTab, setCurrentTab] = useState("online"); const [paymentMethods, setPaymentMethods] = useState(); const [selectedPayment, setSelectedPayment] = useState(null); const navigation = useNavigation>(); const route = useRoute, string>>(); const [expanded, setExpanded] = useState(false); const order = useOrderStore((state) => state.order); const [previewOrder, setPreviewOrder] = useState(); const [loading, setLoading] = useState(false); const { user } = useUserStore(); const [createOrderData, setCreateOrderData] = useState(); const { items, orderData,setOrderData,resetOrder } = useCreateOrderStore(); const [selectedCurrency, setSelectedCurrency] = useState("USD"); const [convertedAmount, setConvertedAmount] = useState(0); const [isConverting, setIsConverting] = useState(false); const [createLoading, setCreateLoading] = useState(false); const [exchangeRates] = useState({ usd: 580.00, eur: 655.96 }); const [totalAmount, setTotalAmount] = useState(121.97); const toggleExpanded = () => { setExpanded(!expanded); }; const onSelectPayment = (paymentId: string) => { if(paymentId === "Paypal"){ setIsConverting(true); const data = { from_currency: user.currency, to_currency: selectedCurrency, amounts:[ { } ] } payApi.convertCurrency({ from_currency: user.currency, to_currency: selectedCurrency, amount: ( (previewOrder?.total_amount || 0) + (createOrderData?.domestic_shipping_fee || 0) + (createOrderData?.shipping_fee || 0) ), }).then((res) => { setConvertedAmount(res.converted_amount); setIsConverting(false); }).catch(error => { console.error("Currency conversion failed:", error); setIsConverting(false); }); } setSelectedPayment(paymentId); }; const onSelectCurrency = (currency: string) => { setSelectedCurrency(currency); // Call the API to convert the currency setIsConverting(true); payApi.convertCurrency({ from_currency: user.currency, to_currency: currency, amount: ( (previewOrder?.total_amount || 0) + (createOrderData?.domestic_shipping_fee || 0) + (createOrderData?.shipping_fee || 0) ), }).then((res) => { setConvertedAmount(res.converted_amount); setIsConverting(false); }).catch(error => { console.error("Currency conversion failed:", error); setIsConverting(false); }); }; const getPaymentMethods = async () => { try { const response = await payApi.getCountryPaymentMethods(); setPaymentMethods(response); // 设置默认支付方式选项 setTabs([ { id: "online", label: "Online Payment", options: response.current_country_methods.map((method) => ({ id: method.key, label: method.key, icon: getPaymentIcon(method.key), value: method.value, })), }, { id: "offline", label: "Offline Payment", options: [], }, ]); } catch (error) { console.error("获取支付方式失败:", error); } }; const getPaymentIcon = (key: string): string => { switch (key) { case "Brainnel Pay(Mobile Money)": return "💳"; case "Wave": return "💸"; case "Paypal": return "🅿️"; case "Bank Card Payment": return "💳"; default: return "💰"; } }; useEffect(() => { getPaymentMethods(); }, []); useEffect(() => { setLoading(true); if (route.params?.freight_forwarder_address_id) { const data = { country_code: route.params.freight_forwarder_address_id, items: items, }; ordersApi .getOrders(data) .then((res) => { setPreviewOrder(res); setLoading(false); }) .catch(() => { setLoading(false); Alert.alert("Error", "Failed to get preview order"); }); } }, [route.params?.freight_forwarder_address_id]); useEffect(() => { setCreateOrderData({ ...orderData, address_id: orderData.address_id, domestic_shipping_fee: orderData.domestic_shipping_fee, shipping_fee: orderData.shipping_fee, transport_type: orderData.transport_type, currency: user.currency, }); console.log("orderData", orderData); }, [orderData]); const handleSubmit = async () => { if (!selectedPayment) { Alert.alert("请选择支付方式"); return; } const items = previewOrder?.items.map((item) => ({ offer_id: item.offer_id, cart_item_id: item.cart_item_id, sku_id: item.sku_id, product_name: item.product_name, product_name_en: item.product_name_en, product_name_ar: item.product_name_ar, product_name_fr: item.product_name_fr, sku_attributes: item.attributes.map((attr) => ({ attribute_name: attr.attribute_name, attribute_value: attr.value, })), sku_image:item.sku_image_url, quantity: item.quantity, unit_price: item.unit_price, total_price: item.total_price, })) || []; if (createOrderData) { createOrderData.items = items; createOrderData.payment_method = selectedPayment; createOrderData.total_amount = selectedPayment === 'Paypal' ? convertedAmount : Number(((previewOrder?.total_amount || 0) + (orderData?.domestic_shipping_fee || 0) + (orderData?.shipping_fee || 0)).toFixed(2)); createOrderData.actual_amount = selectedPayment === 'Paypal' ? convertedAmount : Number(((previewOrder?.total_amount || 0) + (orderData?.domestic_shipping_fee || 0) + (orderData?.shipping_fee || 0)).toFixed(2)); createOrderData.currency = selectedPayment === 'Paypal' ? selectedCurrency : user.currency; } setOrderData(createOrderData || {}); setCreateLoading(true) try { const res = await ordersApi.createOrder(createOrderData as CreateOrderRequest) setCreateLoading(false) navigation.navigate("PreviewOrder",{data:res,payMethod:selectedPayment,currency:selectedCurrency,amount:convertedAmount}); resetOrder() }catch(e) { setCreateLoading(false) Alert.alert('Error', 'Failed to get preview order'); }finally { setCreateLoading(false) } }; return ( navigation.goBack()}> Payment Method {loading ? ( ) : ( 💳 Payment Method {/* 选项卡 */} {tabs.map((tab) => ( { console.log(tab.id); setCurrentTab(tab.id) }} > {tab.label} ))} {/* 支付选项 */} {tabs .find((tab) => tab.id === currentTab) ?.options.map((option) => ( onSelectPayment(option.id)} selectedCurrency={selectedCurrency} onSelectCurrency={onSelectCurrency} exchangeRates={exchangeRates} totalAmount={totalAmount} convertedAmount={convertedAmount} isConverting={isConverting} /> ))} {/* Order Summary Section */} 📦 Order Summary Products({previewOrder?.items?.length || 0} items) {expanded ? "Hide Details" : "View Details"} {previewOrder?.items?.map((item) => ( {item.sku_image_url ? ( ) : ( )} {item.product_name} {item.sku_attributes?.map((attribute) => ( {attribute?.attribute_name}:{" "} {attribute?.attribute_value} ))} Qty: {item.quantity} ${item?.total_price} ))} 商品总价 {previewOrder?.total_amount || 0} {previewOrder?.currency} 中国运费 {createOrderData?.domestic_shipping_fee || 0}{" "} {previewOrder?.currency} 预计国际运费 {createOrderData?.shipping_fee || 0} {previewOrder?.currency} {/* 实际支付金额 */} Total { selectedPayment === 'Paypal' && selectedCurrency !== user.currency && ( {( (previewOrder?.total_amount || 0) + (createOrderData?.domestic_shipping_fee || 0) + (createOrderData?.shipping_fee || 0) ).toFixed(2)}{" "} {previewOrder?.currency} {convertedAmount}{selectedCurrency === "USD" ? "USD" : "EUR"} ) } { selectedPayment === 'Paypal' && selectedCurrency === user.currency && ( {( (previewOrder?.total_amount || 0) + (createOrderData?.domestic_shipping_fee || 0) + (createOrderData?.shipping_fee || 0) ).toFixed(2)}{" "} {previewOrder?.currency} ) } { selectedPayment !== 'Paypal'&& ( {( (previewOrder?.total_amount || 0) + (createOrderData?.domestic_shipping_fee || 0) + (createOrderData?.shipping_fee || 0) ).toFixed(2)}{" "} {previewOrder?.currency} ) } {createLoading ? '创建中...' : '创建订单'} )} ); }; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", marginTop: 10, }, sectionHeader: { flexDirection: "row", alignItems: "center", marginBottom: 15, paddingHorizontal: 15, }, sectionIcon: { fontSize: fontSize(20), marginRight: 8, }, sectionTitle: { fontSize: fontSize(18), fontWeight: "600", color: "#000", }, tabContainer: { flexDirection: "row", marginBottom: 15, borderBottomWidth: 1, borderBottomColor: "#EEEEEE", paddingHorizontal: 15, }, tabButton: { paddingVertical: 10, paddingHorizontal: 15, marginRight: 10, }, tabButtonActive: { borderBottomWidth: 2, borderBottomColor: "#FF5100", }, tabText: { fontSize: fontSize(16), color: "#666", }, tabTextActive: { color: "#FF5100", fontWeight: "500", }, paymentOptions: { marginBottom: 15, paddingHorizontal: 15, }, paymentOption: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", padding: 15, backgroundColor: "#F8F8F8", borderRadius: 8, marginBottom: 10, }, paymentSelected: { backgroundColor: "#FFF0E8", borderWidth: 1, borderColor: "#FF5100", }, paymentContent: { flex: 1, }, defaultPaymentContainer: { flexDirection: "row", alignItems: "center", }, paymentIcon: { fontSize: fontSize(24), marginRight: 8, }, paymentLabel: { fontSize: fontSize(16), fontWeight: "500", }, operatorContainer: { flexDirection: "row", flexWrap: "wrap", marginTop: 8, }, operatorBox: { backgroundColor: "#fff", paddingVertical: 4, paddingHorizontal: 8, borderRadius: 4, marginRight: 8, marginBottom: 4, }, operatorText: { fontSize: fontSize(12), color: "#666", }, radioButton: { width: 20, height: 20, borderRadius: 10, borderWidth: 1, borderColor: "#CCCCCC", justifyContent: "center", alignItems: "center", }, radioInner: { width: 12, height: 12, borderRadius: 6, backgroundColor: "transparent", }, radioInnerSelected: { backgroundColor: "#FF5100", }, titleContainer: { width: "100%", padding: 15, flexDirection: "row", alignItems: "center", justifyContent: "center", position: "relative", backgroundColor: "#fff", }, backIconContainer: { position: "absolute", left: 15, backgroundColor: "#fff", }, titleHeading: { fontWeight: "600", fontSize: 20, lineHeight: 22, fontFamily: "PingFang SC", color: "black", }, // Order Summary Styles section: { backgroundColor: "#fff", borderRadius: 8, paddingHorizontal: 15, marginTop: 15, }, section1: { backgroundColor: "#fff", borderRadius: 8, overflow: "hidden", }, sectionHeader1: { flexDirection: "row", alignItems: "center", paddingTop: 12, paddingBottom: 12, borderBottomWidth: 1, borderBottomColor: "#f5f5f5", }, sectionIcon1: { fontSize: fontSize(18), marginRight: 10, color: "#666", }, sectionTitle1: { fontSize: fontSize(15), fontWeight: "500", flex: 1, }, setOrderContent: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", paddingTop: 12, paddingBottom: 12, paddingHorizontal: 12, }, sectionAction: { color: "#ff6000", fontSize: fontSize(13), fontWeight: "500", }, noCouponsMessage: { color: "#888", fontSize: fontSize(13), }, orderItems: { maxHeight: 0, overflow: "hidden", }, orderItemsExpanded: { maxHeight: 1000, // Arbitrary large number to accommodate all items }, orderItem: { flexDirection: "row", padding: 16, borderBottomWidth: 1, borderBottomColor: "#f5f5f5", }, itemImage: { width: widthUtils(70, 70).width, height: widthUtils(70, 70).height, borderRadius: 6, marginRight: 12, borderWidth: 1, borderColor: "#eee", }, itemImagePlaceholder: { width: widthUtils(70, 70).width, height: widthUtils(70, 70).height, borderRadius: 6, marginRight: 12, borderWidth: 1, borderColor: "#eee", backgroundColor: "#f1f1f1", }, itemDetails: { flex: 1, }, itemName: { fontSize: fontSize(14), lineHeight: 18, }, itemVariant: { fontSize: fontSize(12), color: "#666", backgroundColor: "#f7f7f7", paddingVertical: 3, paddingHorizontal: 6, borderRadius: 4, marginTop: 6, alignSelf: "flex-start", }, itemQuantity: { fontSize: fontSize(12), color: "#666", marginTop: 4, }, itemPrices: { alignItems: "flex-end", fontSize: fontSize(13), color: "#555", }, itemPrice: { fontWeight: "600", color: "#ff6000", fontSize: fontSize(15), marginBottom: 5, }, priceBox: { borderRadius: 10, marginTop: 15, paddingHorizontal: 15, }, priceBox1: { justifyContent: "space-between", flexDirection: "row", alignItems: "center", padding: 12, borderBottomWidth: 1, borderBottomColor: "#f5f5f5", }, actualPaymentBox: { padding: 12, borderRadius: 6, backgroundColor: "#fff8f4", marginTop: 15, marginHorizontal: 15, marginBottom: 20, }, actualPaymentBox1: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", }, loadingContainer: { flex: 1, justifyContent: "center", alignItems: "center", backgroundColor: "#fff", }, submitButtonContainer: { paddingRight: 11, paddingLeft: 11, marginTop: 20, marginBottom: 20, }, primaryButtonStyle: { width: "100%", height: 50, justifyContent: "center", alignItems: "center", fontWeight: "600", fontSize: 16, lineHeight: 22, fontFamily: "PingFang SC", color: "white", backgroundColor: "#002fa7", borderWidth: 0, borderRadius: 25, }, buttonText: { color: "white", fontWeight: "600", fontSize: 16, lineHeight: 22, fontFamily: "PingFang SC", }, selectedCountryText: { padding: 0, margin: 0, fontWeight: "500", fontSize: 16, lineHeight: 22, fontFamily: "PingFang SC", color: "#646472", }, disabledButtonStyle: { backgroundColor: "#ccc", }, currencySelectorContainer: { padding: 15, backgroundColor: "#f9f9f9", borderRadius: 8, marginTop: 5, marginBottom: 15, }, currencySelectorTitle: { fontSize: fontSize(16), fontWeight: "600", color: "#000", marginBottom: 15, }, currencyOptions: { flexDirection: "row", marginBottom: 15, }, currencyOption: { flex: 1, padding: 15, borderWidth: 1, borderColor: "#DDDDDD", borderRadius: 4, marginRight: 10, alignItems: "center", justifyContent: "center", }, selectedCurrencyOption: { borderColor: "#002fa7", backgroundColor: "#fff", }, currencyText: { fontSize: fontSize(16), fontWeight: "500", color: "#000", }, exchangeRateContainer: { marginBottom: 15, }, exchangeRateText: { fontSize: fontSize(14), color: "#666", marginBottom: 5, }, totalContainer: { marginTop: 10, borderTopWidth: 1, borderTopColor: "#EEEEEE", paddingTop: 10, flexDirection: 'row', alignItems: 'center', }, totalText: { fontSize: fontSize(16), fontWeight: "600", color: "#ff6000", }, loadingIndicator: { marginLeft: 10, }, });