Browse Source

feat: 完善支付功能 - 添加国家选择和电话号码格式化

main
unknown 2 weeks ago
parent
commit
2abf8c230a
  1. 17
      app/screens/BalanceScreen/PhoneNumberInputModal.tsx
  2. 9
      app/screens/BalanceScreen/RechargeScreen.tsx
  3. 204
      app/screens/previewOrder/PaymentMethod.tsx
  4. 290
      app/screens/previewOrder/perviewOrder.tsx
  5. 101
      app/screens/productStatus/OrderDatails.tsx

17
app/screens/BalanceScreen/PhoneNumberInputModal.tsx

@ -131,7 +131,18 @@ const PhoneNumberInputModal = ({
</Text>
</View>
{paymentParams?.currency !== "FCFA" && (
{paymentParams?.payment_method === "wave" && (
<View style={styles.paymentSummaryRow}>
<Text style={styles.paymentSummaryLabel}>
Montant converti:
</Text>
<Text style={styles.paymentSummaryValueHighlight}>
{paymentParams?.amount.toFixed(2)} FCFA
</Text>
</View>
)}
{paymentParams?.currency !== "FCFA" && paymentParams?.payment_method !== "wave" && (
<View style={styles.paymentSummaryRow}>
<Text style={styles.paymentSummaryLabel}>
{t('balance.phone_modal.converted_amount')}
@ -212,7 +223,9 @@ const PhoneNumberInputModal = ({
) : (
<Text style={styles.payButtonText}>
{t('balance.phone_modal.pay')}{" "}
{paymentParams?.currency === "FCFA"
{paymentParams?.payment_method === "wave"
? paymentParams.amount.toFixed(2) + " FCFA"
: paymentParams?.currency === "FCFA"
? paymentParams.originalAmount.toLocaleString() +
" " +
paymentParams.currency

9
app/screens/BalanceScreen/RechargeScreen.tsx

@ -273,8 +273,8 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
// 如果没有转换结果,使用原始金额作为备用
params.amount = parseFloat(selectedPrice.replace(/,/g, ""));
}
// 更新显示标签为FCFA
params.selectedPriceLabel = params.amount + " FCFA";
// selectedPriceLabel 保持显示原始美元金额
// params.selectedPriceLabel 已经在上面设置为原始金额,不需要修改
}
} else if (selectedOperator === "balance") {
params.payment_method = "Balance";
@ -296,6 +296,9 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
// 保存支付参数
setPaymentParams(params);
console.log(params);
setShowPhoneModal(true);
}
};
@ -914,7 +917,7 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
(item) => item.item_key === "total_amount"
)
?.converted_amount.toFixed(2)}{" "}
FCFA
{currentCurrency}
</Text>
</View>
) : null}

204
app/screens/previewOrder/PaymentMethod.tsx

@ -77,6 +77,7 @@ const PaymentMethodItem = ({
convertedAmount,
isConverting,
isPaypalExpanded,
isWaveExpanded,
}: {
option: PaymentOption;
isSelected: boolean;
@ -95,6 +96,7 @@ const PaymentMethodItem = ({
}[];
isConverting?: boolean;
isPaypalExpanded?: boolean;
isWaveExpanded?: boolean;
}) => {
const { t } = useTranslation();
const { user } = useUserStore();
@ -231,6 +233,60 @@ const PaymentMethodItem = ({
</View>
</View>
)}
{/* Show Wave expanded view */}
{isSelected &&
option.key === "wave" &&
isWaveExpanded &&
convertedAmount &&
convertedAmount.length > 0 && (
<View style={styles.paypalExpandedContainer}>
<View style={styles.paypalCurrencyContainer}>
<Text style={styles.currencyTitle}>
{t("order.select_currency") || "Select Currency"}
</Text>
<View style={styles.currencyButtonsContainer}>
<TouchableOpacity
style={[
styles.currencyButton,
styles.currencyButtonActive,
]}
>
<Text
style={[
styles.currencyButtonText,
styles.currencyButtonTextActive,
]}
>
FCFA
</Text>
</TouchableOpacity>
</View>
{/* Display converted amount */}
{isConverting ? (
<View style={styles.convertingContainer}>
<ActivityIndicator size="small" color="#007efa" />
<Text style={styles.convertingText}>
{t("order.converting") || "Converting..."}
</Text>
</View>
) : (
<View style={styles.convertedAmountContainer}>
<Text style={styles.convertedAmountLabel}>
{t("order.equivalent_amount") || "Equivalent Amount:"}
</Text>
<Text style={styles.convertedAmountValue}>
{convertedAmount
.reduce((acc, item) => acc + item.converted_amount, 0)
.toFixed(2)}{" "}
FCFA
</Text>
</View>
)}
</View>
</View>
)}
</View>
);
};
@ -275,15 +331,22 @@ export const PaymentMethod = () => {
});
const [totalAmount, setTotalAmount] = useState(121.97);
const { logPaymentConfirm } = useBurialPointStore();
const [isWaveExpanded, setIsWaveExpanded] = useState(false);
const toggleExpanded = () => {
setIsPaypalExpanded(!isPaypalExpanded);
};
const onSelectPayment = (paymentId: string) => {
if (paymentId === selectedPayment) {
// If clicking on already selected paypal, toggle expansion
if (paymentId === "paypal") {
setIsPaypalExpanded(!isPaypalExpanded);
}
// If clicking on already selected wave, toggle expansion
if (paymentId === "wave") {
setIsWaveExpanded(!isWaveExpanded);
}
return;
}
@ -292,11 +355,43 @@ export const PaymentMethod = () => {
// Auto-expand paypal when selecting it
if (paymentId === "paypal") {
setIsPaypalExpanded(true);
setIsWaveExpanded(false);
setIsConverting(true);
// Reset to USD when selecting PayPal
setSelectedCurrency("USD");
const data = {
from_currency: user.currency,
to_currency: selectedCurrency,
to_currency: "USD",
amounts: {
total_amount: previewOrder?.total_amount || 0,
domestic_shipping_fee: createOrderData?.domestic_shipping_fee || 0,
shipping_fee: createOrderData?.shipping_fee || 0,
},
};
payApi
.convertCurrency(data)
.then((res) => {
setConvertedAmount(res.converted_amounts_list);
setIsConverting(false);
})
.catch((error) => {
console.error("Currency conversion failed:", error);
setIsConverting(false);
});
} else if (paymentId === "wave") {
// Auto-expand wave when selecting it
setIsWaveExpanded(true);
setIsPaypalExpanded(false);
setIsConverting(true);
setSelectedCurrency("FCFA");
const data = {
from_currency: user.currency,
to_currency: "FCFA",
amounts: {
total_amount: previewOrder?.total_amount || 0,
domestic_shipping_fee: createOrderData?.domestic_shipping_fee || 0,
@ -315,10 +410,12 @@ export const PaymentMethod = () => {
setIsConverting(false);
});
} else {
// Close expansion for non-paypal options
// Close expansion for non-paypal and non-wave options
setIsPaypalExpanded(false);
setIsWaveExpanded(false);
}
};
const onSelectCurrency = (currency: string) => {
setSelectedCurrency(currency);
setIsConverting(true);
@ -342,6 +439,7 @@ export const PaymentMethod = () => {
setIsConverting(false);
});
};
const getPaymentMethods = async () => {
try {
setLoading(true);
@ -386,6 +484,7 @@ export const PaymentMethod = () => {
setLoading(false);
}
};
const getPaymentIcon = (key: string): string => {
switch (key) {
case "Brainnel Pay(Mobile Money)":
@ -400,9 +499,11 @@ export const PaymentMethod = () => {
return "💰";
}
};
useEffect(() => {
getPaymentMethods();
}, []);
useEffect(() => {
setLoading(true);
if (route.params?.freight_forwarder_address_id) {
@ -422,6 +523,7 @@ export const PaymentMethod = () => {
});
}
}, [route.params?.freight_forwarder_address_id]);
useEffect(() => {
setCreateOrderData({
...orderData,
@ -433,6 +535,7 @@ export const PaymentMethod = () => {
});
console.log("orderData", orderData);
}, [orderData]);
const handleSubmit = async () => {
if (!selectedPayment) {
Alert.alert(t("payment.select_payment"));
@ -461,6 +564,11 @@ export const PaymentMethod = () => {
createOrderData.payment_method = selectedPayment;
createOrderData.total_amount =
selectedPayment === "paypal"
? convertedAmount.reduce(
(acc, item) => acc + item.converted_amount,
0
)
: selectedPayment === "wave"
? convertedAmount.reduce(
(acc, item) => acc + item.converted_amount,
0
@ -474,6 +582,11 @@ export const PaymentMethod = () => {
);
createOrderData.actual_amount =
selectedPayment === "paypal"
? convertedAmount.reduce(
(acc, item) => acc + item.converted_amount,
0
)
: selectedPayment === "wave"
? convertedAmount.reduce(
(acc, item) => acc + item.converted_amount,
0
@ -486,15 +599,22 @@ export const PaymentMethod = () => {
).toFixed(2)
);
createOrderData.currency =
selectedPayment === "paypal" ? selectedCurrency : user.currency;
selectedPayment === "paypal" ? selectedCurrency : selectedPayment === "wave" ? "FCFA" : user.currency;
createOrderData.domestic_shipping_fee =
selectedPayment === "paypal"
? convertedAmount.find(
(item) => item.item_key === "domestic_shipping_fee"
)?.converted_amount || 0
: selectedPayment === "wave"
? convertedAmount.find(
(item) => item.item_key === "domestic_shipping_fee"
)?.converted_amount || 0
: orderData?.domestic_shipping_fee;
createOrderData.shipping_fee =
selectedPayment === "paypal"
? convertedAmount.find((item) => item.item_key === "shipping_fee")
?.converted_amount || 0
: selectedPayment === "wave"
? convertedAmount.find((item) => item.item_key === "shipping_fee")
?.converted_amount || 0
: orderData?.shipping_fee;
@ -505,6 +625,11 @@ export const PaymentMethod = () => {
offline_payment: currentTab === "offline" ? 0 : 1,
all_price:
selectedPayment === "paypal"
? convertedAmount.reduce(
(acc, item) => acc + item.converted_amount,
0
)
: selectedPayment === "wave"
? convertedAmount.reduce(
(acc, item) => acc + item.converted_amount,
0
@ -520,7 +645,7 @@ export const PaymentMethod = () => {
(acc, item) => acc + item.quantity,
0
),
currency: selectedCurrency,
currency: selectedPayment === "paypal" ? selectedCurrency : selectedPayment === "wave" ? "FCFA" : user.currency,
shipping_method: orderData?.transport_type || 0,
shipping_price_outside: orderData?.shipping_fee || 0,
shipping_price_within: orderData?.domestic_shipping_fee || 0,
@ -566,9 +691,14 @@ export const PaymentMethod = () => {
data: res,
payMethod: selectedPayment,
currency:
selectedPayment === "paypal" ? selectedCurrency : user.currency,
selectedPayment === "paypal" ? selectedCurrency : selectedPayment === "wave" ? "FCFA" : user.currency,
amount:
selectedPayment === "paypal"
? convertedAmount.reduce(
(acc, item) => acc + item.converted_amount,
0
)
: selectedPayment === "wave"
? convertedAmount.reduce(
(acc, item) => acc + item.converted_amount,
0
@ -660,6 +790,7 @@ export const PaymentMethod = () => {
convertedAmount={convertedAmount}
isConverting={isConverting}
isPaypalExpanded={isPaypalExpanded}
isWaveExpanded={isWaveExpanded}
/>
))}
</View>
@ -734,6 +865,10 @@ export const PaymentMethod = () => {
<View>
<Text>
{selectedPayment === "paypal"
? convertedAmount.find(
(item) => item.item_key === "total_amount"
)?.converted_amount || 0
: selectedPayment === "wave"
? convertedAmount.find(
(item) => item.item_key === "total_amount"
)?.converted_amount || 0
@ -742,6 +877,8 @@ export const PaymentMethod = () => {
? selectedCurrency === "USD"
? "USD"
: "EUR"
: selectedPayment === "wave"
? "FCFA"
: previewOrder?.currency}
</Text>
</View>
@ -751,6 +888,10 @@ export const PaymentMethod = () => {
<View>
<Text>
{selectedPayment === "paypal"
? convertedAmount.find(
(item) => item.item_key === "domestic_shipping_fee"
)?.converted_amount || 0
: selectedPayment === "wave"
? convertedAmount.find(
(item) => item.item_key === "domestic_shipping_fee"
)?.converted_amount || 0
@ -759,6 +900,8 @@ export const PaymentMethod = () => {
? selectedCurrency === "USD"
? "USD"
: "EUR"
: selectedPayment === "wave"
? "FCFA"
: previewOrder?.currency}
</Text>
</View>
@ -768,6 +911,10 @@ export const PaymentMethod = () => {
<View>
<Text>
{selectedPayment === "paypal"
? convertedAmount.find(
(item) => item.item_key === "shipping_fee"
)?.converted_amount || 0
: selectedPayment === "wave"
? convertedAmount.find(
(item) => item.item_key === "shipping_fee"
)?.converted_amount || 0
@ -776,6 +923,8 @@ export const PaymentMethod = () => {
? selectedCurrency === "USD"
? "USD"
: "EUR"
: selectedPayment === "wave"
? "FCFA"
: previewOrder?.currency}
</Text>
</View>
@ -849,7 +998,42 @@ export const PaymentMethod = () => {
</Text>
</View>
)}
{selectedPayment !== "paypal" && (
{selectedPayment === "wave" && (
<View style={{ flexDirection: "row" }}>
<Text
style={{
fontSize: fontSize(18),
fontWeight: "600",
color: "#151515",
textDecorationLine: "line-through",
}}
>
{(
(previewOrder?.total_amount || 0) +
(createOrderData?.domestic_shipping_fee || 0) +
(createOrderData?.shipping_fee || 0)
).toFixed(2)}{" "}
{previewOrder?.currency}
</Text>
<Text
style={{
fontSize: fontSize(18),
fontWeight: "600",
color: "#ff6000",
marginLeft: 10,
}}
>
{convertedAmount
.reduce(
(acc, item) => acc + item.converted_amount,
0
)
.toFixed(2)}{" "}
FCFA
</Text>
</View>
)}
{selectedPayment !== "paypal" && selectedPayment !== "wave" && (
<Text
style={{
fontSize: fontSize(18),
@ -873,11 +1057,15 @@ export const PaymentMethod = () => {
<TouchableOpacity
style={[
styles.submitButton,
(!selectedPayment || createLoading || isConverting) &&
(!selectedPayment || createLoading || isConverting ||
(selectedPayment === "paypal" && (convertedAmount.length === 0 || !convertedAmount.find(item => item.item_key === "total_amount"))) ||
(selectedPayment === "wave" && (convertedAmount.length === 0 || !convertedAmount.find(item => item.item_key === "total_amount")))) &&
styles.disabledButton,
]}
onPress={handleSubmit}
disabled={!selectedPayment || createLoading || isConverting}
disabled={!selectedPayment || createLoading || isConverting ||
(selectedPayment === "paypal" && (convertedAmount.length === 0 || !convertedAmount.find(item => item.item_key === "total_amount"))) ||
(selectedPayment === "wave" && (convertedAmount.length === 0 || !convertedAmount.find(item => item.item_key === "total_amount")))}
>
{createLoading ? (
<ActivityIndicator size="small" color="#fff" />

290
app/screens/previewOrder/perviewOrder.tsx

@ -12,6 +12,8 @@ import {
StatusBar,
SafeAreaView,
BackHandler,
Modal,
FlatList,
} from "react-native";
import useCreateOrderStore from "../../store/createOrder";
import BackIcon from "../../components/BackIcon";
@ -20,12 +22,15 @@ import {
useRoute,
RouteProp,
useFocusEffect,
CommonActions,
} from "@react-navigation/native";
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { useState, useEffect } from "react";
import useUserStore from "../../store/user";
import { Order } from "../../services/api/orders";
import { payApi } from "../../services/api/payApi";
import { settingApi } from "../../services/api/setting";
import { CountryList } from "../../constants/countries";
import { useTranslation } from "react-i18next";
import fontSize from "../../utils/fontsizeUtils";
import { getBurialPointData } from "../../store/burialPoint";
@ -42,6 +47,7 @@ type RootStackParamList = {
Pay: { payUrl: string; method: string; order_id: string };
OrderDetails: { orderId?: number };
PaymentSuccessScreen: any;
MainTabs: undefined;
};
export const PreviewOrder = () => {
@ -50,6 +56,10 @@ export const PreviewOrder = () => {
useNavigation<NativeStackNavigationProp<RootStackParamList>>();
const [phoneNumber, setPhoneNumber] = useState("");
const [showPhoneInput, setShowPhoneInput] = useState(false);
const [countryList, setCountryList] = useState<CountryList[]>([]);
const [selectedCountry, setSelectedCountry] = useState<CountryList | null>(null);
const [showCountryModal, setShowCountryModal] = useState(false);
const [loadingCountries, setLoadingCountries] = useState(false);
const route = useRoute<RouteProp<RootStackParamList, "PreviewOrder">>();
const [loading, setLoading] = useState(false);
const { user } = useUserStore();
@ -61,11 +71,58 @@ export const PreviewOrder = () => {
}
if (route.params.payMethod === "mobile_money") {
setShowPhoneInput(true);
// 获取国家列表
loadCountryList();
} else {
setShowPhoneInput(false);
}
}, [route.params.payMethod, user.user_id, t]);
// 获取国家列表
const loadCountryList = async () => {
setLoadingCountries(true);
try {
const response = await settingApi.getSendSmsCountryList();
if (response && Array.isArray(response)) {
setCountryList(response);
// 如果用户有国家信息,自动选择对应的国家
if (user?.country_en) {
const userCountry = response.find((country: CountryList) =>
country.name_en.toLowerCase() === user.country_en.toLowerCase()
);
if (userCountry) {
setSelectedCountry(userCountry);
}
}
}
} catch (error) {
console.error('获取国家列表失败:', error);
} finally {
setLoadingCountries(false);
}
};
// 格式化电话号码
const formatPhoneNumber = (phone: string, country: CountryList | null): string => {
if (!phone || !country) return phone;
// 移除电话号码中的空格、破折号等
const cleanPhone = phone.replace(/[\s\-\(\)]/g, '');
// 如果已经有+号开头,直接返回
if (cleanPhone.startsWith('+')) {
return cleanPhone;
}
// 使用 country 字段作为国家代码
const countryCode = `+${country.country}`;
// 如果电话号码以0开头,移除0
const phoneWithoutLeadingZero = cleanPhone.startsWith('0') ? cleanPhone.substring(1) : cleanPhone;
return `${countryCode}${phoneWithoutLeadingZero}`;
};
// 处理系统返回键
useFocusEffect(
React.useCallback(() => {
@ -85,13 +142,22 @@ export const PreviewOrder = () => {
const handleSubmit = () => {
if (showPhoneInput && !phoneNumber) {
// Show error or alert if needed
console.log("Phone number is required for Mobile Money");
Alert.alert(t("error"), t("order.preview.phone_required") || "Phone number is required for Mobile Money");
return;
}
if (showPhoneInput && !selectedCountry) {
Alert.alert(t("error"), "请选择国家");
return;
}
console.log(route.params.currency);
// 格式化电话号码,添加国家前缀
const formattedPhone = showPhoneInput && phoneNumber
? formatPhoneNumber(phoneNumber, selectedCountry)
: '';
const data = {
order_id: route.params.data.order_id,
method: route.params.payMethod,
@ -99,32 +165,53 @@ export const PreviewOrder = () => {
? route.params.currency
: route.params.data.currency,
amount: route.params.data.actual_amount,
...(showPhoneInput && formattedPhone && {
extra: { phone_number: formattedPhone }
}),
};
console.log('发送的电话号码:', formattedPhone);
setLoading(true);
payApi
.getPayInfo(data)
.then((res) => {
if (res.success) {
if (route.params.payMethod === "balance") {
if (res.success) {
navigation.navigate("PaymentSuccessScreen", res);
return;
} else {
Alert.alert(t("order.preview.Insufficient_balance"));
}
}
// 记录埋点数据
logPreviewOrder(
navigation.getState().routes[navigation.getState().index - 1]
?.name as string
);
console.log(getBurialPointData());
console.log("埋点数据: " +getBurialPointData());
navigation.replace("Pay", {
payUrl: res.payment_url,
method: route.params.payMethod,
order_id: route.params.data.order_id.toString(),
});
// 所有成功的支付都跳转到 ProfileScreen
navigation.dispatch(
CommonActions.reset({
index: 0,
routes: [
{
name: 'MainTabs',
state: {
routes: [
{ name: 'Home' },
{ name: 'productCollection' },
{ name: 'Chat' },
{ name: 'Cart' },
{ name: 'Profile' },
],
index: 4, // Profile tab 的索引
},
},
],
})
);
} else {
// 处理失败情况
if (route.params.payMethod === "balance") {
Alert.alert(t("order.preview.Insufficient_balance"));
} else {
Alert.alert(t("order.preview.payment_failed"));
}
}
})
.catch((err) => {
@ -134,12 +221,6 @@ export const PreviewOrder = () => {
.finally(() => {
setLoading(false);
});
// navigation.navigate('Pay', {
// orderId: user.user_id,
// payMethod: route.params.payMethod,
// })
};
return (
@ -177,6 +258,30 @@ export const PreviewOrder = () => {
<Text style={styles.phoneInputLabel}>
{t("order.preview.enter_phone")}
</Text>
{/* 电话号码输入行 - 国家选择器在左侧 */}
<View style={styles.phoneInputRow}>
{/* 国家代码选择器 */}
<TouchableOpacity
style={styles.countryCodeSelector}
onPress={() => setShowCountryModal(true)}
disabled={loadingCountries}
>
<Text style={styles.countryCodeText}>
{loadingCountries
? "..."
: selectedCountry
? `+${selectedCountry.country}`
: '+86'
}
</Text>
<Text style={styles.countryCodeArrow}></Text>
</TouchableOpacity>
{/* 分隔线 */}
<View style={styles.phoneSeparator} />
{/* 电话号码输入框 */}
<TextInput
style={styles.phoneInput}
value={phoneNumber}
@ -185,6 +290,7 @@ export const PreviewOrder = () => {
keyboardType="phone-pad"
/>
</View>
</View>
)}
</View>
@ -280,12 +386,12 @@ export const PreviewOrder = () => {
<TouchableOpacity
style={[
styles.primaryButtonStyle,
(!showPhoneInput || (showPhoneInput && phoneNumber)) && !loading
(!showPhoneInput || (showPhoneInput && phoneNumber && selectedCountry)) && !loading
? {}
: styles.disabledButtonStyle,
]}
onPress={handleSubmit}
disabled={(showPhoneInput && !phoneNumber) || loading}
disabled={(showPhoneInput && (!phoneNumber || !selectedCountry)) || loading}
>
{loading ? (
<ActivityIndicator size="small" color="#ffffff" />
@ -298,6 +404,53 @@ export const PreviewOrder = () => {
</View>
</View>
</View>
{/* 国家选择模态框 */}
<Modal
visible={showCountryModal}
animationType="slide"
transparent={true}
onRequestClose={() => setShowCountryModal(false)}
>
<View style={styles.modalOverlay}>
<View style={styles.modalContent}>
<View style={styles.modalHeader}>
<Text style={styles.modalTitle}></Text>
<TouchableOpacity
onPress={() => setShowCountryModal(false)}
style={styles.modalCloseButton}
>
<Text style={styles.modalCloseText}></Text>
</TouchableOpacity>
</View>
<FlatList
data={countryList}
keyExtractor={(item) => item.country.toString()}
renderItem={({ item }) => (
<TouchableOpacity
style={[
styles.countryItem,
selectedCountry?.country === item.country && styles.selectedCountryItem
]}
onPress={() => {
setSelectedCountry(item);
setShowCountryModal(false);
}}
>
<Text style={[
styles.countryItemText,
selectedCountry?.country === item.country && styles.selectedCountryItemText
]}>
{item.name_en} (+{item.country})
</Text>
</TouchableOpacity>
)}
style={styles.countryList}
/>
</View>
</View>
</Modal>
</SafeAreaView>
);
};
@ -411,11 +564,11 @@ const styles = StyleSheet.create({
color: "#333",
},
phoneInput: {
borderWidth: 1,
borderColor: "#ddd",
borderRadius: 5,
padding: 10,
flex: 1,
paddingHorizontal: 12,
paddingVertical: 15,
fontSize: fontSize(15),
color: "#333",
},
infoRow: {
flexDirection: "row",
@ -454,4 +607,85 @@ const styles = StyleSheet.create({
color: "#002fa7",
fontFamily: "PingFang SC",
},
phoneInputRow: {
flexDirection: "row",
alignItems: "center",
borderWidth: 1,
borderColor: "#ddd",
borderRadius: 5,
overflow: "hidden",
},
countryCodeSelector: {
paddingHorizontal: 12,
paddingVertical: 15,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
minWidth: 80,
backgroundColor: "#f8f8f8",
},
countryCodeText: {
fontSize: fontSize(15),
color: "#333",
fontWeight: "600",
marginRight: 5,
},
countryCodeArrow: {
fontSize: fontSize(10),
color: "#666",
},
phoneSeparator: {
width: 1,
height: 30,
backgroundColor: "#ddd",
},
modalOverlay: {
flex: 1,
backgroundColor: "rgba(0, 0, 0, 0.5)",
justifyContent: "center",
alignItems: "center",
},
modalContent: {
backgroundColor: "white",
padding: 20,
borderRadius: 20,
width: "80%",
maxHeight: "80%",
},
modalHeader: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
marginBottom: 10,
},
modalTitle: {
fontSize: fontSize(18),
fontWeight: "600",
},
modalCloseButton: {
padding: 5,
},
modalCloseText: {
fontSize: fontSize(16),
fontWeight: "600",
},
countryItem: {
padding: 10,
borderWidth: 1,
borderColor: "#ddd",
borderRadius: 5,
},
selectedCountryItem: {
backgroundColor: "#002fa7",
},
countryItemText: {
fontSize: fontSize(15),
color: "#333",
},
countryList: {
flex: 1,
},
selectedCountryItemText: {
color: "white",
},
});

101
app/screens/productStatus/OrderDatails.tsx

@ -226,6 +226,7 @@ export const OrderDetails = () => {
const { user } = useUserStore();
const [isPaymentLoading, setIsPaymentLoading] = useState(false);
const [isPaypalExpanded, setIsPaypalExpanded] = useState(false);
const [isWaveExpanded, setIsWaveExpanded] = useState(false);
const [paymentParams, setPaymentParams] = useState<{
originalAmount: number;
amount: number;
@ -304,6 +305,7 @@ export const OrderDetails = () => {
const onSelectPayment = (paymentId: string) => {
if (paymentId !== selectedPayment) {
setIsPaypalExpanded(false);
setIsWaveExpanded(false);
}
setSelectedPayment(paymentId);
@ -324,6 +326,32 @@ export const OrderDetails = () => {
},
};
payApi
.convertCurrency(data)
.then((res) => {
setConvertedAmount(res.converted_amounts_list);
setIsConverting(false);
})
.catch((error) => {
console.error("Currency conversion failed:", error);
setIsConverting(false);
});
} else if (paymentId === "wave" && paymentId !== selectedPayment) {
setIsWaveExpanded(true);
setIsConverting(true);
setSelectedCurrency("FCFA");
const data = {
from_currency: orderDetails?.currency || "",
to_currency: "FCFA",
amounts: {
total_amount: orderDetails?.total_amount || 0,
domestic_shipping_fee: orderDetails?.domestic_shipping_fee || 0,
shipping_fee: orderDetails?.shipping_fee || 0,
},
};
payApi
.convertCurrency(data)
.then((res) => {
@ -386,28 +414,28 @@ export const OrderDetails = () => {
const paymentData = {
order_id: orderDetails.order_id,
payment_method: selectedPayment,
currency: selectedPayment === "paypal" ? selectedCurrency : user.currency,
currency: selectedPayment === "paypal" ? selectedCurrency : selectedPayment === "wave" ? "FCFA" : user.currency,
total_amount:
selectedPayment === "paypal"
selectedPayment === "paypal" || selectedPayment === "wave"
? convertedAmount.reduce(
(acc, item) => acc + item.converted_amount,
0
)
: orderDetails?.total_amount || 0,
actual_amount:
selectedPayment === "paypal"
selectedPayment === "paypal" || selectedPayment === "wave"
? convertedAmount.reduce(
(acc, item) => acc + item.converted_amount,
0
)
: orderDetails?.actual_amount || 0,
shipping_fee:
selectedPayment === "paypal"
selectedPayment === "paypal" || selectedPayment === "wave"
? convertedAmount.find((item) => item.item_key === "shipping_fee")
?.converted_amount || 0
: orderDetails?.shipping_fee || 0,
domestic_shipping_fee:
selectedPayment === "paypal"
selectedPayment === "paypal" || selectedPayment === "wave"
? convertedAmount.find(
(item) => item.item_key === "domestic_shipping_fee"
)?.converted_amount || 0
@ -420,9 +448,9 @@ export const OrderDetails = () => {
order_id: orderDetails.order_id,
method: selectedPayment,
currency:
selectedPayment === "paypal" ? selectedCurrency : user.currency,
selectedPayment === "paypal" ? selectedCurrency : selectedPayment === "wave" ? "FCFA" : user.currency,
amount:
selectedPayment === "paypal"
selectedPayment === "paypal" || selectedPayment === "wave"
? convertedAmount.reduce(
(acc, item) => acc + item.converted_amount,
0
@ -550,6 +578,15 @@ export const OrderDetails = () => {
return true;
}
// 如果选择了Wave支付方式,但还没有转换结果,禁用按钮
if (
selectedPayment === "wave" &&
(convertedAmount.length === 0 ||
!convertedAmount.find((item) => item.item_key === "total_amount"))
) {
return true;
}
// 其他情况下,启用按钮
return false;
};
@ -1210,6 +1247,56 @@ export const OrderDetails = () => {
</View>
</View>
)}
{/* Wave Currency Selection */}
{selectedPayment === "wave" &&
option.id === "wave" &&
isWaveExpanded && (
<View style={styles.paypalExpandedContainer}>
<View style={styles.paypalCurrencyContainer}>
<Text style={styles.currencyTitle}>
{t("order.select_currency") ||
"Select Currency"}
</Text>
<View style={styles.currencyButtonsContainer}>
<View style={[styles.currencyButton, styles.currencyButtonActive]}>
<Text style={[styles.currencyButtonText, styles.currencyButtonTextActive]}>
FCFA
</Text>
</View>
</View>
{/* 显示转换后的金额 */}
{isConverting ? (
<View style={styles.convertingContainer}>
<ActivityIndicator
size="small"
color="#007efa"
/>
<Text style={styles.convertingText}>
{t("order.converting") || "Converting..."}
</Text>
</View>
) : convertedAmount.length > 0 ? (
<View style={styles.convertedAmountContainer}>
<Text style={styles.convertedAmountLabel}>
{t("order.equivalent_amount") ||
"Equivalent Amount:"}
</Text>
<Text style={styles.convertedAmountValue}>
{convertedAmount
.find(
(item) =>
item.item_key === "total_amount"
)
?.converted_amount.toFixed(2)}{" "}
FCFA
</Text>
</View>
) : null}
</View>
</View>
)}
</View>
))}
</>

Loading…
Cancel
Save