You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1382 lines
46 KiB
1382 lines
46 KiB
import React, { useEffect, useCallback } from "react"; |
|
import { |
|
View, |
|
Text, |
|
Image, |
|
StyleSheet, |
|
TouchableOpacity, |
|
ScrollView, |
|
Modal, |
|
InteractionManager |
|
} from "react-native"; |
|
import widthUtils from "../utils/widthUtils"; |
|
import fontSize from "../utils/fontsizeUtils"; |
|
import CloseIcon from "../components/CloseIcon"; |
|
import { |
|
ProductDetailParams, |
|
ProductGroupList, |
|
SkuAttribute, |
|
Sku, |
|
} from "../services/api/productApi"; |
|
import { cartApi } from "../services/api/cart"; |
|
import { useState } from "react"; |
|
import { useNavigation } from "@react-navigation/native"; |
|
import { NativeStackNavigationProp } from "@react-navigation/native-stack"; |
|
interface ProductCardProps { |
|
onClose: () => void; |
|
product: ProductDetailParams; |
|
groupList: ProductGroupList[]; |
|
} |
|
|
|
const ProductCard: React.FC<ProductCardProps> = ({ |
|
onClose, |
|
product: localProduct, |
|
groupList: localGroupList, |
|
}: { |
|
onClose: () => void; |
|
product: ProductDetailParams; |
|
groupList: ProductGroupList[]; |
|
}) => { |
|
const navigation = useNavigation<NativeStackNavigationProp<any>>(); |
|
const [groupList, setGroupList] = |
|
useState<ProductGroupList[]>(localGroupList); |
|
const [product, setProduct] = useState<ProductDetailParams>(localProduct); |
|
const [imgTitle, setImgTitle] = useState<string>(""); |
|
const [sizeList, setSizeList] = useState<SkuAttribute[]>([]); |
|
const [sizeTitle, setSizeTitle] = useState<string>(""); |
|
const [size, setSize] = useState<string>(""); |
|
const [hasImg, setHasImg] = useState<ProductGroupList>(); |
|
const [noImgList, setNoImgList] = useState<Sku[]>([]); |
|
const [price, setPrice] = useState<number>(0); |
|
const [selectedSize, setSelectedSize] = useState<number>(0); |
|
const [totalPrice, setTotalPrice] = useState<number>(0); |
|
const [flag, setFlag] = useState<boolean>(false); |
|
const [deleteModalVisible, setDeleteModalVisible] = useState<boolean>(false); |
|
useEffect(() => { |
|
setPrice(product.price as number); |
|
const imageItem = groupList.filter((item) => item.has_image); |
|
if (imageItem.length > 0) { |
|
setSizeTitle(imageItem[imageItem.length - 1].attribute_name); |
|
imageItem.forEach((item) => { |
|
const colorItem = item.attributes.filter( |
|
(attribute) => attribute.has_color |
|
); |
|
if (colorItem.length > 0) { |
|
setImgTitle(colorItem[0].sku_image_url); |
|
} |
|
}); |
|
setFlag(true); |
|
} else { |
|
setFlag(false); |
|
} |
|
if (imageItem.length === 0) { |
|
setImgTitle(product.product_image_urls[0]); |
|
} |
|
const sizeItem = groupList.filter((item) => !item.has_image); |
|
if (sizeItem.length > 0) { |
|
setSizeTitle(sizeItem[sizeItem.length - 1].attribute_name); |
|
} |
|
|
|
const noImg = groupList |
|
.find((item) => !item.has_image) |
|
?.attributes.find((item) => item.has_color); |
|
setSize(noImg?.value ?? ""); |
|
|
|
const shotData = groupList.sort((a, b) => (a.has_image ? -1 : 1)); |
|
if (shotData.length > 1) { |
|
const hasImg = shotData[0]; |
|
if (hasImg) { |
|
// 创建一个深拷贝,避免修改原始数据 |
|
const processedImg = { ...hasImg }; |
|
processedImg.attributes = hasImg.attributes.map((attr) => ({ |
|
...attr, |
|
list: [], |
|
})); |
|
// 处理每个属性,添加匹配的SKU到list |
|
processedImg.attributes.forEach((attribute) => { |
|
product.skus.forEach((sku) => { |
|
// 检查SKU是否包含当前属性值 |
|
const matchedAttr = sku.attributes.find( |
|
(attr) => attr.value === attribute.value |
|
); |
|
|
|
if (matchedAttr) { |
|
// 创建SKU的复制,不修改原始SKU |
|
const skuCopy = { ...sku }; |
|
// 过滤属性,创建新的属性数组而不是修改原始数组 |
|
skuCopy.attributes = sku.attributes |
|
.filter((attr) => attr.value !== attribute.value) |
|
.map((attr) => ({ ...attr })); // 复制每个属性对象 |
|
|
|
// 将处理后的SKU添加到list |
|
attribute.list.push(skuCopy); |
|
} |
|
}); |
|
}); |
|
console.log(processedImg); |
|
|
|
setHasImg(processedImg); |
|
} else { |
|
setHasImg(groupList[0]); |
|
} |
|
} else { |
|
setNoImgList(product.skus); |
|
} |
|
|
|
const img = groupList |
|
.find((item) => item.has_image) |
|
?.attributes.find((item) => item.has_color); |
|
|
|
setSize(img?.value ?? ""); |
|
|
|
// 找到有图片的属性组 |
|
}, [groupList, product]); // 添加依赖,确保数据变化时重新处理 |
|
|
|
const handleColorSelect = (colorId: string, index: number) => { |
|
if (!hasImg) return; |
|
// setPrice(price ?? 0); |
|
|
|
// 创建attributes的深拷贝 |
|
const newAttributes = hasImg.attributes.map((attr, i) => { |
|
if (i === index) { |
|
// 当前选中项设为true |
|
return { ...attr, has_color: true }; |
|
} else { |
|
// 其他项设为false |
|
return { ...attr, has_color: false }; |
|
} |
|
}); |
|
|
|
const price = newAttributes[index].list[0].offer_price; |
|
setPrice( |
|
price ?? |
|
product.sale_info.price_range_list[ |
|
product.sale_info.price_range_list.length - 1 |
|
].price |
|
); |
|
|
|
// 更新hasImg状态 |
|
setHasImg({ |
|
...hasImg, |
|
attributes: newAttributes, |
|
}); |
|
}; |
|
|
|
const handleSizeSelect = ( |
|
value: string, |
|
type: string, |
|
index: number, |
|
amount_on_sale: number |
|
) => { |
|
if (!hasImg) return; |
|
|
|
const data = hasImg.attributes.find((item) => item.has_color); |
|
if (data) { |
|
// 创建hasImg的深拷贝 |
|
const newHasImg = { ...hasImg }; |
|
|
|
// 找到有颜色的属性索引 |
|
const colorIndex = newHasImg.attributes.findIndex( |
|
(item) => item.has_color |
|
); |
|
if (colorIndex !== -1) { |
|
// 创建属性数组的深拷贝 |
|
newHasImg.attributes = [...newHasImg.attributes]; |
|
|
|
// 创建特定属性的深拷贝 |
|
newHasImg.attributes[colorIndex] = { |
|
...newHasImg.attributes[colorIndex], |
|
}; |
|
|
|
// 创建list数组的深拷贝 |
|
newHasImg.attributes[colorIndex].list = [ |
|
...(newHasImg.attributes[colorIndex].list || []), |
|
]; |
|
|
|
// 创建特定list项的深拷贝 |
|
if (index < newHasImg.attributes[colorIndex].list.length) { |
|
newHasImg.attributes[colorIndex].list[index] = { |
|
...newHasImg.attributes[colorIndex].list[index], |
|
}; |
|
|
|
// 修改size值 |
|
if (type === "+") { |
|
newHasImg.attributes[colorIndex].size = |
|
(newHasImg.attributes[colorIndex].size ?? 0) + 1; |
|
if (newHasImg.attributes[colorIndex].size > amount_on_sale) { |
|
newHasImg.attributes[colorIndex].size = amount_on_sale; |
|
} |
|
newHasImg.attributes[colorIndex].list[index].size = |
|
(newHasImg.attributes[colorIndex].list[index].size ?? 0) + 1; |
|
|
|
if ( |
|
newHasImg.attributes[colorIndex].list[index].size > amount_on_sale |
|
) { |
|
newHasImg.attributes[colorIndex].list[index].size = |
|
amount_on_sale; |
|
} |
|
} else { |
|
newHasImg.attributes[colorIndex].size = |
|
(newHasImg.attributes[colorIndex].size ?? 0) - 1; |
|
newHasImg.attributes[colorIndex].list[index].size = |
|
(newHasImg.attributes[colorIndex].list[index].size ?? 0) - 1; |
|
|
|
if (newHasImg.attributes[colorIndex].list[index].size < 0) { |
|
newHasImg.attributes[colorIndex].list[index].size = 0; |
|
} |
|
if (newHasImg.attributes[colorIndex].size < 0) { |
|
newHasImg.attributes[colorIndex].size = 0; |
|
} |
|
} |
|
|
|
// 更新hasImg状态 |
|
setHasImg(newHasImg); |
|
calculateTotalSize(newHasImg); |
|
} |
|
} |
|
} |
|
}; |
|
|
|
// 无图片的加减 |
|
const handleNoImgSizeSelect = ( |
|
value: string, |
|
type: string, |
|
index: number, |
|
amount_on_sale: number |
|
) => { |
|
if (!noImgList) return; |
|
console.log(noImgList); |
|
|
|
if (type === "+") { |
|
noImgList[index].size = (noImgList[index].size ?? 0) + 1; |
|
if (noImgList[index].size > amount_on_sale) { |
|
noImgList[index].size = amount_on_sale; |
|
} |
|
} else { |
|
noImgList[index].size = (noImgList[index].size ?? 0) - 1; |
|
} |
|
if (noImgList[index].size < 0) { |
|
noImgList[index].size = 0; |
|
} |
|
setNoImgList([...noImgList]); |
|
|
|
let total = 0; |
|
let priceSum = 0; |
|
|
|
noImgList.forEach((item) => { |
|
total += item.size ?? 0; |
|
priceSum += |
|
(item.offer_price ?? |
|
product.sale_info.price_range_list[ |
|
product.sale_info.price_range_list.length - 1 |
|
].price) * (item.size ?? 0); |
|
}); |
|
|
|
setSelectedSize(total); |
|
setTotalPrice(priceSum); |
|
}; |
|
|
|
// 计算所有size的总和 |
|
const calculateTotalSize = (hasImgData: ProductGroupList | undefined) => { |
|
if (!hasImgData) return; |
|
|
|
let total = 0; |
|
let priceSum = 0; |
|
hasImgData.attributes.forEach((attr) => { |
|
attr.list?.forEach((item) => { |
|
const itemSize = item.size ?? 0; |
|
total += itemSize; |
|
priceSum += |
|
(item.offer_price ?? |
|
product.sale_info.price_range_list[ |
|
product.sale_info.price_range_list.length - 1 |
|
].price) * itemSize; |
|
}); |
|
}); |
|
|
|
setSelectedSize(total); |
|
setTotalPrice(priceSum); |
|
}; |
|
|
|
// 加入购物车 |
|
const addCartHandel = () => { |
|
if (groupList.length > 1) { |
|
const selectedSku = |
|
hasImg?.attributes.filter((item) => (item.size ?? 0) > 0) || []; |
|
const skus: { sku_id: number; quantity: number }[] = []; |
|
selectedSku.forEach((item) => { |
|
item.list.forEach((item) => { |
|
if ((item.size ?? 0) > 0) { |
|
skus.push({ |
|
sku_id: item.sku_id, |
|
quantity: item.size as number, |
|
}); |
|
} |
|
}); |
|
}); |
|
const data = { |
|
offer_id: product.offer_id, |
|
skus, |
|
}; |
|
cartApi(data).then((res) => { |
|
console.log(res); |
|
}); |
|
} else if (groupList.length === 1) { |
|
const selectedSku = |
|
noImgList.filter((item) => (item.size ?? 0) > 0) || []; |
|
const skus: { sku_id: number; quantity: number }[] = []; |
|
selectedSku.forEach((item) => { |
|
skus.push({ |
|
sku_id: item.sku_id, |
|
quantity: item.size as number, |
|
}); |
|
}); |
|
const data = { |
|
offer_id: product.offer_id, |
|
skus, |
|
}; |
|
cartApi(data).then((res) => { |
|
console.log(res); |
|
}); |
|
} |
|
setDeleteModalVisible(true); |
|
}; |
|
|
|
const cancelDelete = () => { |
|
// 关闭确认对话框 |
|
setDeleteModalVisible(false); |
|
}; |
|
|
|
const handleNavigateToCart = useCallback(() => { |
|
setDeleteModalVisible(false); |
|
InteractionManager.runAfterInteractions(() => { |
|
navigation.navigate("MainTabs", { screen: "Cart" }); |
|
}); |
|
}, [navigation]); |
|
|
|
return ( |
|
<View style={styles.container}> |
|
<View style={styles.productCardContainer3}> |
|
<View style={styles.pricingCard}> |
|
<View style={styles.flexRowAlignedEndFullWidth}> |
|
<View style={styles.productCardContainer}> |
|
<View style={styles.cardContainer}> |
|
<View style={styles.flexColumnEndAlign2}> |
|
<Image |
|
source={{ uri: imgTitle }} |
|
style={styles.flexColumnImg} |
|
/> |
|
{/* SVG commented out as requested */} |
|
{/* <View style={styles.svgContainer}> |
|
<svg viewBox="0 0 24 24" x="0" y="0" fill="none" xmlns="http://www.w3.org/2000/svg"> |
|
<g id="look" xmlns="http://www.w3.org/2000/svg"> |
|
<path id="Rectangle 653" d="M1,1h17c2.7614,0 5,2.239 5,5v17h-17c-2.7614,0 -5,-2.239 -5,-5z" fill="#5B5B5B" fill-opacity="0.7" /> |
|
<path id="Vector 12" d="M12,6h6v6" stroke="white" stroke-linecap="round" stroke-linejoin="round" /> |
|
<path id="Vector 13" d="M12,18h-6v-6" stroke="white" stroke-linecap="round" stroke-linejoin="round" /> |
|
</g> |
|
</svg> |
|
</View> */} |
|
</View> |
|
</View> |
|
</View> |
|
<View style={styles.productCardContainer2}> |
|
<View style={styles.productCardContainer1}> |
|
<View style={styles.priceInfoContainer1}> |
|
<Text style={styles.highlightedText}>{price}</Text> |
|
<View style={styles.priceInfoContainer2}> |
|
<Text style={styles.orangeHeading}>FCFA</Text> |
|
<View style={styles.percentageChangeContainer}> |
|
<Text style={styles.discountPercentageTextStyle}> |
|
-5% |
|
</Text> |
|
{/* SVG commented out as requested */} |
|
{/* <View style={styles.svgContainer1}> |
|
<svg viewBox="0 0 32 32" x="0" y="0" fill="none" xmlns="http://www.w3.org/2000/svg"> |
|
<defs> |
|
<linearGradient id="paint5_linear_128_1116" x1="7.443999999999988" y1="7.443999999999988" x2="12.580000000000013" y2="29.312000000000012" gradientUnits="userSpaceOnUse" xmlns="http://www.w3.org/2000/svg"> |
|
<stop stop-color="#FFE5AD" /> |
|
<stop offset="1" stop-color="#F9AE46" /> |
|
</linearGradient> |
|
<linearGradient id="paint6_linear_128_1116" x1="16" y1="2" x2="16" y2="30" gradientUnits="userSpaceOnUse" xmlns="http://www.w3.org/2000/svg"> |
|
<stop stop-color="white" /> |
|
<stop offset="1" stop-color="#FFD180" /> |
|
</linearGradient> |
|
</defs> |
|
<path id="Star 1_2" d="M14.621,3.313c0.772,-0.735 1.986,-0.735 2.758,0l1.401,1.334c0.439,0.418 1.043,0.615 1.644,0.534l1.917,-0.255c1.057,-0.141 2.039,0.572 2.232,1.621l0.349,1.903c0.109,0.596 0.483,1.11 1.016,1.398l1.701,0.92c0.939,0.507 1.314,1.661 0.853,2.623l-0.836,1.745c-0.262,0.546 -0.262,1.182 0,1.728l0.836,1.745c0.461,0.962 0.086,2.116 -0.853,2.623l-1.701,0.92c-0.533,0.288 -0.907,0.802 -1.016,1.398l-0.349,1.903c-0.193,1.049 -1.175,1.762 -2.232,1.621l-1.917,-0.255c-0.601,-0.081 -1.205,0.116 -1.644,0.534l-1.401,1.334c-0.772,0.735 -1.986,0.735 -2.758,0l-1.401,-1.334c-0.439,-0.418 -1.043,-0.615 -1.644,-0.534l-1.917,0.255c-1.057,0.141 -2.039,-0.572 -2.232,-1.621l-0.349,-1.903c-0.109,-0.596 -0.483,-1.11 -1.016,-1.398l-1.701,-0.92c-0.939,-0.507 -1.314,-1.661 -0.853,-2.623l0.836,-1.745c0.262,-0.546 0.262,-1.182 0,-1.728l-0.836,-1.745c-0.461,-0.962 -0.086,-2.116 0.853,-2.623l1.701,-0.92c0.533,-0.288 0.907,-0.802 1.016,-1.398l0.349,-1.903c0.193,-1.049 1.175,-1.762 2.232,-1.621l1.917,0.255c0.601,0.081 1.205,-0.116 1.644,-0.534z" fill="url(#paint5_linear_128_1116)" stroke="url(#paint6_linear_128_1116)" xmlns="http://www.w3.org/2000/svg" /> |
|
</svg> |
|
</View> */} |
|
</View> |
|
</View> |
|
</View> |
|
<View style={styles.vipButtonContainer}> |
|
<View style={styles.vipButton}> |
|
<Text style={styles.italicBoldSegoeVip}>VIP</Text> |
|
</View> |
|
</View> |
|
</View> |
|
<View style={styles.pricingCardContainer}> |
|
<View style={styles.pricingCard}> |
|
<View style={styles.priceInfoContainer}> |
|
<Text style={styles.priceHighlightedText}>3072</Text> |
|
<Text style={styles.priceTagBold}>FCFA</Text> |
|
</View> |
|
<Text style={styles.productPriceTier}>≥2 Pièces</Text> |
|
</View> |
|
<View style={styles.pricingCard}> |
|
<View style={styles.priceInfoContainer}> |
|
<Text style={styles.priceHighlightedText}>2500</Text> |
|
<Text style={styles.priceTagBold}>FCFA</Text> |
|
</View> |
|
<Text style={styles.productPriceTier}>≥50 Pièces</Text> |
|
</View> |
|
<View style={styles.pricingCard}> |
|
<View style={styles.priceInfoContainer}> |
|
<Text style={styles.priceHighlightedText}>2099</Text> |
|
<Text style={styles.priceTagBold}>FCFA</Text> |
|
</View> |
|
<Text style={styles.productPriceTier}>≥100 Pièces</Text> |
|
</View> |
|
</View> |
|
</View> |
|
</View> |
|
<View style={styles.productDetailsContainer}> |
|
{hasImg && groupList.length > 1 && hasImg.has_image && ( |
|
<View style={{ flex: 1 }}> |
|
<Text style={styles.primaryTextHeading}> |
|
{hasImg?.attribute_name}: {size} |
|
</Text> |
|
|
|
<ScrollView |
|
horizontal |
|
showsHorizontalScrollIndicator={false} |
|
key={hasImg.attribute_name} |
|
style={{ flexGrow: 0 }} |
|
> |
|
<View |
|
style={{ flexDirection: "row", gap: 12, width: "100%" }} |
|
> |
|
{hasImg.attributes.map((attribute, index1) => ( |
|
<TouchableOpacity |
|
key={attribute.value + index1} |
|
onPress={() => |
|
handleColorSelect(attribute.value, index1) |
|
} |
|
> |
|
<View |
|
style={[ |
|
styles.colorPaletteContainer1, |
|
attribute.has_color && |
|
styles.selectedColorImageContainer, |
|
]} |
|
> |
|
<View |
|
key={attribute.value} |
|
style={styles.cardContainerWithTitle} |
|
> |
|
<View style={styles.cardContainerWithImage}> |
|
<Image |
|
source={{ uri: attribute.sku_image_url }} |
|
style={styles.imageContainer} |
|
/> |
|
{(attribute.size ?? 0) > 0 && ( |
|
<View style={styles.topLeftBadge}> |
|
<Text style={styles.topLeftBadgeText}> |
|
x{attribute.size} |
|
</Text> |
|
</View> |
|
)} |
|
</View> |
|
<Text style={styles.profileCard}> |
|
{attribute.value} |
|
</Text> |
|
</View> |
|
</View> |
|
</TouchableOpacity> |
|
))} |
|
</View> |
|
</ScrollView> |
|
<View style={styles.specifications}> |
|
<Text style={styles.primaryTextHeading}>{sizeTitle}</Text> |
|
<View style={styles.specificationsList}> |
|
<ScrollView showsHorizontalScrollIndicator={false}> |
|
{/* 显示属性列表 */} |
|
{hasImg.attributes |
|
.find((item) => item.has_color) |
|
?.list.map((list, index1) => ( |
|
<View |
|
key={list?.sku_id} |
|
style={styles.specificationsItem} |
|
> |
|
<View> |
|
<View |
|
style={{ |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "space-between", |
|
}} |
|
> |
|
{(list?.size ?? 0) > 0 && ( |
|
<Text style={styles.selectedNumText}> |
|
x{list?.size} |
|
</Text> |
|
)} |
|
<Text |
|
style={styles.sizeText} |
|
numberOfLines={1} |
|
ellipsizeMode="tail" |
|
> |
|
{list?.attributes[0]?.value} |
|
</Text> |
|
</View> |
|
<Text style={styles.amountText}> |
|
库存 {list?.amount_on_sale} |
|
</Text> |
|
</View> |
|
|
|
<View style={styles.numberContainer}> |
|
<TouchableOpacity |
|
onPress={() => |
|
handleSizeSelect( |
|
list?.attributes[0]?.value, |
|
"-", |
|
index1, |
|
list.amount_on_sale |
|
) |
|
} |
|
> |
|
<Text>-</Text> |
|
</TouchableOpacity> |
|
<Text style={styles.numText}> |
|
{list?.size ?? 0} |
|
</Text> |
|
<TouchableOpacity |
|
onPress={() => |
|
handleSizeSelect( |
|
list?.attributes[0]?.value, |
|
"+", |
|
index1, |
|
list.amount_on_sale |
|
) |
|
} |
|
> |
|
<Text>+</Text> |
|
</TouchableOpacity> |
|
</View> |
|
</View> |
|
))} |
|
</ScrollView> |
|
</View> |
|
</View> |
|
</View> |
|
)} |
|
|
|
{hasImg && groupList.length > 1 && !hasImg.has_image && ( |
|
<View style={{ flex: 1 }}> |
|
<Text style={styles.primaryTextHeading}> |
|
{hasImg?.attribute_name}: {size} |
|
</Text> |
|
<View style={styles.specifications}> |
|
<ScrollView |
|
style={styles.sizeList} |
|
showsHorizontalScrollIndicator={false} |
|
> |
|
{hasImg.attributes.map((item, index) => ( |
|
<TouchableOpacity |
|
key={item.value} |
|
style={[ |
|
styles.sizeItem, |
|
item.has_color && styles.sizeActiveItem, |
|
]} |
|
onPress={() => handleColorSelect(item.value, index)} |
|
> |
|
<View style={styles.fixedCornerView}> |
|
{item.size && ( |
|
<Text style={styles.fixedCornerText}> |
|
x{item.size} |
|
</Text> |
|
)} |
|
</View> |
|
<Text |
|
style={item.has_color && styles.sizeActiveItemText} |
|
> |
|
{item.value} |
|
</Text> |
|
</TouchableOpacity> |
|
))} |
|
|
|
<View> |
|
<Text style={styles.sizeTitle}>{sizeTitle}</Text> |
|
<View> |
|
{hasImg.attributes |
|
.find((item) => item.has_color) |
|
?.list.map((list, index1) => ( |
|
<View |
|
key={list?.sku_id} |
|
style={styles.specificationsItem} |
|
> |
|
<View> |
|
<View |
|
style={{ |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "space-between", |
|
}} |
|
> |
|
{(list?.size ?? 0) > 0 && ( |
|
<Text style={styles.selectedNumText}> |
|
x{list?.size} |
|
</Text> |
|
)} |
|
<Text |
|
style={styles.sizeText} |
|
numberOfLines={1} |
|
ellipsizeMode="tail" |
|
> |
|
{list?.attributes[0]?.value} |
|
</Text> |
|
</View> |
|
<Text style={styles.amountText}> |
|
库存 {list?.amount_on_sale} |
|
</Text> |
|
</View> |
|
|
|
<View style={styles.numberContainer}> |
|
<TouchableOpacity |
|
onPress={() => |
|
handleSizeSelect( |
|
list?.attributes[0]?.value, |
|
"-", |
|
index1, |
|
list.amount_on_sale |
|
) |
|
} |
|
> |
|
<Text>-</Text> |
|
</TouchableOpacity> |
|
<Text style={styles.numText}> |
|
{list?.size ?? 0} |
|
</Text> |
|
<TouchableOpacity |
|
onPress={() => |
|
handleSizeSelect( |
|
list?.attributes[0]?.value, |
|
"+", |
|
index1, |
|
list.amount_on_sale |
|
) |
|
} |
|
> |
|
<Text>+</Text> |
|
</TouchableOpacity> |
|
</View> |
|
</View> |
|
))} |
|
</View> |
|
</View> |
|
</ScrollView> |
|
</View> |
|
</View> |
|
)} |
|
|
|
{noImgList && groupList.length === 1 && !flag && ( |
|
<View style={styles.specifications}> |
|
<Text style={styles.primaryTextHeading}> |
|
{sizeTitle}: {size} |
|
</Text> |
|
<View style={styles.specificationsList}> |
|
<ScrollView |
|
showsHorizontalScrollIndicator={false} |
|
showsVerticalScrollIndicator={false} |
|
style={{ height: "65%" }} |
|
> |
|
{/* 显示属性列表 */} |
|
{noImgList?.map((list, index1) => ( |
|
<View |
|
key={list?.sku_id} |
|
style={styles.specificationsItem} |
|
> |
|
<View> |
|
<View |
|
style={{ |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "space-between", |
|
}} |
|
> |
|
{(list?.size ?? 0) > 0 && ( |
|
<Text style={styles.selectedNumText}> |
|
x{list?.size} |
|
</Text> |
|
)} |
|
<Text |
|
style={styles.sizeText} |
|
numberOfLines={1} |
|
ellipsizeMode="tail" |
|
> |
|
{list?.attributes[0]?.value} |
|
</Text> |
|
</View> |
|
<Text style={styles.amountText}> |
|
库存 {list?.amount_on_sale} |
|
</Text> |
|
</View> |
|
|
|
<View style={styles.numberContainer}> |
|
<TouchableOpacity |
|
onPress={() => |
|
handleNoImgSizeSelect( |
|
list?.attributes[0]?.value, |
|
"-", |
|
index1, |
|
list.amount_on_sale |
|
) |
|
} |
|
> |
|
<Text>-</Text> |
|
</TouchableOpacity> |
|
<Text style={styles.numText}>{list?.size ?? 0}</Text> |
|
<TouchableOpacity |
|
onPress={() => |
|
handleNoImgSizeSelect( |
|
list?.attributes[0]?.value, |
|
"+", |
|
index1, |
|
list.amount_on_sale |
|
) |
|
} |
|
> |
|
<Text>+</Text> |
|
</TouchableOpacity> |
|
</View> |
|
</View> |
|
))} |
|
</ScrollView> |
|
</View> |
|
</View> |
|
)} |
|
|
|
{noImgList && groupList.length === 1 && flag && ( |
|
<View style={styles.specifications}> |
|
<Text style={styles.primaryTextHeading}> |
|
{sizeTitle}: {size} |
|
</Text> |
|
<View style={styles.specificationsList}> |
|
<ScrollView |
|
showsVerticalScrollIndicator={false} |
|
style={{ height: "80%" }} |
|
> |
|
{/* 显示属性列表 */} |
|
{noImgList?.map((list, index1) => ( |
|
<View |
|
key={list?.sku_id} |
|
style={styles.specificationsItem} |
|
> |
|
<View> |
|
<View |
|
style={{ |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "space-between", |
|
}} |
|
> |
|
<View |
|
style={{ |
|
width: widthUtils(50,50).width, |
|
height: widthUtils(50,50).height, |
|
borderRadius: 5, |
|
marginRight: 10, |
|
}} |
|
> |
|
<Image |
|
source={{ |
|
uri: list?.attributes[0]?.sku_image_url, |
|
}} |
|
style={{ |
|
width: widthUtils(50,50).width, |
|
height: widthUtils(50,50).height, |
|
borderRadius: 5, |
|
}} |
|
/> |
|
</View> |
|
<View> |
|
<View> |
|
<View |
|
style={{ |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "space-between", |
|
}} |
|
> |
|
{(list?.size ?? 0) > 0 && ( |
|
<Text style={styles.selectedNumText}> |
|
x{list?.size} |
|
</Text> |
|
)} |
|
<Text |
|
style={styles.sizeText} |
|
numberOfLines={1} |
|
ellipsizeMode="tail" |
|
> |
|
{list?.attributes[0]?.value} |
|
</Text> |
|
</View> |
|
</View> |
|
|
|
<Text style={styles.amountText}> |
|
库存 {list?.amount_on_sale} |
|
</Text> |
|
</View> |
|
</View> |
|
</View> |
|
|
|
<View style={styles.numberContainer}> |
|
<TouchableOpacity |
|
onPress={() => |
|
handleNoImgSizeSelect( |
|
list?.attributes[0]?.value, |
|
"-", |
|
index1, |
|
list.amount_on_sale |
|
) |
|
} |
|
> |
|
<Text>-</Text> |
|
</TouchableOpacity> |
|
<Text style={styles.numText}>{list?.size ?? 0}</Text> |
|
<TouchableOpacity |
|
onPress={() => |
|
handleNoImgSizeSelect( |
|
list?.attributes[0]?.value, |
|
"+", |
|
index1, |
|
list.amount_on_sale |
|
) |
|
} |
|
> |
|
<Text>+</Text> |
|
</TouchableOpacity> |
|
</View> |
|
</View> |
|
))} |
|
</ScrollView> |
|
</View> |
|
</View> |
|
)} |
|
</View> |
|
</View> |
|
</View> |
|
<View style={styles.closeIconContainer}> |
|
<TouchableOpacity onPress={onClose}> |
|
<CloseIcon size={18} /> |
|
</TouchableOpacity> |
|
</View> |
|
<View style={styles.bottomFixedContainer}> |
|
<View> |
|
<View style={styles.bottomFixedContainer1}> |
|
<Text style={styles.bottomFixedContainerText}> |
|
总数量:{selectedSize} |
|
</Text> |
|
<Text style={styles.bottomFixedContainerText}> |
|
Total: {totalPrice.toFixed(2)} FCFA |
|
</Text> |
|
</View> |
|
<TouchableOpacity |
|
style={styles.bottomFixedContainer2} |
|
onPress={addCartHandel} |
|
> |
|
<View style={styles.bottomFixedContainer2}> |
|
<Text style={styles.bottomFixedContainerButtonText}> |
|
加入购物车 |
|
</Text> |
|
</View> |
|
</TouchableOpacity> |
|
</View> |
|
</View> |
|
|
|
<Modal |
|
visible={deleteModalVisible} |
|
transparent |
|
animationType="fade" |
|
onRequestClose={cancelDelete} |
|
> |
|
<View style={styles.overlay}> |
|
<View style={styles.popup}> |
|
{/* <Image |
|
source={require("../assets/image_5f59afb0.png")} // 替换成你实际的路径 |
|
style={styles.image} |
|
/> */} |
|
<Text style={styles.promptText}>Supprimer l'article ?</Text> |
|
<View style={styles.buttonContainer}> |
|
<TouchableOpacity style={styles.cancelButton1} onPress={cancelDelete}> |
|
<Text style={styles.cancelText}>Non</Text> |
|
</TouchableOpacity> |
|
<TouchableOpacity style={styles.confirmButton} onPress={handleNavigateToCart}> |
|
<Text style={styles.confirmText}>Voir le panier</Text> |
|
</TouchableOpacity> |
|
</View> |
|
</View> |
|
</View> |
|
</Modal> |
|
</View> |
|
); |
|
}; |
|
|
|
const styles = StyleSheet.create({ |
|
container: { |
|
width: "100%", |
|
backgroundColor: "white", |
|
height: "100%", |
|
}, |
|
productCardContainer3: { |
|
flexDirection: "column", |
|
alignItems: "stretch", |
|
justifyContent: "flex-start", |
|
width: "100%", |
|
paddingTop: 15, |
|
paddingRight: 19, |
|
paddingLeft: 19, |
|
height: "100%", |
|
}, |
|
pricingCard: { |
|
paddingTop: 5, |
|
paddingBottom: 5, |
|
height: "100%", |
|
}, |
|
flexRowAlignedEndFullWidth: { |
|
flexDirection: "row", |
|
alignItems: "flex-end", |
|
justifyContent: "flex-start", |
|
width: "100%", |
|
}, |
|
productCardContainer: { |
|
flexBasis: widthUtils(80, 80).width, |
|
paddingTop: 5, |
|
}, |
|
cardContainer: { |
|
width: "100%", |
|
backgroundColor: "#e0e0e0", |
|
borderRadius: 5, |
|
}, |
|
flexColumnEndAlign2: { |
|
flexDirection: "column", |
|
alignItems: "flex-end", |
|
justifyContent: "flex-start", |
|
width: "100%", |
|
height: widthUtils(80, 80).height, |
|
borderRadius: 5, |
|
}, |
|
flexColumnImg: { |
|
width: "100%", |
|
height: "100%", |
|
borderRadius: 5, |
|
}, |
|
productCardContainer2: { |
|
flexBasis: widthUtils(295, 295).width, |
|
marginLeft: 15, |
|
}, |
|
productCardContainer1: { |
|
flexDirection: "row", |
|
alignItems: "flex-end", |
|
justifyContent: "flex-start", |
|
}, |
|
priceInfoContainer1: { |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "flex-start", |
|
}, |
|
highlightedText: { |
|
padding: 0, |
|
margin: 0, |
|
fontWeight: "700", |
|
fontSize: fontSize(30), |
|
fontFamily: "Segoe UI", |
|
color: "#ff5100", |
|
}, |
|
priceInfoContainer2: { |
|
flexDirection: "row", |
|
alignItems: "flex-start", |
|
justifyContent: "flex-start", |
|
marginLeft: 1, |
|
}, |
|
orangeHeading: { |
|
padding: 0, |
|
paddingBottom: 14, |
|
margin: 0, |
|
fontWeight: "700", |
|
fontSize: fontSize(14), |
|
fontFamily: "Segoe UI", |
|
color: "#ff5100", |
|
}, |
|
percentageChangeContainer: { |
|
flexDirection: "column", |
|
alignItems: "center", |
|
justifyContent: "flex-start", |
|
marginLeft: 14.5, |
|
}, |
|
discountPercentageTextStyle: { |
|
padding: 0, |
|
margin: 0, |
|
fontStyle: "italic", |
|
fontWeight: "900", |
|
fontSize: fontSize(11), |
|
fontFamily: "Segoe UI", |
|
color: "#4e2000", |
|
}, |
|
vipButtonContainer: { |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "flex-start", |
|
marginLeft: 1.25, |
|
}, |
|
vipButton: { |
|
width: widthUtils(55,55).width, |
|
minWidth: 55, |
|
height: 21, |
|
marginLeft: -2.5, |
|
backgroundColor: "#3b3b3b", |
|
borderWidth: 0, |
|
borderRadius: 5, |
|
borderBottomLeftRadius: 0, |
|
}, |
|
italicBoldSegoeVip: { |
|
fontStyle: "italic", |
|
fontWeight: "900", |
|
fontSize: fontSize(14), |
|
fontFamily: "Segoe UI", |
|
}, |
|
pricingCardContainer: { |
|
flexDirection: "row", |
|
gap: widthUtils(29.5, 29.5).width, |
|
alignItems: "flex-start", |
|
justifyContent: "space-between", |
|
width: "100%", |
|
paddingRight: 15, |
|
paddingBottom: 3, |
|
paddingLeft: 11, |
|
marginTop: 7, |
|
backgroundColor: "#f3f4f8", |
|
borderRadius: 5, |
|
}, |
|
priceInfoContainer: { |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "flex-start", |
|
}, |
|
priceHighlightedText: { |
|
padding: 0, |
|
margin: 0, |
|
fontWeight: "700", |
|
fontSize: fontSize(16), |
|
fontFamily: "Segoe UI", |
|
color: "#373737", |
|
}, |
|
priceTagBold: { |
|
padding: 0, |
|
margin: 0, |
|
fontWeight: "700", |
|
fontSize: fontSize(11), |
|
fontFamily: "Segoe UI", |
|
color: "#373737", |
|
}, |
|
productPriceTier: { |
|
padding: 0, |
|
margin: 0, |
|
marginTop: -4, |
|
fontWeight: "400", |
|
fontSize: fontSize(12), |
|
fontFamily: "PingFang SC", |
|
color: "#373737", |
|
}, |
|
productDetailsContainer: { |
|
width: "100%", |
|
marginTop: 24, |
|
height: "100%", |
|
}, |
|
primaryTextHeading: { |
|
padding: 0, |
|
margin: 0, |
|
fontWeight: "600", |
|
fontSize: fontSize(16), |
|
lineHeight: fontSize(20), |
|
fontFamily: "Segoe UI", |
|
color: "black", |
|
}, |
|
colorPaletteContainer1: { |
|
marginTop: 12, |
|
}, |
|
cardContainerWithTitle: { |
|
flexDirection: "column", |
|
alignItems: "stretch", |
|
justifyContent: "flex-start", |
|
width: widthUtils(116,116).width, |
|
height: widthUtils(116,116).height, |
|
paddingBottom: 5, |
|
backgroundColor: "#f4f4f4", |
|
borderRadius: 5, |
|
}, |
|
cardContainerWithImage: { |
|
flexDirection: "row", |
|
alignItems: "flex-start", |
|
justifyContent: "flex-start", |
|
borderRadius: 5, |
|
width: widthUtils(90,90).width, |
|
height: widthUtils(90,90).height, |
|
}, |
|
imageContainer: { |
|
width: "100%", |
|
height: "100%", |
|
borderWidth: 0, |
|
resizeMode: "cover", |
|
}, |
|
profileCard: { |
|
alignSelf: "center", |
|
padding: 0, |
|
margin: 0, |
|
marginTop: 1, |
|
fontWeight: "400", |
|
fontFamily: "Segoe UI", |
|
color: "black", |
|
textAlign: "center", |
|
width: widthUtils(90,26).width, |
|
height: widthUtils(90,26).height, |
|
fontSize: fontSize(18), |
|
}, |
|
closeIconContainer: { |
|
position: "absolute", |
|
top: 15, |
|
right: 15, |
|
zIndex: 1, |
|
}, |
|
selectedColorImageContainer: { |
|
borderWidth: 1, |
|
borderColor: "#ff5217", |
|
}, |
|
topLeftBadge: { |
|
position: "absolute", |
|
top: -6, |
|
left: -1, |
|
width: widthUtils(16,30).width, |
|
height: widthUtils(16,30).height, |
|
borderRadius: 8, |
|
backgroundColor: "#ff5323", |
|
zIndex: 1, |
|
alignItems: "center", |
|
justifyContent: "center", |
|
}, |
|
topLeftBadgeText: { |
|
color: "white", |
|
fontSize: fontSize(10), |
|
fontWeight: "400", |
|
fontFamily: "Segoe UI", |
|
textAlign: "center", |
|
lineHeight: fontSize(16), |
|
}, |
|
specifications: { |
|
flex: 1, |
|
paddingVertical: 10, |
|
}, |
|
sizeList: { |
|
gap: 5, |
|
}, |
|
sizeItem: { |
|
paddingHorizontal: 10, |
|
paddingVertical: 8, |
|
borderRadius: 5, |
|
marginTop: 10, |
|
backgroundColor: "#efefef", |
|
}, |
|
sizeActiveItem: { |
|
backgroundColor: "#ff5323", |
|
color: "#ffffff", |
|
}, |
|
sizeActiveItemText: { |
|
color: "#ffffff", |
|
}, |
|
sizeTitle: { |
|
marginTop: 5, |
|
padding: 0, |
|
margin: 0, |
|
fontWeight: "600", |
|
fontSize: fontSize(16), |
|
lineHeight: fontSize(20), |
|
fontFamily: "Segoe UI", |
|
color: "black", |
|
}, |
|
specificationsList: { |
|
marginTop: 10, |
|
}, |
|
specificationsItem: { |
|
paddingVertical: 5, |
|
flexDirection: "row", |
|
justifyContent: "space-between", |
|
alignItems: "center", |
|
}, |
|
sizeText: { |
|
fontSize: fontSize(16), |
|
fontWeight: "600", |
|
fontFamily: "Segoe UI", |
|
color: "black", |
|
width: widthUtils(200,200).width, |
|
}, |
|
selectedNumText: { |
|
width: widthUtils(16,30).width, |
|
height: widthUtils(16,30).height, |
|
backgroundColor: "#ff5217", |
|
borderRadius: 5, |
|
color: "white", |
|
textAlign: "center", |
|
fontSize: fontSize(12), |
|
fontWeight: "600", |
|
fontFamily: "Segoe UI", |
|
marginRight: 5, |
|
lineHeight: 18, |
|
}, |
|
amountText: { |
|
fontSize: fontSize(16), |
|
fontWeight: "600", |
|
fontFamily: "Segoe UI", |
|
color: "#bdbdbd", |
|
}, |
|
numberContainer: { |
|
flexDirection: "row", |
|
alignItems: "center", |
|
}, |
|
numText: { |
|
width: widthUtils(24,40).width, |
|
height: widthUtils(24,40).height, |
|
textAlign: "center", |
|
fontSize: fontSize(16), |
|
fontWeight: "600", |
|
fontFamily: "Segoe UI", |
|
color: "black", |
|
backgroundColor: "#f4f4f4", |
|
borderRadius: 5, |
|
lineHeight: fontSize(28), |
|
marginHorizontal: 5, |
|
}, |
|
bottomFixedContainer: { |
|
position: "absolute", |
|
bottom: 0, |
|
left: 0, |
|
width: "100%", |
|
height: widthUtils(118,118).height, |
|
backgroundColor: "white", |
|
borderTopWidth: 1, |
|
borderTopColor: "#f4f4f4", |
|
elevation: 5, |
|
shadowColor: "#000", |
|
shadowOffset: { width: 0, height: -2 }, |
|
shadowOpacity: 0.1, |
|
shadowRadius: 3, |
|
paddingHorizontal: 19, |
|
paddingVertical: 15, |
|
}, |
|
bottomFixedContainer1: { |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "space-between", |
|
paddingTop: 10, |
|
paddingBottom: 10, |
|
}, |
|
bottomFixedContainerText: { |
|
fontSize: fontSize(14), |
|
fontWeight: "600", |
|
fontFamily: "PingFang SC", |
|
color: "black", |
|
}, |
|
bottomFixedContainer2: { |
|
width: "100%", |
|
height: widthUtils(40,40).height, |
|
backgroundColor: "#ff5217", |
|
borderRadius: 25, |
|
alignItems: "center", |
|
justifyContent: "center", |
|
}, |
|
bottomFixedContainerButtonText: { |
|
fontSize: fontSize(14), |
|
fontWeight: "600", |
|
fontFamily: "PingFang SC", |
|
color: "white", |
|
}, |
|
fixedCornerView: { |
|
position: "absolute", |
|
top: -8, |
|
left: 0, |
|
width: widthUtils(16,30).width, |
|
height: widthUtils(16,30).height, |
|
zIndex: 10, |
|
borderRadius: 5, |
|
}, |
|
fixedCornerText: { |
|
fontSize: fontSize(12), |
|
fontWeight: "600", |
|
fontFamily: "Segoe UI", |
|
color: "white", |
|
textAlign: "center", |
|
lineHeight: fontSize(18), |
|
backgroundColor: "#ff5217", |
|
borderRadius: 5, |
|
}, |
|
overlay: { |
|
flex: 1, |
|
backgroundColor: "rgba(0,0,0,0.4)", |
|
justifyContent: "center", |
|
alignItems: "center", |
|
}, |
|
popup: { |
|
backgroundColor: "white", |
|
borderRadius: 10, |
|
paddingVertical: 27, |
|
paddingHorizontal: 20, |
|
alignItems: "center", |
|
gap: 21, |
|
}, |
|
image: { |
|
width: widthUtils(80,80).width, |
|
height: widthUtils(80,80).height, |
|
borderRadius: 5, |
|
resizeMode: "cover", |
|
}, |
|
promptText: { |
|
fontSize: fontSize(20), |
|
fontWeight: "600", |
|
color: "black", |
|
fontFamily: "Segoe UI", // 注意要在项目中配置字体 |
|
}, |
|
buttonContainer: { |
|
flexDirection: "row", |
|
justifyContent: "center", |
|
marginTop: 10, |
|
}, |
|
cancelButton1: { |
|
width: widthUtils(50,160).width, |
|
height: widthUtils(50,160).height, |
|
borderRadius: 25, |
|
backgroundColor: "#f2f3f5", |
|
justifyContent: "center", |
|
alignItems: "center", |
|
}, |
|
confirmButton: { |
|
width: widthUtils(50,160).width, |
|
height: widthUtils(50,160).height, |
|
borderRadius: 25, |
|
backgroundColor: "#002fa7", |
|
justifyContent: "center", |
|
alignItems: "center", |
|
marginLeft: 20, |
|
}, |
|
cancelText: { |
|
fontSize: fontSize(16), |
|
fontWeight: "500", |
|
color: "#333333", |
|
fontFamily: "Source Han Sans CN", // 注意要在项目中配置字体 |
|
}, |
|
confirmText: { |
|
fontSize: fontSize(16), |
|
fontWeight: "500", |
|
color: "#ffffff", |
|
fontFamily: "Source Han Sans CN", // 同上 |
|
}, |
|
}); |
|
|
|
export default ProductCard;
|
|
|