From 7493657e8168d37c6ffb9cd7b04b1709c17dc0d4 Mon Sep 17 00:00:00 2001 From: Mac Date: Wed, 28 May 2025 11:27:03 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=90=E8=B4=B9=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/locales/en/translation.json | 4 +- app/locales/fr/translation.json | 4 +- app/screens/CartScreen.tsx | 493 ++++++++++++-------- app/screens/previewOrder/PaymentMethod.tsx | 189 ++++---- app/screens/previewOrder/PreviewAddress.tsx | 8 +- app/screens/previewOrder/ShippingFee.tsx | 138 ++++-- 6 files changed, 509 insertions(+), 327 deletions(-) diff --git a/app/locales/en/translation.json b/app/locales/en/translation.json index f9c084d..3b73ff1 100644 --- a/app/locales/en/translation.json +++ b/app/locales/en/translation.json @@ -252,7 +252,7 @@ "order.shipping.estimated_time": "Estimated arrival time", "order.shipping.sea_time": "45 days", "order.shipping.air_time": "20 days", - "order.shipping.domestic_fee": "Domestic shipping fee", + "order.shipping.domestic_fee": "Freight charges in China", "order.shipping.international_fee": "International shipping fee", "order.shipping.submit": "Submit", "order.shipping.calculating": "Calculating shipping fee...", @@ -452,6 +452,7 @@ }, "cart": { "cart":"Cart", + "minimum":"The minimum purchase quantity is", "add_failed": "Add Failed", "login_required": "Please login first", "select_products": "Please select products", @@ -543,6 +544,7 @@ "yes": "Yes", "no": "No", "preview": { + "Cash_on_delivery":"International cash on delivery", "login_required": "Please login first", "payment_failed": "Payment failed, please try again", "Insufficient_balance": "Insufficient balance", diff --git a/app/locales/fr/translation.json b/app/locales/fr/translation.json index 2cfcc35..f4223bd 100644 --- a/app/locales/fr/translation.json +++ b/app/locales/fr/translation.json @@ -180,7 +180,7 @@ "order.shipping.estimated_time": "Temps d'arrivée estimé", "order.shipping.sea_time": "45 jours", "order.shipping.air_time": "20 jours", - "order.shipping.domestic_fee": "Frais de livraison nationale", + "order.shipping.domestic_fee": "Fret en Chine", "order.shipping.international_fee": "Frais de livraison internationale", "order.shipping.submit": "Soumettre", "order.shipping.calculating": "Calcul des frais de livraison...", @@ -463,6 +463,7 @@ }, "cart": { "cart":"Panier", + "minimum":"La quantité minimum de commande est", "add_failed": "Ajout échoué", "login_required": "Veuillez vous connecter d'abord", "select_products": "Veuillez sélectionner des produits", @@ -622,6 +623,7 @@ "yes": "Oui", "no": "Non", "preview": { + "Cash_on_delivery":"Paiement international à l’arrivée", "login_required": "Veuillez vous connecter d'abord", "payment_failed": "Le paiement a échoué", "Insufficient_balance": "Solde insuffisant", diff --git a/app/screens/CartScreen.tsx b/app/screens/CartScreen.tsx index 5023809..e550481 100644 --- a/app/screens/CartScreen.tsx +++ b/app/screens/CartScreen.tsx @@ -12,6 +12,7 @@ import { Platform, StatusBar, SafeAreaView, + ActivityIndicator, } from "react-native"; import fontSize from "../utils/fontsizeUtils"; import CircleOutlineIcon from "../components/CircleOutlineIcon"; @@ -33,7 +34,11 @@ import useUserStore from "../store/user"; import { t } from "../i18n"; import { payApi } from "../services/api/payApi"; import IconComponent from "../components/IconComponent"; -import {getSubjectTransLanguage,getAttributeTransLanguage} from "../utils/languageUtils"; +import { + getSubjectTransLanguage, + getAttributeTransLanguage, +} from "../utils/languageUtils"; +import Toast from "react-native-toast-message"; export const CartScreen = () => { const [cartList, setCartList] = useState([]); @@ -45,7 +50,9 @@ export const CartScreen = () => { }>({}); const [allSelected, setAllSelected] = useState(false); const [totalAmount, setTotalAmount] = useState(0); - const [convertedMinAmount, setConvertedMinAmount] = useState(null); + const [convertedMinAmount, setConvertedMinAmount] = useState( + null + ); const [deleteModalVisible, setDeleteModalVisible] = useState(false); const [itemToDelete, setItemToDelete] = useState<{ cartId: number; @@ -63,6 +70,7 @@ export const CartScreen = () => { const { setItems } = useCreateOrderStore(); const [minQuantityModalVisible, setMinQuantityModalVisible] = useState(false); const [minQuantityMessage, setMinQuantityMessage] = useState(""); + const [loading, setLoading] = useState(false); // 货币转换函数 const convertCurrency = async () => { @@ -70,18 +78,9 @@ export const CartScreen = () => { if (!user_id) { return; } - - console.log(country_code); - - // 如果 country_code 是 255,不需要转换 - if (country_code === 225) { - setConvertedMinAmount(null); - return; - } + console.log(country_code); try { - console.log(`Converting currency for country_code: ${country_code}, from FCFA to ${currency}`); - const data = { from_currency: "FCFA", // 固定使用 FCFA to_currency: currency, // 使用用户的货币 @@ -92,23 +91,29 @@ export const CartScreen = () => { const response = await payApi.convertCurrency(data); console.log("Currency conversion response:", response); - - if (response && response.converted_amounts_list && response.converted_amounts_list.length > 0) { + + 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); + console.log( + `Converted minimum amount: ${convertedTotal.converted_amount} ${currency}` + ); + return convertedTotal.converted_amount; } } else { console.warn("No converted amounts found in response"); - setConvertedMinAmount(null); + return null; } } catch (error) { console.error("货币转换失败:", error); // 转换失败时不设置转换金额,使用原始逻辑 - setConvertedMinAmount(null); + return null; } }; @@ -153,7 +158,7 @@ export const CartScreen = () => { if (!user_id) { return; } - + if (index != null) { // 处理子类 SKU 的选择 const data = { @@ -286,9 +291,9 @@ export const CartScreen = () => { if (!user_id) { return; } - + const res = await getCartList(); - + // 修正父商品的选择状态,确保与子商品状态一致 const correctedItems = res.items.map((item) => { // 检查该商品下所有子商品是否都被选中 @@ -298,7 +303,7 @@ export const CartScreen = () => { selected: allSkusSelected ? 1 : 0, // 根据子商品状态设置父商品状态 }; }); - + setCartList(correctedItems); calculateTotalAmount(correctedItems); @@ -316,7 +321,7 @@ export const CartScreen = () => { if (!user_id) { return; } - + const newAllSelected = !allSelected; setAllSelected(newAllSelected); @@ -373,7 +378,7 @@ export const CartScreen = () => { if (!user_id) { return; } - + // 设置要删除的商品信息并显示确认对话框 setItemToDelete({ cartId, cartItemId, cartId1 }); setDeleteModalVisible(true); @@ -384,7 +389,7 @@ export const CartScreen = () => { if (!user_id || !itemToDelete) { return; } - + const { cartId, cartItemId, cartId1 } = itemToDelete; console.log(itemToDelete); @@ -461,86 +466,127 @@ export const CartScreen = () => { // 只有在用户已登录时才执行API调用 if (user_id) { getCart(); - convertCurrency(); // 添加货币转换调用 } }, [user_id]) ); - const gotoOrder = () => { + const gotoOrder = async () => { if (!user_id) { Alert.alert(t("cart.add_failed"), t("cart.login_required")); return; } - - // 检查是否有选中的商品 - const items: { cart_item_id: number }[] = []; - cartList.forEach((item) => { - item.skus.forEach((sku) => { - if (sku.selected === 1) { - if (sku.cart_item_id) { - items.push({ - cart_item_id: sku.cart_item_id, - }); + + // 立即设置loading状态 + setLoading(true); + + try { + // 检查是否有选中的商品 + const items: { cart_item_id: number }[] = []; + cartList.forEach((item) => { + item.skus.forEach((sku) => { + if (sku.selected === 1) { + if (sku.cart_item_id) { + items.push({ + cart_item_id: sku.cart_item_id, + }); + } } - } + }); }); - }); - if (items.length === 0) { - Alert.alert(t("cart.add_failed"), t("cart.select_products")); - return; - } + if (items.length === 0) { + Alert.alert(t("cart.add_failed"), t("cart.select_products")); + return; + } - // 检查每个商品组的最小起订量 - for (const item of cartList) { - // 检查该商品组是否有选中的SKU - const hasSelectedSku = item.skus.some(sku => sku.selected === 1); - if (hasSelectedSku) { - const currentGroupTotal = calculateProductGroupTotalQuantity(item.cart_id); - if (currentGroupTotal < item.min_order_quantity) { - Alert.alert( - t("cart.notice"), - `${getSubjectTransLanguage(item)} ${t("cart.min_order")}${item.min_order_quantity}${t("cart.pieces")},${t("cart.current_quantity", "当前数量")}${currentGroupTotal}${t("cart.pieces")}` + // 检查每个商品组的最小起订量 + for (const item of cartList) { + // 检查该商品组是否有选中的SKU + const hasSelectedSku = item.skus.some((sku) => sku.selected === 1); + if (hasSelectedSku) { + const currentGroupTotal = calculateProductGroupTotalQuantity( + item.cart_id ); - return; + if (currentGroupTotal < item.min_order_quantity) { + Toast.show({ + text1: `${getSubjectTransLanguage(item)} ${t("cart.min_order")}${ + item.min_order_quantity + }${t("cart.pieces")},${t( + "cart.current_quantity", + "当前数量" + )}${currentGroupTotal}${t("cart.pieces")}`, + }); + + return; + } } } - } + console.log(totalAmount); - // 检查最低订单金额 - 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 - }) - ); + console.log(country_code); + + const conver = await convertCurrency(); + console.log(conver); + + let isFei = true + if (country_code !== 225) { + if (totalAmount < conver) { + Toast.show({ + text1: `${t('cart.minimum')}${conver}${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; + }else{ + if (totalAmount < conver) { + isFei = false + }else{ + isFei = true } } - } - // 如果 country_code === 255,则不进行任何最低订单金额检查 - setItems(items); - navigation.navigate("PreviewAddress"); + // 检查最低订单金额 + // 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); + navigation.navigate("PreviewAddress",{isFei:isFei}); + } catch (error) { + console.error("提交订单失败:", error); + Toast.show({ + text1: t("cart.submit_failed", "提交失败,请重试"), + }); + } finally { + // 确保在所有情况下都重置loading状态 + setLoading(false); + } }; // 添加更新商品数量的方法 @@ -553,7 +599,7 @@ export const CartScreen = () => { if (!user_id) { return; } - + try { // 更新本地状态 setCartList((prev) => { @@ -596,9 +642,9 @@ export const CartScreen = () => { // 计算同一商品组的总数量 const calculateProductGroupTotalQuantity = (cartId: number) => { - const product = cartList.find(item => item.cart_id === cartId); + const product = cartList.find((item) => item.cart_id === cartId); if (!product) return 0; - + return product.skus.reduce((total, sku) => total + sku.quantity, 0); }; @@ -613,15 +659,19 @@ export const CartScreen = () => { if (!user_id) { return; } - + // 计算减少1个数量后,该商品组的总数量 const currentGroupTotal = calculateProductGroupTotalQuantity(cartId); const newGroupTotal = currentGroupTotal - 1; - + if (newGroupTotal >= minOrderQuantity) { updateQuantity(cartId, cartItemId, currentQuantity - 1); } else { - showMinQuantityModal(`${t("cart.notice")}:${t("cart.min_order")}${minOrderQuantity}${t("cart.pieces")}`); + showMinQuantityModal( + `${t("cart.notice")}:${t("cart.min_order")}${minOrderQuantity}${t( + "cart.pieces" + )}` + ); } }; @@ -635,7 +685,7 @@ export const CartScreen = () => { if (!user_id) { return; } - + updateQuantity(cartId, cartItemId, currentQuantity + 1); }; @@ -645,7 +695,7 @@ export const CartScreen = () => { if (!user_id || !editingItem) { return; } - + const newQuantity = parseInt(quantityInput); if (isNaN(newQuantity) || newQuantity < 1) { showMinQuantityModal(t("cart.enter_valid_quantity")); @@ -653,17 +703,23 @@ export const CartScreen = () => { } const { cartId, cartItemId } = editingItem; - const product = cartList.find(item => item.cart_id === cartId); + const product = cartList.find((item) => item.cart_id === cartId); const minOrderQuantity = product?.min_order_quantity || 1; // 计算修改数量后,该商品组的总数量 const currentGroupTotal = calculateProductGroupTotalQuantity(cartId); - const currentSkuQuantity = product?.skus.find(sku => sku.cart_item_id === cartItemId)?.quantity || 0; + const currentSkuQuantity = + product?.skus.find((sku) => sku.cart_item_id === cartItemId)?.quantity || + 0; const quantityDifference = newQuantity - currentSkuQuantity; const newGroupTotal = currentGroupTotal + quantityDifference; if (newGroupTotal < minOrderQuantity) { - showMinQuantityModal(`${t("cart.notice")}:${t("cart.min_order")}${minOrderQuantity}${t("cart.pieces")}`); + showMinQuantityModal( + `${t("cart.notice")}:${t("cart.min_order")}${minOrderQuantity}${t( + "cart.pieces" + )}` + ); } else { updateQuantity(cartId, cartItemId, newQuantity); setQuantityInputVisible(false); @@ -682,7 +738,7 @@ export const CartScreen = () => { if (!user_id) { return; } - + setEditingItem({ cartId, cartItemId, currentQuantity }); setQuantityInput(currentQuantity.toString()); setQuantityInputVisible(true); @@ -742,7 +798,7 @@ export const CartScreen = () => { style={styles.imageThumbnail} /> - { {getSubjectTransLanguage(item) || item.subject} - {t("cart.min_order")}: {calculateProductGroupTotalQuantity(item.cart_id)}/{item.min_order_quantity} + {t("cart.min_order")}:{" "} + {calculateProductGroupTotalQuantity(item.cart_id)}/ + {item.min_order_quantity} {t("cart.pieces")} @@ -768,11 +826,13 @@ export const CartScreen = () => { alignItems: "center", width: 80, }} - onPress={() => handleDeleteSku( - item.cart_id, - sku.cart_item_id, - item.cart_id - )} + onPress={() => + handleDeleteSku( + item.cart_id, + sku.cart_item_id, + item.cart_id + ) + } disabled={!user_id} > { price: sku.price, }); } - } } + }} style={[ styles.productCardContainer5, styles.productCardContainer4, @@ -800,11 +860,14 @@ export const CartScreen = () => { > user_id && toggleSelection( - String(sku.cart_item_id), - index1, - index - )} + onPress={() => + user_id && + toggleSelection( + String(sku.cart_item_id), + index1, + index + ) + } disabled={!user_id} > @@ -823,7 +886,8 @@ export const CartScreen = () => { ? sku.attributes[0]?.sku_image_url : item.product_image, }} - style={styles.productImageDisplayStyle} /> + style={styles.productImageDisplayStyle} + /> {/* 1. SKU attributes at the top */} {sku.attributes[0]?.value && ( @@ -833,9 +897,17 @@ export const CartScreen = () => { numberOfLines={2} ellipsizeMode="tail" > - {getAttributeTransLanguage(sku.attributes[0]) || sku.attributes[0].attribute_name_trans}{" "} + {getAttributeTransLanguage( + sku.attributes[0] + ) || + sku.attributes[0].attribute_name_trans}{" "} {sku.attributes[1] ? "/" : ""}{" "} - {sku.attributes[1] ? getAttributeTransLanguage(sku.attributes[1]) || sku.attributes[1].attribute_name_trans : ""} + {sku.attributes[1] + ? getAttributeTransLanguage( + sku.attributes[1] + ) || + sku.attributes[1].attribute_name_trans + : ""} )} @@ -853,8 +925,11 @@ export const CartScreen = () => { - + style={styles.VipImg} + /> + -{((1 - vip_discount) * 100).toFixed(0)}% @@ -878,12 +953,15 @@ export const CartScreen = () => { styles.svgContainer4, { borderRightWidth: 0 }, ]} - onPress={() => user_id && handleDecreaseQuantity( - item.cart_id, - sku.cart_item_id, - sku.quantity, - item.min_order_quantity - )} + onPress={() => + user_id && + handleDecreaseQuantity( + item.cart_id, + sku.cart_item_id, + sku.quantity, + item.min_order_quantity + ) + } disabled={!user_id} > { user_id && handleQuantityPress( - item.cart_id, - sku.cart_item_id, - sku.quantity - )} + onPress={() => + user_id && + handleQuantityPress( + item.cart_id, + sku.cart_item_id, + sku.quantity + ) + } disabled={!user_id} > @@ -914,11 +995,14 @@ export const CartScreen = () => { styles.svgContainer4, { borderLeftWidth: 0, marginLeft: 0 }, ]} - onPress={() => user_id && handleIncreaseQuantity( - item.cart_id, - sku.cart_item_id, - sku.quantity - )} + onPress={() => + user_id && + handleIncreaseQuantity( + item.cart_id, + sku.cart_item_id, + sku.quantity + ) + } disabled={!user_id} > { {/* Fixed Bottom Section */} {/* Order Summary */} - {country_code !== 225 && ( + {/* {country_code !== 225 && ( { - )} + )} */} - + {allSelected ? ( @@ -994,19 +1081,27 @@ export const CartScreen = () => { {currency} - - {t("cart.submit")} - + {loading ? ( + + ) : ( + + {t("cart.submit")} + + )} @@ -1024,7 +1119,10 @@ export const CartScreen = () => { {t("cart.login_required_title", "请先登录")} - {t("cart.login_required_subtitle", "登录后即可使用购物车功能")} + {t( + "cart.login_required_subtitle", + "登录后即可使用购物车功能" + )} { - {minQuantityMessage} + + {minQuantityMessage} + setMinQuantityModalVisible(false)} > - {t("cart.confirm")} + + {t("cart.confirm")} + @@ -1317,12 +1419,12 @@ const styles = StyleSheet.create({ fontFamily: "PingFang SC", fontWeight: "600", color: "#9a9a9a", - textDecorationLine: 'line-through', + textDecorationLine: "line-through", }, vipContainer: { - position: 'relative', - justifyContent: 'center', - alignItems: 'center', + position: "relative", + justifyContent: "center", + alignItems: "center", marginLeft: 10, }, VipImg: { @@ -1330,13 +1432,13 @@ const styles = StyleSheet.create({ height: widthUtils(28, 28).height, }, discountPercentageTextStyle: { - position: 'absolute', + position: "absolute", fontSize: fontSize(12), fontFamily: "Segoe UI", fontWeight: "900", fontStyle: "italic", color: "#4e2000", - textAlign: 'center', + textAlign: "center", }, borderBoxDivider: { width: "100%", @@ -1819,30 +1921,31 @@ const styles = StyleSheet.create({ opacity: 0.6, }, loginOverlay: { - position: 'absolute', + position: "absolute", top: 0, left: 0, right: 0, bottom: 0, - backgroundColor: 'rgba(255, 255, 255, 0.9)', - backdropFilter: 'blur(10px)', // iOS 毛玻璃效果 - justifyContent: 'center', - alignItems: 'center', + backgroundColor: "rgba(255, 255, 255, 0.9)", + backdropFilter: "blur(10px)", // iOS 毛玻璃效果 + justifyContent: "center", + alignItems: "center", zIndex: 1000, }, blurContainer: { - width: '100%', - height: '100%', - justifyContent: 'center', - alignItems: 'center', - backgroundColor: Platform.OS === 'android' ? 'rgba(255, 255, 255, 0.95)' : 'transparent', + width: "100%", + height: "100%", + justifyContent: "center", + alignItems: "center", + backgroundColor: + Platform.OS === "android" ? "rgba(255, 255, 255, 0.95)" : "transparent", }, loginPromptContainer: { - backgroundColor: 'white', + backgroundColor: "white", borderRadius: 20, padding: 40, - alignItems: 'center', - shadowColor: '#000', + alignItems: "center", + shadowColor: "#000", shadowOffset: { width: 0, height: 2, @@ -1850,90 +1953,90 @@ const styles = StyleSheet.create({ shadowOpacity: 0.25, shadowRadius: 3.84, elevation: 5, - maxWidth: '80%', + maxWidth: "80%", }, loginIcon: { width: 80, height: 80, marginBottom: 20, - justifyContent: 'center', - alignItems: 'center', - backgroundColor: 'rgba(255, 81, 0, 0.1)', + justifyContent: "center", + alignItems: "center", + backgroundColor: "rgba(255, 81, 0, 0.1)", borderRadius: 40, }, loginIconText: { fontSize: 40, - fontWeight: 'bold', - color: '#FF5100', + fontWeight: "bold", + color: "#FF5100", }, loginPromptTitle: { fontSize: fontSize(24), - fontWeight: '700', - color: '#333', + fontWeight: "700", + color: "#333", marginBottom: 10, - textAlign: 'center', + textAlign: "center", }, loginPromptSubtitle: { fontSize: fontSize(16), - color: '#666', + color: "#666", marginBottom: 30, - textAlign: 'center', + textAlign: "center", lineHeight: fontSize(22), }, loginButton: { - backgroundColor: '#FF5100', + backgroundColor: "#FF5100", paddingHorizontal: 40, paddingVertical: 15, borderRadius: 25, minWidth: 160, }, loginButtonText: { - color: 'white', + color: "white", fontSize: fontSize(18), - fontWeight: '700', - textAlign: 'center', + fontWeight: "700", + textAlign: "center", }, warningIconContainer: { backgroundColor: "#FFF2E9", borderRadius: 20, padding: 12, marginBottom: 16, - alignSelf: 'center', + alignSelf: "center", width: 52, height: 52, - justifyContent: 'center', - alignItems: 'center', + justifyContent: "center", + alignItems: "center", }, warningIcon: { width: 32, height: 32, }, minQuantityPopup: { - width: '80%', + width: "80%", padding: 24, }, minQuantityText: { fontSize: fontSize(16), - color: '#333', + color: "#333", marginVertical: 16, - textAlign: 'center', + textAlign: "center", lineHeight: fontSize(22), - fontWeight: '500', + fontWeight: "500", }, minQuantityButton: { - width: '100%', + width: "100%", height: 44, borderRadius: 22, - backgroundColor: '#FF5100', + backgroundColor: "#FF5100", marginTop: 16, }, minQuantityButtonText: { fontSize: fontSize(16), - fontWeight: '600', + fontWeight: "600", }, productGroupDivider: { height: 5, - backgroundColor: '#f0f0f0', - width: '100%', + backgroundColor: "#f0f0f0", + width: "100%", }, }); diff --git a/app/screens/previewOrder/PaymentMethod.tsx b/app/screens/previewOrder/PaymentMethod.tsx index b18a725..c9915d8 100644 --- a/app/screens/previewOrder/PaymentMethod.tsx +++ b/app/screens/previewOrder/PaymentMethod.tsx @@ -37,6 +37,7 @@ import payMap from "../../utils/payMap"; // Define route params type type PaymentMethodRouteParams = { freight_forwarder_address_id?: number; + isFei?: boolean; }; // Define the root navigation params type RootStackParamList = { @@ -47,8 +48,8 @@ type RootStackParamList = { amount: number; }; Pay: { order_id: string }; - ShippingFee: { freight_forwarder_address_id?: number }; - PaymentMethod: { freight_forwarder_address_id?: number }; + ShippingFee: { freight_forwarder_address_id?: number; isFei?: boolean }; + PaymentMethod: { freight_forwarder_address_id?: number; isFei?: boolean }; PreviewAddress: undefined; AddressList: undefined; // Add other routes as needed @@ -333,6 +334,44 @@ export const PaymentMethod = () => { const { logPaymentConfirm } = useBurialPointStore(); const [isWaveExpanded, setIsWaveExpanded] = useState(false); + // Get isFei parameter from route + const isFei = route.params?.isFei || false; + + // State to store the original total price (fixed, won't change) + const [originalTotalPrice, setOriginalTotalPrice] = useState(0); + + // Helper function to get shipping fee - always return actual fee for display + const getShippingFee = () => { + return orderData?.shipping_fee || 0; + }; + + // Helper function to get converted shipping fee - always return actual converted fee for display + const getConvertedShippingFee = () => { + return convertedAmount.find((item) => item.item_key === "shipping_fee")?.converted_amount || 0; + }; + + // Helper function to get shipping fee for calculation (0 if isFei is true) + const getShippingFeeForCalculation = () => { + return isFei ? 0 : (orderData?.shipping_fee || 0); + }; + + // Helper function to get converted shipping fee for calculation (0 if isFei is true) + const getConvertedShippingFeeForCalculation = () => { + if (isFei) return 0; + return convertedAmount.find((item) => item.item_key === "shipping_fee")?.converted_amount || 0; + }; + + // Helper function to get converted total amount for calculation (excluding shipping fee if isFei is true) + const getConvertedTotalForCalculation = () => { + if (isFei) { + // If isFei is true, subtract the shipping fee from the total converted amount + const totalConverted = convertedAmount.reduce((acc, item) => acc + item.converted_amount, 0); + const shippingFeeConverted = convertedAmount.find((item) => item.item_key === "shipping_fee")?.converted_amount || 0; + return totalConverted - shippingFeeConverted; + } + return convertedAmount.reduce((acc, item) => acc + item.converted_amount, 0); + }; + const toggleExpanded = () => { setIsPaypalExpanded(!isPaypalExpanded); }; @@ -536,6 +575,17 @@ export const PaymentMethod = () => { console.log("orderData", orderData); }, [orderData]); + // Set original total price when both previewOrder and orderData are available + useEffect(() => { + if (previewOrder && orderData && originalTotalPrice === 0) { + const originalTotal = + (previewOrder.total_amount || 0) + + (orderData.domestic_shipping_fee || 0) + + (isFei ? 0 : (orderData.shipping_fee || 0)); + setOriginalTotalPrice(originalTotal); + } + }, [previewOrder, orderData, originalTotalPrice, isFei]); + const handleSubmit = async () => { if (!selectedPayment) { Alert.alert(t("payment.select_payment")); @@ -564,38 +614,26 @@ export const PaymentMethod = () => { createOrderData.payment_method = selectedPayment; createOrderData.total_amount = selectedPayment === "paypal" - ? convertedAmount.reduce( - (acc, item) => acc + item.converted_amount, - 0 - ) + ? getConvertedTotalForCalculation() : selectedPayment === "wave" - ? convertedAmount.reduce( - (acc, item) => acc + item.converted_amount, - 0 - ) + ? getConvertedTotalForCalculation() : Number( ( (previewOrder?.total_amount || 0) + (orderData?.domestic_shipping_fee || 0) + - (orderData?.shipping_fee || 0) + getShippingFeeForCalculation() ).toFixed(2) ); createOrderData.actual_amount = selectedPayment === "paypal" - ? convertedAmount.reduce( - (acc, item) => acc + item.converted_amount, - 0 - ) + ? getConvertedTotalForCalculation() : selectedPayment === "wave" - ? convertedAmount.reduce( - (acc, item) => acc + item.converted_amount, - 0 - ) + ? getConvertedTotalForCalculation() : Number( ( (previewOrder?.total_amount || 0) + (orderData?.domestic_shipping_fee || 0) + - (orderData?.shipping_fee || 0) + getShippingFeeForCalculation() ).toFixed(2) ); createOrderData.currency = @@ -612,12 +650,10 @@ export const PaymentMethod = () => { : orderData?.domestic_shipping_fee; createOrderData.shipping_fee = selectedPayment === "paypal" - ? convertedAmount.find((item) => item.item_key === "shipping_fee") - ?.converted_amount || 0 + ? getConvertedShippingFeeForCalculation() : selectedPayment === "wave" - ? convertedAmount.find((item) => item.item_key === "shipping_fee") - ?.converted_amount || 0 - : orderData?.shipping_fee; + ? getConvertedShippingFeeForCalculation() + : getShippingFeeForCalculation(); } setOrderData(createOrderData || {}); const data = { @@ -625,20 +661,14 @@ export const PaymentMethod = () => { offline_payment: currentTab === "offline" ? 0 : 1, all_price: selectedPayment === "paypal" - ? convertedAmount.reduce( - (acc, item) => acc + item.converted_amount, - 0 - ) + ? getConvertedTotalForCalculation() : selectedPayment === "wave" - ? convertedAmount.reduce( - (acc, item) => acc + item.converted_amount, - 0 - ) + ? getConvertedTotalForCalculation() : Number( ( (previewOrder?.total_amount || 0) + (orderData?.domestic_shipping_fee || 0) + - (orderData?.shipping_fee || 0) + getShippingFeeForCalculation() ).toFixed(2) ), all_quantity: previewOrder?.items?.reduce( @@ -647,7 +677,7 @@ export const PaymentMethod = () => { ), currency: selectedPayment === "paypal" ? selectedCurrency : selectedPayment === "wave" ? "FCFA" : user.currency, shipping_method: orderData?.transport_type || 0, - shipping_price_outside: orderData?.shipping_fee || 0, + shipping_price_outside: getShippingFeeForCalculation(), shipping_price_within: orderData?.domestic_shipping_fee || 0, timestamp: new Date().toISOString(), pay_product: JSON.stringify( @@ -694,20 +724,14 @@ export const PaymentMethod = () => { selectedPayment === "paypal" ? selectedCurrency : selectedPayment === "wave" ? "FCFA" : user.currency, amount: selectedPayment === "paypal" - ? convertedAmount.reduce( - (acc, item) => acc + item.converted_amount, - 0 - ) + ? getConvertedTotalForCalculation() : selectedPayment === "wave" - ? convertedAmount.reduce( - (acc, item) => acc + item.converted_amount, - 0 - ) + ? getConvertedTotalForCalculation() : Number( ( (previewOrder?.total_amount || 0) + - (createOrderData?.domestic_shipping_fee || 0) + - (createOrderData?.shipping_fee || 0) + (orderData?.domestic_shipping_fee || 0) + + getShippingFeeForCalculation() ).toFixed(2) ), }); @@ -884,7 +908,7 @@ export const PaymentMethod = () => { - {t("payment.domestic_shipping")} + {t("order.shipping.domestic_fee")} {selectedPayment === "paypal" @@ -908,17 +932,13 @@ export const PaymentMethod = () => { {t("payment.international_shipping")} - + {selectedPayment === "paypal" - ? convertedAmount.find( - (item) => item.item_key === "shipping_fee" - )?.converted_amount || 0 + ? getConvertedShippingFee() : selectedPayment === "wave" - ? convertedAmount.find( - (item) => item.item_key === "shipping_fee" - )?.converted_amount || 0 - : orderData?.shipping_fee || 0}{" "} + ? getConvertedShippingFee() + : getShippingFee()}{" "} {selectedPayment === "paypal" ? selectedCurrency === "USD" ? "USD" @@ -927,6 +947,17 @@ export const PaymentMethod = () => { ? "FCFA" : previewOrder?.currency} + {isFei && ( + Alert.alert( + t("payment.notice") || "Notice", + t("payment.cash_on_delivery") || "Cash on Delivery" + )} + > + ⚠️ + + )} @@ -953,11 +984,7 @@ export const PaymentMethod = () => { textDecorationLine: "line-through", }} > - {( - (previewOrder?.total_amount || 0) + - (createOrderData?.domestic_shipping_fee || 0) + - (createOrderData?.shipping_fee || 0) - ).toFixed(2)}{" "} + {originalTotalPrice.toFixed(2)}{" "} {previewOrder?.currency} { marginLeft: 10, }} > - {convertedAmount - .reduce( - (acc, item) => acc + item.converted_amount, - 0 - ) - .toFixed(2)} + {getConvertedTotalForCalculation().toFixed(2)} {selectedCurrency === "USD" ? "USD" : "EUR"} @@ -988,12 +1010,7 @@ export const PaymentMethod = () => { color: "#ff6000", }} > - {convertedAmount - .reduce( - (acc, item) => acc + item.converted_amount, - 0 - ) - .toFixed(2)} + {getConvertedTotalForCalculation().toFixed(2)} {selectedCurrency === "USD" ? "USD" : "EUR"} @@ -1008,11 +1025,7 @@ export const PaymentMethod = () => { textDecorationLine: "line-through", }} > - {( - (previewOrder?.total_amount || 0) + - (createOrderData?.domestic_shipping_fee || 0) + - (createOrderData?.shipping_fee || 0) - ).toFixed(2)}{" "} + {originalTotalPrice.toFixed(2)}{" "} {previewOrder?.currency} { marginLeft: 10, }} > - {convertedAmount - .reduce( - (acc, item) => acc + item.converted_amount, - 0 - ) - .toFixed(2)}{" "} + {getConvertedTotalForCalculation().toFixed(2)}{" "} FCFA @@ -1041,11 +1049,7 @@ export const PaymentMethod = () => { color: "#ff6000", }} > - {( - (previewOrder?.total_amount || 0) + - (createOrderData?.domestic_shipping_fee || 0) + - (createOrderData?.shipping_fee || 0) - ).toFixed(2)}{" "} + {originalTotalPrice.toFixed(2)}{" "} {previewOrder?.currency} )} @@ -1715,4 +1719,15 @@ const styles = StyleSheet.create({ fontWeight: "600", color: "#FF5100", }, + shippingFeeAmountRow: { + flexDirection: "row", + alignItems: "center", + }, + warningIconContainer: { + padding: 5, + }, + warningIcon: { + fontSize: fontSize(16), + color: "#ff6000", + }, }); diff --git a/app/screens/previewOrder/PreviewAddress.tsx b/app/screens/previewOrder/PreviewAddress.tsx index 2044336..61780fd 100644 --- a/app/screens/previewOrder/PreviewAddress.tsx +++ b/app/screens/previewOrder/PreviewAddress.tsx @@ -33,14 +33,12 @@ import { useTranslation } from "react-i18next"; import fontSize from "../../utils/fontsizeUtils"; type RootStackParamList = { - AddRess: { address?: AddressItem; cart_item_id?: number | string }; + AddRess: { address?: AddressItem; cart_item_id?: number | string; totalAmount?: number; isFei?: boolean }; AddressList: undefined; - ShippingFee: { cart_item_id : {}}; + ShippingFee: { cart_item_id: any; totalAmount?: number; isFei?: boolean }; }; type AddRessRouteProp = RouteProp; - - export const PreviewAddress = () => { const { t } = useTranslation(); const { @@ -68,7 +66,6 @@ export const PreviewAddress = () => { is_default: false, }); const [selectedCountry, setSelectedCountry] = useState(null); - const [isDefault, setIsDefault] = useState(false); const [copyPhoneToWhatsApp, setCopyPhoneToWhatsApp] = useState(false); const [phoneNumbersMatch, setPhoneNumbersMatch] = useState(true); const [errors, setErrors] = useState>({}); @@ -230,6 +227,7 @@ export const PreviewAddress = () => { navigation.navigate("ShippingFee",{ cart_item_id: route.params, + isFei: route.params.isFei || false }); } }; diff --git a/app/screens/previewOrder/ShippingFee.tsx b/app/screens/previewOrder/ShippingFee.tsx index 3021389..b347103 100644 --- a/app/screens/previewOrder/ShippingFee.tsx +++ b/app/screens/previewOrder/ShippingFee.tsx @@ -30,26 +30,22 @@ import useUserStore from "../../store/user"; import useBurialPointStore from "../../store/burialPoint"; import { getBurialPointData } from "../../store/burialPoint"; import { useTranslation } from "react-i18next"; -import { getCurrentLanguage } from '../../i18n'; - +import { getCurrentLanguage } from "../../i18n"; type RootStackParamList = { - ShippingFee: undefined; - PaymentMethod: { freight_forwarder_address_id: number }; + ShippingFee: { cart_item_id: any; totalAmount?: number; isFei?: boolean }; + PaymentMethod: { freight_forwarder_address_id: number; isFei?: boolean }; }; type ShippingFeeParams = { - cart_item_id: { - items: any[]; - cart_item_id: number; - }; + cart_item_id: any; + totalAmount: number; }; export const ShippingFee = () => { const { t } = useTranslation(); const navigation = useNavigation>(); - const route = - useRoute, string>>(); + const route = useRoute>(); const { fetchFreightForwarderAddress, state, @@ -69,8 +65,7 @@ export const ShippingFee = () => { const [selectedWarehouse, setSelectedWarehouse] = useState
(); const [domesticShippingFeeData, setDomesticShippingFeeData] = useState(); - const [isShippingFeeLoading, setIsShippingFeeLoading] = - useState(false); + const [isShippingFeeLoading, setIsShippingFeeLoading] = useState(false); const [count, setCount] = useState(); const { setOrderData, orderData, items } = useCreateOrderStore(); @@ -97,7 +92,12 @@ export const ShippingFee = () => { state.freightForwarderAddress.other_addresses.length > 0 ) { const firstItem = state.freightForwarderAddress.other_addresses[0]; - const label = (getCurrentLanguage() === 'fr' ? firstItem.country_name : firstItem.country_name_en) + " | " + firstItem.city; + const label = + (getCurrentLanguage() === "fr" + ? firstItem.country_name + : firstItem.country_name_en) + + " | " + + firstItem.city; setWarehouse(label); setSelectedWarehouseLabel(label); setCountryCode(firstItem.country_code); @@ -119,7 +119,11 @@ export const ShippingFee = () => { // 统一处理loading状态 useEffect(() => { - if (state.shippingFees && state.domesticShippingFees && isShippingFeeLoading) { + if ( + state.shippingFees && + state.domesticShippingFees && + isShippingFeeLoading + ) { setIsShippingFeeLoading(false); } }, [state.shippingFees, state.domesticShippingFees, isShippingFeeLoading]); @@ -140,7 +144,10 @@ export const ShippingFee = () => { const changeCountryHandel = async (value: string) => { if (value && freightForwarderAddress?.other_addresses) { const selectedWarehouse = freightForwarderAddress.other_addresses.find( - (item) => getCurrentLanguage() === 'fr' ? item.country_name : item.country_name_en+ " | " + item.city === value + (item) => + getCurrentLanguage() === "fr" + ? item.country_name + : item.country_name_en + " | " + item.city === value ); setSelectedWarehouse(selectedWarehouse); @@ -156,10 +163,10 @@ export const ShippingFee = () => { // 设置loading状态为true,开始计算 setIsShippingFeeLoading(true); setCount(t("order.shipping.calculating")); - + // 清空store中的旧数据,确保loading状态正确 clearShippingFees(); - + // 清空之前的运费数据,确保loading状态正确 setShippingFeeData(undefined); setDomesticShippingFeeData(undefined); @@ -205,10 +212,15 @@ export const ShippingFee = () => { country_city: selectedWarehouseLabel, timestamp: new Date().toISOString(), }; - logShippingConfirm(data,navigation.getState().routes[navigation.getState().index - 1]?.name as string); + logShippingConfirm( + data, + navigation.getState().routes[navigation.getState().index - 1] + ?.name as string + ); console.log(getBurialPointData()); navigation.navigate("PaymentMethod", { freight_forwarder_address_id: selectedWarehouse?.address_id || 0, + isFei:route.params.isFei }); } else { Alert.alert(t("order.shipping.select_method")); @@ -228,7 +240,9 @@ export const ShippingFee = () => { - {t("order.shipping.method")} + + {t("order.shipping.method")} + {state.isLoading ? ( @@ -239,7 +253,9 @@ export const ShippingFee = () => { 🚢 - {t("order.shipping.method")} + + {t("order.shipping.method")} + {[ @@ -286,7 +302,9 @@ export const ShippingFee = () => { 🏭 - {t("order.shipping.warehouse")} + + {t("order.shipping.warehouse")} + @@ -298,7 +316,8 @@ export const ShippingFee = () => { onPress={() => setModalVisible(true)} > - {selectedWarehouseLabel || t("order.shipping.select_warehouse")} + {selectedWarehouseLabel || + t("order.shipping.select_warehouse")} @@ -337,21 +356,36 @@ export const ShippingFee = () => { style={[ styles.optionItem, warehouse === - (getCurrentLanguage() === 'fr' ? item.country_name : item.country_name_en+ " | " + item.city) && - styles.selectedOption, + (getCurrentLanguage() === "fr" + ? item.country_name + : item.country_name_en + + " | " + + item.city) && styles.selectedOption, ]} onPress={() => handleSelectWarehouse( item.country_code, - (getCurrentLanguage() === 'fr' ? item.country_name : item.country_name_en) + " | " + item.city + (getCurrentLanguage() === "fr" + ? item.country_name + : item.country_name_en) + + " | " + + item.city ) } > - {(getCurrentLanguage() === 'fr' ? item.country_name : item.country_name_en) + " | " + item.city} + {(getCurrentLanguage() === "fr" + ? item.country_name + : item.country_name_en) + + " | " + + item.city} {warehouse === - (getCurrentLanguage() === 'fr' ? item.country_name : item.country_name_en) + " | " + item.city && ( + (getCurrentLanguage() === "fr" + ? item.country_name + : item.country_name_en) + + " | " + + item.city && ( )} @@ -376,18 +410,16 @@ export const ShippingFee = () => { marginLeft: 10, }} > - {shippingMethod === "sea" ? - t("order.shipping.sea_time") : - t("order.shipping.air_time")} + {shippingMethod === "sea" + ? t("order.shipping.sea_time") + : t("order.shipping.air_time")} {isShippingFeeLoading ? ( // 统一显示一个加载状态 - - {count} - + {count} { {userStore.user?.currency} + {userStore.user.country_code !== 225 ? ( + + + {t("order.preview.Cash_on_delivery")} + + + ) : ( + route.params.isFei ? ( + + + {t("order.preview.Cash_on_delivery")} + + + ) : ( + + ) + )} )} @@ -458,7 +507,9 @@ export const ShippingFee = () => { domesticShippingFeeData?.total_shipping_fee == null } > - {t("order.shipping.submit")} + + {t("order.shipping.submit")} + @@ -736,14 +787,25 @@ const styles = StyleSheet.create({ backgroundColor: "#ccc", }, loadingFeesContainer: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', + flexDirection: "row", + alignItems: "center", + justifyContent: "center", marginVertical: 15, }, calculatingText: { color: "#ff6000", fontSize: fontSize(14), - fontWeight: "500" + fontWeight: "500", + }, + delivery: { + alignItems: "center", + justifyContent: "center", + marginTop: 8, + }, + deliveryText: { + color: "#ff6000", + fontSize: fontSize(20), + fontWeight: "900", + textAlign: "center", }, });