|
|
|
@ -17,12 +17,13 @@ import {
|
|
|
|
|
TextStyle, |
|
|
|
|
ImageStyle, |
|
|
|
|
StyleProp, |
|
|
|
|
FlatList, |
|
|
|
|
} from "react-native"; |
|
|
|
|
import { useTranslation } from "react-i18next"; |
|
|
|
|
import BackIcon from "../../components/BackIcon"; |
|
|
|
|
import MassageIcon from "../../components/MassageIcon"; |
|
|
|
|
import fontSize from "../../utils/fontsizeUtils"; |
|
|
|
|
import { useNavigation } from "@react-navigation/native"; |
|
|
|
|
import { useNavigation, CommonActions } from "@react-navigation/native"; |
|
|
|
|
import { NativeStackNavigationProp } from "@react-navigation/native-stack"; |
|
|
|
|
import { useRoute, RouteProp } from "@react-navigation/native"; |
|
|
|
|
import { |
|
|
|
@ -31,6 +32,7 @@ import {
|
|
|
|
|
OrderItemDetails, |
|
|
|
|
} from "../../services/api/orders"; |
|
|
|
|
import { payApi, PaymentMethod } from "../../services/api/payApi"; |
|
|
|
|
import { settingApi } from "../../services/api/setting"; |
|
|
|
|
import useUserStore from "../../store/user"; |
|
|
|
|
import OrderIcon from "../../components/OrderIcon"; |
|
|
|
|
import InfoIcon from "../../components/InfoIcon"; |
|
|
|
@ -50,6 +52,18 @@ import payMap from "../../utils/payMap";
|
|
|
|
|
import PhoneNumberInputModal from "../../screens/BalanceScreen/PhoneNumberInputModal"; |
|
|
|
|
import { cartApi } from "../../services/api/cart"; |
|
|
|
|
import IconComponent from "../../components/IconComponent"; |
|
|
|
|
import AsyncStorage from "@react-native-async-storage/async-storage"; |
|
|
|
|
import { CountryList } from "../../constants/countries"; |
|
|
|
|
|
|
|
|
|
// 定义本地存储的国家数据类型
|
|
|
|
|
interface LocalCountryData { |
|
|
|
|
code: string; |
|
|
|
|
flag: string; |
|
|
|
|
name: string; |
|
|
|
|
phoneCode: string; |
|
|
|
|
userCount: number; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 定义选项类型
|
|
|
|
|
interface PaymentOption { |
|
|
|
|
id: string; |
|
|
|
@ -244,6 +258,13 @@ export const OrderDetails = () => {
|
|
|
|
|
const [showCancelModal, setShowCancelModal] = useState(false); |
|
|
|
|
const [isCancelling, setIsCancelling] = useState(false); |
|
|
|
|
|
|
|
|
|
// 添加国家选择相关状态
|
|
|
|
|
const [countryList, setCountryList] = useState<CountryList[]>([]); |
|
|
|
|
const [selectedCountry, setSelectedCountry] = useState<CountryList | null>(null); |
|
|
|
|
const [localSelectedCountry, setLocalSelectedCountry] = useState<LocalCountryData | null>(null); |
|
|
|
|
const [showCountryModal, setShowCountryModal] = useState(false); |
|
|
|
|
const [loadingCountries, setLoadingCountries] = useState(false); |
|
|
|
|
|
|
|
|
|
const getOrderDetails = async () => { |
|
|
|
|
try { |
|
|
|
|
setIsLoading(true); |
|
|
|
@ -256,6 +277,86 @@ export const OrderDetails = () => {
|
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// 获取国家列表
|
|
|
|
|
const loadCountryList = async () => { |
|
|
|
|
setLoadingCountries(true); |
|
|
|
|
try { |
|
|
|
|
// 首先尝试读取本地存储的国家数据
|
|
|
|
|
const savedLocalCountry = await AsyncStorage.getItem("@selected_country"); |
|
|
|
|
if (savedLocalCountry) { |
|
|
|
|
try { |
|
|
|
|
const parsedLocalCountry: LocalCountryData = JSON.parse(savedLocalCountry); |
|
|
|
|
setLocalSelectedCountry(parsedLocalCountry); |
|
|
|
|
console.log('使用本地存储的国家:', parsedLocalCountry); |
|
|
|
|
} catch (e) { |
|
|
|
|
console.error("解析本地存储国家数据失败:", e); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const response = await settingApi.getSendSmsCountryList(); |
|
|
|
|
if (response && Array.isArray(response)) { |
|
|
|
|
setCountryList(response); |
|
|
|
|
|
|
|
|
|
// 如果没有本地存储的国家,则使用API返回的数据进行匹配
|
|
|
|
|
if (!savedLocalCountry) { |
|
|
|
|
// 如果用户有国家信息,自动选择对应的国家
|
|
|
|
|
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, localCountry: LocalCountryData | null, apiCountry: CountryList | null): string => { |
|
|
|
|
if (!phone) return phone; |
|
|
|
|
|
|
|
|
|
// 移除电话号码中的空格、破折号等
|
|
|
|
|
const cleanPhone = phone.replace(/[\s\-\(\)]/g, ''); |
|
|
|
|
|
|
|
|
|
// 如果已经有+号开头,直接返回
|
|
|
|
|
if (cleanPhone.startsWith('+')) { |
|
|
|
|
return cleanPhone; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 优先使用本地存储的国家数据的 phoneCode
|
|
|
|
|
let countryCode = ''; |
|
|
|
|
if (localCountry?.phoneCode) { |
|
|
|
|
countryCode = localCountry.phoneCode; |
|
|
|
|
} else if (apiCountry?.country) { |
|
|
|
|
countryCode = `+${apiCountry.country}`; |
|
|
|
|
} else { |
|
|
|
|
return phone; // 如果都没有,返回原始电话号码
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 如果电话号码以0开头,移除0
|
|
|
|
|
const phoneWithoutLeadingZero = cleanPhone.startsWith('0') ? cleanPhone.substring(1) : cleanPhone; |
|
|
|
|
|
|
|
|
|
return `${countryCode}${phoneWithoutLeadingZero}`; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// 获取显示的国家代码
|
|
|
|
|
const getDisplayCountryCode = () => { |
|
|
|
|
if (loadingCountries) return "..."; |
|
|
|
|
if (localSelectedCountry?.phoneCode) { |
|
|
|
|
return localSelectedCountry.phoneCode; |
|
|
|
|
} |
|
|
|
|
if (selectedCountry?.country) { |
|
|
|
|
return `+${selectedCountry.country}`; |
|
|
|
|
} |
|
|
|
|
return '+243'; // 默认值,刚果民主共和国
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
getOrderDetails(); |
|
|
|
|
|
|
|
|
@ -399,6 +500,9 @@ export const OrderDetails = () => {
|
|
|
|
|
|
|
|
|
|
// 如果是mobile_money支付方式,显示电话号码输入模态框
|
|
|
|
|
if (selectedPayment === "mobile_money") { |
|
|
|
|
// 先加载国家列表
|
|
|
|
|
await loadCountryList(); |
|
|
|
|
|
|
|
|
|
// 准备支付参数
|
|
|
|
|
const params = { |
|
|
|
|
originalAmount: orderDetails.total_amount, |
|
|
|
@ -514,9 +618,19 @@ export const OrderDetails = () => {
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 验证国家选择
|
|
|
|
|
if (!localSelectedCountry && !selectedCountry) { |
|
|
|
|
Alert.alert(t("error"), "请选择国家"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
setIsPaymentLoading(true); |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
// 格式化电话号码,添加国家前缀
|
|
|
|
|
const formattedPhone = formatPhoneNumber(phoneNumber, localSelectedCountry, selectedCountry); |
|
|
|
|
console.log('发送的电话号码:', formattedPhone); |
|
|
|
|
|
|
|
|
|
// 准备请求数据
|
|
|
|
|
const paymentData = { |
|
|
|
|
order_id: orderDetails?.order_id || "", |
|
|
|
@ -526,7 +640,6 @@ export const OrderDetails = () => {
|
|
|
|
|
actual_amount: paymentParams.amount, |
|
|
|
|
shipping_fee: 0, |
|
|
|
|
domestic_shipping_fee: 0, |
|
|
|
|
phone: phoneNumber, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// 更新订单支付方式
|
|
|
|
@ -538,19 +651,35 @@ export const OrderDetails = () => {
|
|
|
|
|
method: paymentParams.payment_method, |
|
|
|
|
currency: paymentParams.currency, |
|
|
|
|
amount: paymentParams.amount, |
|
|
|
|
phone: phoneNumber, |
|
|
|
|
extra: { phone_number: formattedPhone }, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const response = await payApi.getPayInfo(payData); |
|
|
|
|
if (response.success) { |
|
|
|
|
setShowPhoneModal(false); |
|
|
|
|
setShowPaymentModal(false); |
|
|
|
|
// 打开支付页面
|
|
|
|
|
navigation.navigate("Pay", { |
|
|
|
|
payUrl: response.payment_url, |
|
|
|
|
method: paymentParams.payment_method, |
|
|
|
|
order_id: orderDetails?.order_id || "", |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// 支付成功后跳转到 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 { |
|
|
|
|
Alert.alert(t("error"), t("order.error.payment_update")); |
|
|
|
|
} |
|
|
|
@ -801,7 +930,7 @@ export const OrderDetails = () => {
|
|
|
|
|
<View style={styles.recipientPhoneContainer}> |
|
|
|
|
<PhoneIcon size={16} color="#3D3D3D" /> |
|
|
|
|
<Text style={styles.recipientPhone}> |
|
|
|
|
{orderDetails.receiver_phone} |
|
|
|
|
{formatPhoneNumber(orderDetails.receiver_phone, localSelectedCountry, selectedCountry)} |
|
|
|
|
</Text> |
|
|
|
|
</View> |
|
|
|
|
</View> |
|
|
|
@ -811,7 +940,7 @@ export const OrderDetails = () => {
|
|
|
|
|
<WhatsAppIcon size={16} /> |
|
|
|
|
<Text style={styles.recipientPhone}>WhatsApp:</Text> |
|
|
|
|
<Text style={styles.recipientPhone}> |
|
|
|
|
{orderDetails.receiver_phone} |
|
|
|
|
{formatPhoneNumber(orderDetails.receiver_phone, localSelectedCountry, selectedCountry)} |
|
|
|
|
</Text> |
|
|
|
|
</View> |
|
|
|
|
</View> |
|
|
|
@ -972,7 +1101,7 @@ export const OrderDetails = () => {
|
|
|
|
|
<TouchableOpacity |
|
|
|
|
style={styles.bottomButton1} |
|
|
|
|
onPress={() => { |
|
|
|
|
callPhone(orderDetails.whatsapp_number); |
|
|
|
|
callPhone(formatPhoneNumber(orderDetails.receiver_phone, localSelectedCountry, selectedCountry)); |
|
|
|
|
}} |
|
|
|
|
> |
|
|
|
|
<Text style={styles.bottomButtonText1}> |
|
|
|
@ -1445,8 +1574,58 @@ export const OrderDetails = () => {
|
|
|
|
|
paymentParams={paymentParams} |
|
|
|
|
onSubmit={handlePhoneSubmit} |
|
|
|
|
onCloses={() => setShowPaymentModal(false)} |
|
|
|
|
displayCountryCode={getDisplayCountryCode()} |
|
|
|
|
onCountrySelect={() => setShowCountryModal(true)} |
|
|
|
|
/> |
|
|
|
|
|
|
|
|
|
{/* 国家选择模态框 */} |
|
|
|
|
<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.closeButtonContainer} |
|
|
|
|
> |
|
|
|
|
<Text style={styles.closeButtonText}>✕</Text> |
|
|
|
|
</TouchableOpacity> |
|
|
|
|
</View> |
|
|
|
|
|
|
|
|
|
<FlatList |
|
|
|
|
data={countryList} |
|
|
|
|
keyExtractor={(item) => item.country.toString()} |
|
|
|
|
renderItem={({ item }) => ( |
|
|
|
|
<TouchableOpacity |
|
|
|
|
style={[ |
|
|
|
|
styles.cardContainer, |
|
|
|
|
selectedCountry?.country === item.country && styles.currencyButtonActive |
|
|
|
|
]} |
|
|
|
|
onPress={() => { |
|
|
|
|
setSelectedCountry(item); |
|
|
|
|
setLocalSelectedCountry(null); // 清除本地存储的选择,使用API的数据
|
|
|
|
|
setShowCountryModal(false); |
|
|
|
|
}} |
|
|
|
|
> |
|
|
|
|
<Text style={[ |
|
|
|
|
styles.buttonTextDark, |
|
|
|
|
selectedCountry?.country === item.country && styles.currencyButtonTextActive |
|
|
|
|
]}> |
|
|
|
|
{item.name_en} (+{item.country}) |
|
|
|
|
</Text> |
|
|
|
|
</TouchableOpacity> |
|
|
|
|
)} |
|
|
|
|
style={styles.paymentOptions} |
|
|
|
|
/> |
|
|
|
|
</View> |
|
|
|
|
</View> |
|
|
|
|
</Modal> |
|
|
|
|
|
|
|
|
|
{/* 取消订单确认弹窗 */} |
|
|
|
|
<Modal |
|
|
|
|
visible={showCancelModal} |
|
|
|
|