|
|
@ -1,4 +1,4 @@ |
|
|
|
import React, { useEffect, useState, useCallback } from "react"; |
|
|
|
import React, { useState, useCallback } from "react"; |
|
|
|
import { |
|
|
|
import { |
|
|
|
View, |
|
|
|
View, |
|
|
|
Text, |
|
|
|
Text, |
|
|
@ -13,7 +13,6 @@ import { |
|
|
|
StatusBar, |
|
|
|
StatusBar, |
|
|
|
SafeAreaView, |
|
|
|
SafeAreaView, |
|
|
|
} from "react-native"; |
|
|
|
} from "react-native"; |
|
|
|
import BackIcon from "../components/BackIcon"; |
|
|
|
|
|
|
|
import fontSize from "../utils/fontsizeUtils"; |
|
|
|
import fontSize from "../utils/fontsizeUtils"; |
|
|
|
import CircleOutlineIcon from "../components/CircleOutlineIcon"; |
|
|
|
import CircleOutlineIcon from "../components/CircleOutlineIcon"; |
|
|
|
import { |
|
|
|
import { |
|
|
@ -32,17 +31,19 @@ import { useFocusEffect } from "@react-navigation/native"; |
|
|
|
import useCreateOrderStore from "../store/createOrder"; |
|
|
|
import useCreateOrderStore from "../store/createOrder"; |
|
|
|
import useUserStore from "../store/user"; |
|
|
|
import useUserStore from "../store/user"; |
|
|
|
import { t } from "../i18n"; |
|
|
|
import { t } from "../i18n"; |
|
|
|
|
|
|
|
import { payApi } from "../services/api/payApi"; |
|
|
|
|
|
|
|
|
|
|
|
export const CartScreen = () => { |
|
|
|
export const CartScreen = () => { |
|
|
|
const [cartList, setCartList] = useState<GetCartList[]>([]); |
|
|
|
const [cartList, setCartList] = useState<GetCartList[]>([]); |
|
|
|
const { |
|
|
|
const { |
|
|
|
user: { user_id, currency, vip_discount }, |
|
|
|
user: { user_id, currency, vip_discount, country_code }, |
|
|
|
} = useUserStore(); |
|
|
|
} = useUserStore(); |
|
|
|
const [selectedItems, setSelectedItems] = useState<{ |
|
|
|
const [selectedItems, setSelectedItems] = useState<{ |
|
|
|
[key: string]: boolean; |
|
|
|
[key: string]: boolean; |
|
|
|
}>({}); |
|
|
|
}>({}); |
|
|
|
const [allSelected, setAllSelected] = useState(false); |
|
|
|
const [allSelected, setAllSelected] = useState(false); |
|
|
|
const [totalAmount, setTotalAmount] = useState(0); |
|
|
|
const [totalAmount, setTotalAmount] = useState(0); |
|
|
|
|
|
|
|
const [convertedMinAmount, setConvertedMinAmount] = useState<number | null>(null); |
|
|
|
const [deleteModalVisible, setDeleteModalVisible] = useState(false); |
|
|
|
const [deleteModalVisible, setDeleteModalVisible] = useState(false); |
|
|
|
const [itemToDelete, setItemToDelete] = useState<{ |
|
|
|
const [itemToDelete, setItemToDelete] = useState<{ |
|
|
|
cartId: number; |
|
|
|
cartId: number; |
|
|
@ -58,6 +59,50 @@ export const CartScreen = () => { |
|
|
|
const [quantityInput, setQuantityInput] = useState(""); |
|
|
|
const [quantityInput, setQuantityInput] = useState(""); |
|
|
|
const navigation = useNavigation<NativeStackNavigationProp<any>>(); |
|
|
|
const navigation = useNavigation<NativeStackNavigationProp<any>>(); |
|
|
|
const { setItems } = useCreateOrderStore(); |
|
|
|
const { setItems } = useCreateOrderStore(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 货币转换函数
|
|
|
|
|
|
|
|
const convertCurrency = async () => { |
|
|
|
|
|
|
|
console.log(country_code); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果 country_code 是 255,不需要转换
|
|
|
|
|
|
|
|
if (country_code === 225) { |
|
|
|
|
|
|
|
setConvertedMinAmount(null); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
console.log(`Converting currency for country_code: ${country_code}, from FCFA to ${currency}`); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const data = { |
|
|
|
|
|
|
|
from_currency: "FCFA", // 固定使用 FCFA
|
|
|
|
|
|
|
|
to_currency: currency, // 使用用户的货币
|
|
|
|
|
|
|
|
amounts: { |
|
|
|
|
|
|
|
total_amount: 50000, // 固定的最低订单金额 50,000 FCFA
|
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const response = await payApi.convertCurrency(data); |
|
|
|
|
|
|
|
console.log("Currency conversion response:", response); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (response && response.converted_amounts_list && response.converted_amounts_list.length > 0) { |
|
|
|
|
|
|
|
const convertedTotal = response.converted_amounts_list.find( |
|
|
|
|
|
|
|
(item: any) => item.item_key === "total_amount" |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
if (convertedTotal) { |
|
|
|
|
|
|
|
console.log(`Converted minimum amount: ${convertedTotal.converted_amount} ${currency}`); |
|
|
|
|
|
|
|
setConvertedMinAmount(convertedTotal.converted_amount); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
console.warn("No converted amounts found in response"); |
|
|
|
|
|
|
|
setConvertedMinAmount(null); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
|
|
console.error("货币转换失败:", error); |
|
|
|
|
|
|
|
// 转换失败时不设置转换金额,使用原始逻辑
|
|
|
|
|
|
|
|
setConvertedMinAmount(null); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 计算选中商品的总金额
|
|
|
|
// 计算选中商品的总金额
|
|
|
|
const calculateTotalAmount = (list: GetCartList[]) => { |
|
|
|
const calculateTotalAmount = (list: GetCartList[]) => { |
|
|
|
let total = 0; |
|
|
|
let total = 0; |
|
|
@ -83,12 +128,13 @@ export const CartScreen = () => { |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const changeAllSelected = () => { |
|
|
|
const changeAllSelected = (newList: GetCartList[]) => { |
|
|
|
const allSkusSelected = cartList.every((item) => |
|
|
|
const allSkusSelected = newList.every((item) => |
|
|
|
item.skus.every((sku) => sku.selected === 1) |
|
|
|
item.skus.every((sku) => sku.selected === 1) |
|
|
|
); |
|
|
|
); |
|
|
|
setAllSelected(!allSkusSelected); |
|
|
|
setAllSelected(allSkusSelected); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const toggleSelection = async ( |
|
|
|
const toggleSelection = async ( |
|
|
|
cartItemId: string, |
|
|
|
cartItemId: string, |
|
|
|
index1: number, |
|
|
|
index1: number, |
|
|
@ -123,6 +169,8 @@ export const CartScreen = () => { |
|
|
|
return item; |
|
|
|
return item; |
|
|
|
}); |
|
|
|
}); |
|
|
|
calculateTotalAmount(newList); |
|
|
|
calculateTotalAmount(newList); |
|
|
|
|
|
|
|
// 在状态更新后检查全选状态
|
|
|
|
|
|
|
|
changeAllSelected(newList); |
|
|
|
return newList; |
|
|
|
return newList; |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
@ -157,6 +205,7 @@ export const CartScreen = () => { |
|
|
|
return item; |
|
|
|
return item; |
|
|
|
}); |
|
|
|
}); |
|
|
|
calculateTotalAmount(newList); |
|
|
|
calculateTotalAmount(newList); |
|
|
|
|
|
|
|
changeAllSelected(newList); |
|
|
|
return newList; |
|
|
|
return newList; |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
@ -180,6 +229,8 @@ export const CartScreen = () => { |
|
|
|
return item; |
|
|
|
return item; |
|
|
|
}); |
|
|
|
}); |
|
|
|
calculateTotalAmount(newList); |
|
|
|
calculateTotalAmount(newList); |
|
|
|
|
|
|
|
// 在状态更新后检查全选状态
|
|
|
|
|
|
|
|
changeAllSelected(newList); |
|
|
|
return newList; |
|
|
|
return newList; |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
@ -209,28 +260,35 @@ export const CartScreen = () => { |
|
|
|
return item; |
|
|
|
return item; |
|
|
|
}); |
|
|
|
}); |
|
|
|
calculateTotalAmount(newList); |
|
|
|
calculateTotalAmount(newList); |
|
|
|
|
|
|
|
changeAllSelected(newList); |
|
|
|
return newList; |
|
|
|
return newList; |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
changeAllSelected(); |
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const getCart = async () => { |
|
|
|
const getCart = async () => { |
|
|
|
const res = await getCartList(); |
|
|
|
const res = await getCartList(); |
|
|
|
setCartList(res.items); |
|
|
|
|
|
|
|
calculateTotalAmount(res.items); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (res.items.length === 0) { |
|
|
|
// 修正父商品的选择状态,确保与子商品状态一致
|
|
|
|
|
|
|
|
const correctedItems = res.items.map((item) => { |
|
|
|
|
|
|
|
// 检查该商品下所有子商品是否都被选中
|
|
|
|
|
|
|
|
const allSkusSelected = item.skus.every((sku) => sku.selected === 1); |
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
...item, |
|
|
|
|
|
|
|
selected: allSkusSelected ? 1 : 0, // 根据子商品状态设置父商品状态
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setCartList(correctedItems); |
|
|
|
|
|
|
|
calculateTotalAmount(correctedItems); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (correctedItems.length === 0) { |
|
|
|
// 如果购物车为空,直接设置全选为false
|
|
|
|
// 如果购物车为空,直接设置全选为false
|
|
|
|
setAllSelected(false); |
|
|
|
setAllSelected(false); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
// 检查所有商品的 skus 数组中的 selected 属性是否都为 1
|
|
|
|
// 检查所有商品的 skus 数组中的 selected 属性是否都为 1
|
|
|
|
const allSkusSelected = res.items.every((item) => |
|
|
|
changeAllSelected(correctedItems); |
|
|
|
item.skus.every((sku) => sku.selected === 1) |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
setAllSelected(allSkusSelected); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -264,9 +322,9 @@ export const CartScreen = () => { |
|
|
|
}; |
|
|
|
}; |
|
|
|
}); |
|
|
|
}); |
|
|
|
calculateTotalAmount(newList); |
|
|
|
calculateTotalAmount(newList); |
|
|
|
|
|
|
|
setAllSelected(!newAllSelected); |
|
|
|
return newList; |
|
|
|
return newList; |
|
|
|
}); |
|
|
|
}); |
|
|
|
setAllSelected(!newAllSelected); |
|
|
|
|
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
|
return { |
|
|
@ -369,6 +427,7 @@ export const CartScreen = () => { |
|
|
|
useFocusEffect( |
|
|
|
useFocusEffect( |
|
|
|
useCallback(() => { |
|
|
|
useCallback(() => { |
|
|
|
getCart(); |
|
|
|
getCart(); |
|
|
|
|
|
|
|
convertCurrency(); // 添加货币转换调用
|
|
|
|
}, []) |
|
|
|
}, []) |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
@ -377,6 +436,8 @@ export const CartScreen = () => { |
|
|
|
Alert.alert(t("cart.add_failed"), t("cart.login_required")); |
|
|
|
Alert.alert(t("cart.add_failed"), t("cart.login_required")); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否有选中的商品
|
|
|
|
const items: { cart_item_id: number }[] = []; |
|
|
|
const items: { cart_item_id: number }[] = []; |
|
|
|
cartList.forEach((item) => { |
|
|
|
cartList.forEach((item) => { |
|
|
|
item.skus.forEach((sku) => { |
|
|
|
item.skus.forEach((sku) => { |
|
|
@ -393,6 +454,40 @@ export const CartScreen = () => { |
|
|
|
Alert.alert(t("cart.add_failed"), t("cart.select_products")); |
|
|
|
Alert.alert(t("cart.add_failed"), t("cart.select_products")); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查最低订单金额
|
|
|
|
|
|
|
|
if (country_code !== 225) { |
|
|
|
|
|
|
|
// 只有当 country_code 不是 255 时才进行最低订单金额检查
|
|
|
|
|
|
|
|
if (convertedMinAmount !== null) { |
|
|
|
|
|
|
|
// 如果有转换后的最低金额,检查当前总价是否满足要求
|
|
|
|
|
|
|
|
console.log(`Checking converted minimum amount: ${convertedMinAmount} ${currency} vs current total: ${totalAmount}`); |
|
|
|
|
|
|
|
if (totalAmount < convertedMinAmount) { |
|
|
|
|
|
|
|
Alert.alert( |
|
|
|
|
|
|
|
t("cart.notice"),
|
|
|
|
|
|
|
|
t("cart.minimum_order_required", { |
|
|
|
|
|
|
|
amount: convertedMinAmount.toFixed(2), |
|
|
|
|
|
|
|
currency: currency |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// 如果转换失败,使用原始的 50,000 FCFA 检查
|
|
|
|
|
|
|
|
console.log(`Checking original minimum amount: 50000 FCFA vs current total: ${totalAmount}`); |
|
|
|
|
|
|
|
if (totalAmount < 50000) { |
|
|
|
|
|
|
|
Alert.alert( |
|
|
|
|
|
|
|
t("cart.notice"),
|
|
|
|
|
|
|
|
t("cart.minimum_order_required", { |
|
|
|
|
|
|
|
amount: "50,000", |
|
|
|
|
|
|
|
currency: "FCFA" |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// 如果 country_code === 255,则不进行任何最低订单金额检查
|
|
|
|
|
|
|
|
|
|
|
|
setItems(items); |
|
|
|
setItems(items); |
|
|
|
navigation.navigate("PreviewAddress"); |
|
|
|
navigation.navigate("PreviewAddress"); |
|
|
|
}; |
|
|
|
}; |
|
|
@ -735,6 +830,7 @@ export const CartScreen = () => { |
|
|
|
{/* Fixed Bottom Section */} |
|
|
|
{/* Fixed Bottom Section */} |
|
|
|
<View style={styles.fixedBottomContainer}> |
|
|
|
<View style={styles.fixedBottomContainer}> |
|
|
|
{/* Order Summary */} |
|
|
|
{/* Order Summary */} |
|
|
|
|
|
|
|
{country_code !== 225 && ( |
|
|
|
<View style={styles.orderSummaryHeader}> |
|
|
|
<View style={styles.orderSummaryHeader}> |
|
|
|
<View style={styles.svgContainer6}> |
|
|
|
<View style={styles.svgContainer6}> |
|
|
|
<Image |
|
|
|
<Image |
|
|
@ -745,9 +841,15 @@ export const CartScreen = () => { |
|
|
|
|
|
|
|
|
|
|
|
<Text style={styles.orderQuantityInfo}> |
|
|
|
<Text style={styles.orderQuantityInfo}> |
|
|
|
<Text>{t("cart.min_order_quantity")} </Text> |
|
|
|
<Text>{t("cart.min_order_quantity")} </Text> |
|
|
|
<Text style={styles.tiltWarpText}>50,000FCFA</Text> |
|
|
|
<Text style={styles.tiltWarpText}> |
|
|
|
|
|
|
|
{convertedMinAmount !== null |
|
|
|
|
|
|
|
? `${convertedMinAmount.toFixed(2)} ${currency}` |
|
|
|
|
|
|
|
: "50,000FCFA" |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
</Text> |
|
|
|
</Text> |
|
|
|
</Text> |
|
|
|
</View> |
|
|
|
</View> |
|
|
|
|
|
|
|
)} |
|
|
|
|
|
|
|
|
|
|
|
<View style={styles.flexboxContainerWithButton}> |
|
|
|
<View style={styles.flexboxContainerWithButton}> |
|
|
|
<View style={styles.productInfoContainer}> |
|
|
|
<View style={styles.productInfoContainer}> |
|
|
|