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.
1768 lines
56 KiB
1768 lines
56 KiB
import React, { useEffect, useCallback, useState } from "react"; |
|
import { |
|
View, |
|
Text, |
|
Image, |
|
StyleSheet, |
|
TouchableOpacity, |
|
ScrollView, |
|
Dimensions, |
|
useWindowDimensions, |
|
Animated, |
|
BackHandler, |
|
ActivityIndicator, |
|
Alert, |
|
InteractionManager, |
|
Platform, |
|
StatusBar, |
|
SafeAreaView, |
|
Modal, |
|
} from "react-native"; |
|
import fontSize from "../utils/fontsizeUtils"; |
|
import widthUtils from "../utils/widthUtils"; |
|
import DiagonalArrowIcon from "../components/DiagonalArrowIcon"; |
|
import Carousel from "react-native-reanimated-carousel"; |
|
import WhiteCircleIcon from "../components/WhiteCircleIconIcon"; |
|
import ShoppingCartIcon from "../components/ShoppingCartIcon"; |
|
import HeartIcon from "../components/HeartIcon"; |
|
import HeartRedIcon from "../components/HeartIconRed"; |
|
import ShareIcon from "../components/ShareIcon"; |
|
import { Image as ExpoImage, ImageBackground } from "expo-image"; |
|
import useUserStore from "../store/user"; |
|
import { getSubjectTransLanguage } from "../utils/languageUtils"; |
|
import { useTranslation } from "react-i18next"; |
|
import { getBurialPointData } from "../store/burialPoint"; |
|
import useBurialPointStore from "../store/burialPoint"; |
|
import * as ImagePicker from "expo-image-picker"; |
|
import * as FileSystem from "expo-file-system"; |
|
import Toast from "react-native-toast-message"; |
|
import { |
|
productApi, |
|
ProductDetailParams, |
|
Similars, |
|
SkuAttribute, |
|
ProductGroupList, |
|
similar, |
|
} from "../services/api/productApi"; |
|
import { useNavigation, useRoute } from "@react-navigation/native"; |
|
import { NativeStackNavigationProp } from "@react-navigation/native-stack"; |
|
import { RouteProp } from "@react-navigation/native"; |
|
import BackIcon from "../components/BackIcon"; |
|
import CameraIcon from "../components/CameraIcon"; |
|
import ProductCard from "./ProductCard"; |
|
import useProductCartStore from "../store/productCart"; |
|
type ProductDetailRouteParams = { |
|
offer_id: string; |
|
searchKeyword?: string; |
|
price: number; |
|
}; |
|
export const ProductDetailScreen = () => { |
|
const { t } = useTranslation(); |
|
const { logViewProduct } = useBurialPointStore(); |
|
const { product, setProduct, groupList, setGroupList } = |
|
useProductCartStore(); |
|
const userStore = useUserStore(); |
|
const { width } = useWindowDimensions(); // 移动到组件内部 |
|
const navigation = useNavigation<NativeStackNavigationProp<any>>(); |
|
const route = |
|
useRoute<RouteProp<Record<string, ProductDetailRouteParams>, string>>(); |
|
const [activeIndex, setActiveIndex] = useState(0); |
|
const screenWidth = Dimensions.get("window").width; |
|
const [expandedGroups, setExpandedGroups] = useState<{ |
|
[key: string]: boolean; |
|
}>({}); |
|
const [isHeartRed, setIsHeartRed] = useState(false); |
|
const [isLoading, setIsLoading] = useState(true); |
|
const [similars, setSimilars] = useState<Similars>(); |
|
const [isSimilarsFlag, setIsSimilarsFlag] = useState(false); |
|
const [imageUrls, setImageUrls] = useState<any[]>([]); |
|
const [imageHeights, setImageHeights] = useState<{ [key: string]: number }>( |
|
{} |
|
); |
|
const [priceSelectedSku, setPriceSelectedSku] = useState<any>(); |
|
const [showBottomSheet, setShowBottomSheet] = useState(false); |
|
const [showImagePickerModal, setShowImagePickerModal] = useState(false); |
|
const [galleryUsed, setGalleryUsed] = useState(false); |
|
const groupData = ( |
|
res: ProductDetailParams, |
|
priceSelectedSku: SkuAttribute[] |
|
) => { |
|
let result = {} as any; |
|
// 遍历数据 |
|
res.skus.forEach((item) => { |
|
item.attributes.forEach((attribute) => { |
|
const { attribute_name_trans, value } = attribute; |
|
// 如果结果对象中没有对应的属性名,则创建一个空数组 |
|
if (!result[attribute_name_trans]) { |
|
result[attribute_name_trans] = []; |
|
} |
|
// 如果当前属性的值(value)已经存在于该组内,跳过 |
|
if ( |
|
!result[attribute_name_trans].some( |
|
(existingAttribute: any) => existingAttribute.value === value |
|
) |
|
) { |
|
result[attribute_name_trans].push(attribute); |
|
} |
|
}); |
|
}); |
|
const list: ProductGroupList[] = []; |
|
// Iterate over each attribute and transform the data |
|
for (const [attributeName, attributes] of Object.entries(result)) { |
|
const withImage: any[] = []; |
|
const withoutImage: any[] = []; |
|
// @ts-ignore |
|
attributes.forEach((attribute) => { |
|
attribute.has_color = false; |
|
// Check if sku_image_url is not null or undefined |
|
const hasImage = |
|
attribute.sku_image_url !== null && |
|
attribute.sku_image_url !== undefined; |
|
// Push the attribute to the appropriate array |
|
if (hasImage) { |
|
withImage.push(attribute); |
|
} else { |
|
withoutImage.push(attribute); |
|
} |
|
}); |
|
// Add has_image to the list item |
|
list.push({ |
|
attribute_name: attributeName, |
|
attribute_name_trans: attributeName, |
|
attribute_name_trans_ar: attributeName, |
|
attribute_name_trans_en: attributeName, |
|
has_image: withImage.length > 0, |
|
attributes: [...withImage, ...withoutImage], |
|
}); |
|
} |
|
if (!priceSelectedSku) { |
|
list.forEach((item) => { |
|
item.attributes[0].has_color = true; |
|
}); |
|
return list; |
|
} |
|
if (priceSelectedSku.length >= 1) { |
|
priceSelectedSku.forEach((item) => { |
|
list.forEach((item1) => { |
|
item1.attributes.forEach((attribute) => { |
|
if (attribute.value === item.value) { |
|
attribute.has_color = true; |
|
} |
|
}); |
|
}); |
|
}); |
|
return list; |
|
} |
|
return list; |
|
}; |
|
// 处理展开/收起 |
|
const toggleExpand = (attributeName: string) => { |
|
setExpandedGroups((prev) => ({ |
|
...prev, |
|
[attributeName]: !prev[attributeName], |
|
})); |
|
}; |
|
// 获取要显示的属性 |
|
const getDisplayAttributes = (attributes: any[], attributeName: string) => { |
|
if (expandedGroups[attributeName]) { |
|
return attributes; |
|
} |
|
return attributes.slice(0, 6); |
|
}; |
|
// 处理尺码选择 |
|
const handleSizeSelect = (size: string, index: number) => { |
|
setShowBottomSheet(true); |
|
const newGroupList = [...groupList]; |
|
const attributeIndex = newGroupList[index]?.attributes.findIndex( |
|
(item) => item.value === size |
|
); |
|
if (attributeIndex !== -1) { |
|
newGroupList[index].attributes = newGroupList[index].attributes.map( |
|
(item, i) => { |
|
if (i === attributeIndex) { |
|
return { ...item, has_color: true }; |
|
} |
|
return { ...item, has_color: false }; |
|
} |
|
); |
|
setGroupList(newGroupList); |
|
} |
|
const selectedSku: SkuAttribute[] = []; |
|
groupList.forEach((item) => { |
|
item.attributes.forEach((attribute) => { |
|
if (attribute.has_color) { |
|
selectedSku.push(attribute); |
|
} |
|
}); |
|
}); |
|
let price = 0; |
|
let original_price = 0; |
|
product?.skus.forEach((item) => { |
|
const values1 = item.attributes.map((item) => item.value).sort(); |
|
const values2 = selectedSku.map((item) => item.value).sort(); |
|
if (values1.every((val, index) => val === values2[index])) { |
|
if (item.offer_price) { |
|
price = item.offer_price; |
|
original_price = item.original_price; |
|
} else { |
|
price = |
|
product.sale_info.price_range_list[ |
|
product.sale_info.price_range_list.length - 1 |
|
].price; |
|
original_price = |
|
product.sale_info.price_range_list[ |
|
product.sale_info.price_range_list.length - 1 |
|
].original_price; |
|
} |
|
} |
|
}); |
|
if (product) { |
|
setProduct({ |
|
...product, |
|
price: price === 0 ? t("no_stock") : price, |
|
}); |
|
} |
|
}; |
|
// 处理颜色选择 |
|
const handleColorSelect = (colorId: string, index: number) => { |
|
setShowBottomSheet(true); |
|
const newGroupList = [...groupList]; |
|
const attributeIndex = newGroupList[index]?.attributes.findIndex( |
|
(item) => item.value === colorId |
|
); |
|
if (attributeIndex !== -1) { |
|
newGroupList[index].attributes = newGroupList[index].attributes.map( |
|
(item, i) => { |
|
if (i === attributeIndex) { |
|
return { ...item, has_color: true }; |
|
} |
|
return { ...item, has_color: false }; |
|
} |
|
); |
|
setGroupList(newGroupList); |
|
} |
|
const selectedSku: SkuAttribute[] = []; |
|
groupList.forEach((item) => { |
|
item.attributes.forEach((attribute) => { |
|
if (attribute.has_color) { |
|
selectedSku.push(attribute); |
|
} |
|
}); |
|
}); |
|
let price = 0; |
|
product?.skus.forEach((item) => { |
|
const values1 = item.attributes.map((item) => item.value).sort(); |
|
const values2 = selectedSku.map((item) => item.value).sort(); |
|
if (values1.every((val, index) => val === values2[index])) { |
|
if (item.offer_price) { |
|
price = item.offer_price; |
|
} else { |
|
price = |
|
product?.sale_info?.price_range_list[ |
|
product?.sale_info?.price_range_list?.length - 1 |
|
]?.price; |
|
} |
|
} |
|
}); |
|
if (product) { |
|
setProduct({ |
|
...product, |
|
price: price === 0 ? t("no_stock") : price, |
|
}); |
|
} |
|
}; |
|
const getProductDetail = async () => { |
|
if (!route.params?.offer_id) return; |
|
setIsLoading(true); |
|
try { |
|
const res = await productApi.getProductDetail( |
|
route.params.offer_id, |
|
userStore.user?.user_id |
|
); |
|
if (res.skus != null) { |
|
const priceSelectedSku = res.skus.find( |
|
(item) => item.offer_price === route.params.price |
|
); |
|
if (priceSelectedSku) { |
|
res.price = priceSelectedSku.offer_price; |
|
res.original_price = priceSelectedSku.original_price; |
|
} else { |
|
res.price = |
|
res?.sale_info?.price_range_list[ |
|
res?.sale_info?.price_range_list?.length - 1 |
|
]?.price; |
|
res.original_price = |
|
res?.sale_info?.price_range_list[ |
|
res?.sale_info?.price_range_list?.length - 1 |
|
]?.original_price; |
|
} |
|
} else { |
|
res.price = route.params.price; |
|
} |
|
if (res.skus != null) { |
|
const priceSelectedSku = res.skus.find( |
|
(item) => item.offer_price === route.params.price |
|
); |
|
if (priceSelectedSku) { |
|
setPriceSelectedSku({ |
|
price: route.params.price, |
|
}); |
|
} |
|
} |
|
setPriceSelectedSku(priceSelectedSku); |
|
setProduct(res); |
|
let list: ProductGroupList[] = []; |
|
if (res.skus != null) { |
|
list = groupData(res, priceSelectedSku?.attributes as SkuAttribute[]); |
|
} else { |
|
list = []; |
|
} |
|
const imageUrls = []; |
|
const regex = /<img[^>]+src="([^"]+)"/g; |
|
let match; |
|
while ((match = regex.exec(res.description)) !== null) { |
|
imageUrls.push(match[1]); // match[1] 是 src 属性的值 |
|
} |
|
// 只保留前 5 张图片(如果超过 5 张) |
|
const limitedImageUrls = |
|
imageUrls.length > 5 ? imageUrls.slice(0, 5) : imageUrls; |
|
setImageUrls(limitedImageUrls); |
|
setGroupList(list); |
|
|
|
const previousScreen = |
|
navigation.getState().routes[navigation.getState().index - 1]; |
|
const data = { |
|
offer_id: res.offer_id, |
|
category_id: res.category_id, |
|
price: res.price, |
|
sku_id: priceSelectedSku?.sku_id, |
|
currency: userStore.user?.currency, |
|
product_name: res.subject, |
|
product_img: res.product_image_urls[0], |
|
timestamp: new Date().toISOString(), |
|
}; |
|
logViewProduct(data, previousScreen?.name as string); |
|
console.log(getBurialPointData()); |
|
} catch (error) { |
|
console.error("Error fetching product details:", error); |
|
} finally { |
|
setIsLoading(false); |
|
} |
|
}; |
|
const getSimilars = () => { |
|
productApi |
|
.getSimilarProducts(route.params.offer_id, userStore.user?.user_id) |
|
.then((res) => { |
|
setSimilars(res); |
|
setIsSimilarsFlag(true); |
|
}); |
|
}; |
|
useEffect(() => { |
|
getProductDetail(); |
|
getSimilars(); |
|
}, []); |
|
useEffect(() => { |
|
if (Platform.OS !== "web") { |
|
const backHandler = BackHandler.addEventListener( |
|
"hardwareBackPress", |
|
() => { |
|
if (showBottomSheet) { |
|
setShowBottomSheet(false); |
|
return true; |
|
} |
|
return false; |
|
} |
|
); |
|
return () => backHandler.remove(); |
|
} |
|
}, [showBottomSheet]); |
|
const handleImageLoad = (src: string, event: any) => { |
|
// ExpoImage的onLoad事件直接返回尺寸信息 |
|
const { width: imageWidth, height: imageHeight } = event; |
|
const aspectRatio = imageHeight / imageWidth; |
|
const calculatedHeight = width * aspectRatio; |
|
setImageHeights((prev) => ({ |
|
...prev, |
|
[src]: calculatedHeight, |
|
})); |
|
}; |
|
const handleSearchPress = useCallback(() => { |
|
navigation.navigate("Search"); |
|
}, [navigation]); |
|
|
|
const handleCameraPress = useCallback(() => { |
|
setShowImagePickerModal(true); |
|
}, []); |
|
const handleProductPress = useCallback( |
|
(item: similar) => { |
|
InteractionManager.runAfterInteractions(() => { |
|
navigation.push("ProductDetail", { |
|
offer_id: item.offer_id, |
|
price: item.min_price, |
|
}); |
|
}); |
|
}, |
|
[navigation] |
|
); |
|
// Add this function to render skeleton UI |
|
const renderSkeletonItems = () => { |
|
// Create an array of 5 skeleton items |
|
return Array(5) |
|
.fill(0) |
|
.map((_, index) => ( |
|
<View style={styles.productCard} key={`skeleton-${index}`}> |
|
<View style={[styles.cardContainerWithPrice, styles.skeletonBox]} /> |
|
<View style={styles.priceContainerFlex}> |
|
<View style={[styles.skeletonText, { width: 50 }]} /> |
|
<View style={[styles.skeletonText, { width: 30, marginLeft: 5 }]} /> |
|
</View> |
|
</View> |
|
)); |
|
}; |
|
// 清理expo-image-picker临时文件 |
|
const cleanupImagePickerCache = async () => { |
|
try { |
|
// Skip cache cleanup on web platform |
|
if (Platform.OS === "web") { |
|
console.log("Cache cleanup skipped on web platform"); |
|
setGalleryUsed(false); |
|
return; |
|
} |
|
|
|
// 相册选择后清理临时缓存 |
|
const cacheDir = `${FileSystem.cacheDirectory}ImagePicker`; |
|
await FileSystem.deleteAsync(cacheDir, { idempotent: true }); |
|
console.log("已清理ImagePicker缓存"); |
|
// 立即重置状态,无需用户干预 |
|
setGalleryUsed(false); |
|
} catch (error) { |
|
console.log("清理缓存错误", error); |
|
// Even if cleanup fails, reset the state |
|
setGalleryUsed(false); |
|
} |
|
}; |
|
// 处理从相册选择 |
|
const handleChooseFromGallery = useCallback(async () => { |
|
console.log("handleChooseFromGallery"); |
|
setShowImagePickerModal(false); |
|
// 等待模态窗关闭后再执行 |
|
setTimeout(async () => { |
|
try { |
|
// 请求相册权限 |
|
const permissionResult = |
|
await ImagePicker.requestMediaLibraryPermissionsAsync(); |
|
if (permissionResult.status !== "granted") { |
|
console.log("相册权限被拒绝"); |
|
return; |
|
} |
|
// 打开相册 |
|
const result = await ImagePicker.launchImageLibraryAsync({ |
|
mediaTypes: ImagePicker.MediaTypeOptions.Images, |
|
allowsEditing: true, |
|
aspect: [4, 3], |
|
quality: 1, |
|
}); |
|
if (!result.canceled && result.assets && result.assets.length > 0) { |
|
console.log("相册选择成功:", result.assets[0].uri); |
|
await cleanupImagePickerCache(); |
|
navigation.navigate("ImageSearchResultScreen", { |
|
image: result.assets[0].uri, |
|
type: 1, |
|
}); |
|
} |
|
} catch (error: any) { |
|
console.error("相册错误:", error); |
|
// 出错时也清理缓存 |
|
await cleanupImagePickerCache(); |
|
} |
|
}, 500); |
|
}, [navigation, userStore.user]); |
|
// 处理相机拍照 |
|
const handleTakePhoto = useCallback(async () => { |
|
console.log("handleTakePhoto"); |
|
setShowImagePickerModal(false); |
|
// 等待模态窗关闭后再执行 |
|
setTimeout(async () => { |
|
try { |
|
const permissionResult = |
|
await ImagePicker.requestCameraPermissionsAsync(); |
|
if (permissionResult.status !== "granted") { |
|
console.log("相机权限被拒绝"); |
|
return; |
|
} |
|
const result = await ImagePicker.launchCameraAsync({ |
|
mediaTypes: ImagePicker.MediaTypeOptions.Images, |
|
allowsEditing: true, |
|
aspect: [4, 3], |
|
quality: 1, |
|
}); |
|
if (!result.canceled && result.assets && result.assets.length > 0) { |
|
console.log("拍照成功:", result.assets[0].uri); |
|
// 使用后清理缓存 |
|
await cleanupImagePickerCache(); |
|
navigation.navigate("ImageSearchResultScreen", { |
|
image: result.assets[0].uri, |
|
type: 1, |
|
}); |
|
} |
|
} catch (error: any) { |
|
console.error("相机错误:", error); |
|
// 出错时也清理缓存 |
|
await cleanupImagePickerCache(); |
|
} |
|
}, 500); |
|
}, [navigation, userStore.user]); |
|
// 重置应用状态函数 |
|
const resetAppState = useCallback(() => { |
|
// 重置标记 |
|
setGalleryUsed(false); |
|
// 清理缓存 |
|
cleanupImagePickerCache(); |
|
// 提示用户 |
|
Alert.alert("已重置", "现在您可以使用相机功能了"); |
|
}, []); |
|
return ( |
|
<SafeAreaView style={styles.safeArea}> |
|
<StatusBar barStyle="dark-content" backgroundColor="#fff" /> |
|
<View style={styles.safeAreaContent}> |
|
<View style={styles.container}> |
|
{isLoading ? ( |
|
<View style={styles.loadingContainer}> |
|
<ActivityIndicator size="large" color="#FF5100" /> |
|
<Text style={styles.loadingText}>Loading product details...</Text> |
|
</View> |
|
) : ( |
|
<> |
|
<View style={styles.headerBox}> |
|
<TouchableOpacity |
|
style={styles.backIcon} |
|
onPress={() => navigation.goBack()} |
|
> |
|
<BackIcon size={fontSize(20)} /> |
|
</TouchableOpacity> |
|
|
|
<TouchableOpacity |
|
style={styles.search} |
|
onPress={handleSearchPress} |
|
activeOpacity={0.7} |
|
> |
|
<View style={{ width: "100%", alignItems: "flex-start" }}> |
|
<Text style={styles.searchText}>{t("search")}</Text> |
|
</View> |
|
</TouchableOpacity> |
|
|
|
<TouchableOpacity |
|
style={styles.searchIcon} |
|
onPress={() => { |
|
navigation.navigate("MainTabs", { screen: "Cart" }); |
|
}} |
|
> |
|
<ShoppingCartIcon size={fontSize(20)} /> |
|
<ShareIcon size={fontSize(20)} /> |
|
</TouchableOpacity> |
|
</View> |
|
<ScrollView |
|
style={styles.scrollView} |
|
contentContainerStyle={styles.scrollViewContent} |
|
> |
|
<View style={styles.productDetailsContainer3}> |
|
<View style={styles.centerColumnWithPagination}> |
|
<View style={{ position: "relative" }}> |
|
<Carousel |
|
loop |
|
width={screenWidth} |
|
data={product?.product_image_urls as string[]} |
|
height={widthUtils(430, 430).height} |
|
onSnapToItem={(index) => setActiveIndex(index)} |
|
modeConfig={{ |
|
parallaxScrollingScale: 0.9, |
|
parallaxScrollingOffset: 50, |
|
}} |
|
renderItem={({ item }) => ( |
|
<View |
|
style={{ |
|
flex: 1, |
|
justifyContent: "center", |
|
alignItems: "center", |
|
backgroundColor: "#f2f2f2", |
|
borderRadius: 10, |
|
}} |
|
> |
|
<Image |
|
source={{ uri: item }} |
|
style={{ width: "100%", height: "100%" }} |
|
/> |
|
</View> |
|
)} |
|
/> |
|
<View |
|
style={{ |
|
position: "absolute", |
|
top: 20, |
|
right: 20, |
|
width: 40, |
|
height: 40, |
|
backgroundColor: "#efefef", |
|
borderRadius: 20, |
|
justifyContent: "center", |
|
alignItems: "center", |
|
}} |
|
> |
|
<TouchableOpacity |
|
onPress={() => { |
|
setProduct({ |
|
...product, |
|
is_favorited: !product.is_favorited, |
|
}); |
|
productApi.collectProduct(route.params.offer_id); |
|
}} |
|
> |
|
{product.is_favorited ? ( |
|
<HeartRedIcon size={20} color="red" /> |
|
) : ( |
|
<HeartIcon size={20} color="#373737" /> |
|
)} |
|
</TouchableOpacity> |
|
</View> |
|
{/* 底部指示灯 - 固定在右下角 */} |
|
<View |
|
style={{ |
|
position: "absolute", |
|
bottom: 20, |
|
right: 20, |
|
backgroundColor: "gray", // 可选,看得清楚 |
|
borderRadius: 13, |
|
justifyContent: "center", |
|
alignItems: "center", |
|
}} |
|
> |
|
<Text style={styles.activeIndexText}> |
|
{activeIndex + 1}/ |
|
{product?.product_image_urls?.length} |
|
</Text> |
|
</View> |
|
</View> |
|
</View> |
|
<View style={styles.productDetailsContainer2}> |
|
<View style={styles.nightLampProductCard}> |
|
<Text style={styles.creativeHeading}> |
|
{getSubjectTransLanguage(product)} |
|
</Text> |
|
<View style={styles.priceBox}> |
|
<Text style={styles.priceLabel}> |
|
{product?.original_price} |
|
{userStore.user?.currency} |
|
</Text> |
|
</View> |
|
<View style={styles.productInfoContainer1}> |
|
<View style={styles.productInfoContainer}> |
|
<View style={styles.salesInfoContainer}> |
|
<Text style={styles.highlightedText}> |
|
{product?.price} |
|
</Text> |
|
<Text style={styles.orangeHighlightedText}> |
|
{userStore.user?.currency || "FCFA"} |
|
</Text> |
|
</View> |
|
<Text style={styles.salesCountLabel}> |
|
{product?.sold_out} {t("sales")} |
|
</Text> |
|
</View> |
|
{userStore.user?.vip_level > 0 && ( |
|
<> |
|
<View style={styles.discountInfoContainer}> |
|
<Text style={styles.emphasizedTextWidget}> |
|
-5% |
|
</Text> |
|
</View> |
|
<View style={styles.priceInfoVip}> |
|
<ImageBackground |
|
source={require("../../assets/img/vip1.png")} |
|
style={styles.priceInfoVipImg} |
|
> |
|
<Text style={styles.vipStatusNumeric}> |
|
VIP {userStore.user?.vip_level} |
|
</Text> |
|
</ImageBackground> |
|
</View> |
|
</> |
|
)} |
|
</View> |
|
</View> |
|
<View style={styles.productDetailsContainer}> |
|
<View style={styles.productDetailsContainer1}> |
|
<View style={styles.blackThemeContainer}> |
|
{groupList.map((item, index) => |
|
item.has_image ? ( |
|
<View key={item.attribute_name_trans}> |
|
<Text style={styles.uniqueTextBlock}> |
|
{item.attribute_name_trans} :{" "} |
|
{ |
|
// getSkuTransLanguage() |
|
item.attributes.find( |
|
(item) => item.has_color |
|
)?.value |
|
} |
|
</Text> |
|
<View style={styles.horizontalFlexContainer}> |
|
{getDisplayAttributes( |
|
item.attributes, |
|
item.attribute_name_trans |
|
).map((attribute) => ( |
|
<TouchableOpacity |
|
key={attribute.value} |
|
onPress={() => |
|
handleColorSelect( |
|
attribute.value, |
|
index |
|
) |
|
} |
|
style={[ |
|
styles.colorImageContainer, |
|
attribute.has_color && |
|
styles.selectedColorImageContainer, |
|
]} |
|
> |
|
<Image |
|
source={{ |
|
uri: attribute.sku_image_url, |
|
}} |
|
style={styles.imageContainer} |
|
/> |
|
</TouchableOpacity> |
|
))} |
|
{!expandedGroups[item.attribute_name_trans] && |
|
item.attributes.length > 6 && ( |
|
<TouchableOpacity |
|
style={styles.expandButton} |
|
onPress={() => |
|
toggleExpand(item.attribute_name_trans) |
|
} |
|
> |
|
<Text style={styles.expandButtonText}> |
|
+{item.attributes.length - 6} |
|
</Text> |
|
</TouchableOpacity> |
|
)} |
|
{expandedGroups[item.attribute_name_trans] && ( |
|
<TouchableOpacity |
|
style={styles.expandButton} |
|
onPress={() => |
|
toggleExpand(item.attribute_name_trans) |
|
} |
|
> |
|
<Text style={styles.expandButtonText}> |
|
收起 |
|
</Text> |
|
</TouchableOpacity> |
|
)} |
|
</View> |
|
{groupList.length > 1 && index === 0 && ( |
|
<TouchableOpacity |
|
style={styles.svgContainer6} |
|
onPress={() => setShowBottomSheet(true)} |
|
> |
|
<View style={styles.svgContainer6}> |
|
<DiagonalArrowIcon size={fontSize(18)} /> |
|
</View> |
|
</TouchableOpacity> |
|
)} |
|
{groupList.length === 1 && index === 0 && ( |
|
<TouchableOpacity |
|
style={styles.svgContainer6} |
|
onPress={() => setShowBottomSheet(true)} |
|
> |
|
<View style={styles.svgContainer6}> |
|
<DiagonalArrowIcon size={fontSize(18)} /> |
|
</View> |
|
</TouchableOpacity> |
|
)} |
|
</View> |
|
) : ( |
|
<View key={item.attribute_name_trans}> |
|
<Text style={styles.uniqueTextBlock}> |
|
{item.attribute_name_trans} |
|
</Text> |
|
<View style={styles.horizontalFlexContainer}> |
|
{getDisplayAttributes( |
|
item.attributes, |
|
item.attribute_name_trans |
|
).map((attribute) => ( |
|
<TouchableOpacity |
|
key={attribute.value} |
|
onPress={() => |
|
handleSizeSelect(attribute.value, index) |
|
} |
|
style={[ |
|
styles.sizeButton, |
|
attribute.has_color && |
|
styles.selectedSizeButton, |
|
]} |
|
> |
|
<Text |
|
style={[ |
|
styles.sizeButtonText, |
|
attribute.has_color && |
|
styles.selectedSizeText, |
|
]} |
|
> |
|
{attribute.value} |
|
</Text> |
|
</TouchableOpacity> |
|
))} |
|
{!expandedGroups[item.attribute_name_trans] && |
|
item.attributes.length > 6 && ( |
|
<TouchableOpacity |
|
style={styles.expandButton} |
|
onPress={() => |
|
toggleExpand(item.attribute_name_trans) |
|
} |
|
> |
|
<Text style={styles.expandButtonText}> |
|
更多 |
|
</Text> |
|
</TouchableOpacity> |
|
)} |
|
{expandedGroups[item.attribute_name_trans] && ( |
|
<TouchableOpacity |
|
style={styles.expandButton} |
|
onPress={() => |
|
toggleExpand(item.attribute_name_trans) |
|
} |
|
> |
|
<Text style={styles.expandButtonText}> |
|
收起 |
|
</Text> |
|
</TouchableOpacity> |
|
)} |
|
</View> |
|
{groupList.length === 1 && ( |
|
<TouchableOpacity |
|
style={styles.svgContainer6} |
|
onPress={() => setShowBottomSheet(true)} |
|
> |
|
<View style={styles.svgContainer6}> |
|
<DiagonalArrowIcon size={fontSize(18)} /> |
|
</View> |
|
</TouchableOpacity> |
|
)} |
|
{groupList.length === 2 && index === 0 && ( |
|
<TouchableOpacity |
|
style={styles.svgContainer6} |
|
onPress={() => setShowBottomSheet(true)} |
|
> |
|
<View style={styles.svgContainer6}> |
|
<DiagonalArrowIcon size={fontSize(18)} /> |
|
</View> |
|
</TouchableOpacity> |
|
)} |
|
</View> |
|
) |
|
)} |
|
</View> |
|
</View> |
|
</View> |
|
<View style={styles.storeRecommendationsContainer}> |
|
<View style={styles.storeInfoContainer}> |
|
<Text style={styles.storeSectionTitle}> |
|
More from this store |
|
</Text> |
|
{/* <Text style={styles.storeMoreLink}>View All</Text> */} |
|
</View> |
|
<ScrollView |
|
horizontal |
|
showsHorizontalScrollIndicator={false} |
|
contentContainerStyle={styles.productGridContainer} |
|
> |
|
{isSimilarsFlag |
|
? similars?.map((item) => ( |
|
<TouchableOpacity |
|
style={styles.productCard} |
|
key={item.offer_id} |
|
onPress={() => handleProductPress(item)} |
|
> |
|
<View style={styles.cardContainerWithPrice}> |
|
<Image |
|
source={{ uri: item.product_image_urls[0] }} |
|
style={styles.imageContainerCompact} |
|
/> |
|
</View> |
|
<View style={styles.priceContainerFlex}> |
|
<Text style={styles.highlightedText1}> |
|
{item.max_price} |
|
</Text> |
|
<Text |
|
style={styles.highlightedTextWithBorder} |
|
> |
|
FCFA |
|
</Text> |
|
</View> |
|
</TouchableOpacity> |
|
)) |
|
: renderSkeletonItems()} |
|
</ScrollView> |
|
</View> |
|
<View style={{ width: "100%" }}> |
|
{imageUrls.map((src, index) => ( |
|
<View key={index} style={{ width: "100%" }}> |
|
<ExpoImage |
|
style={{ |
|
width: "100%", |
|
height: imageHeights[src] || 200, |
|
backgroundColor: "#f5f5f5", |
|
}} |
|
source={{ uri: src }} |
|
contentFit="contain" |
|
onLoad={(event) => handleImageLoad(src, event)} |
|
/> |
|
</View> |
|
))} |
|
</View> |
|
</View> |
|
</View> |
|
</ScrollView> |
|
<View style={styles.fixedBottomBar}> |
|
<TouchableOpacity style={styles.chatNowButton}> |
|
<WhiteCircleIcon color="#fff" size={fontSize(20)} /> |
|
<Text style={styles.chatNowText}>chatNow</Text> |
|
</TouchableOpacity> |
|
<TouchableOpacity |
|
style={styles.addToCartButton} |
|
onPress={() => setShowBottomSheet(true)} |
|
> |
|
<ShoppingCartIcon color="#fff" size={fontSize(20)} /> |
|
<Text style={styles.addToCartText}>addToCart</Text> |
|
</TouchableOpacity> |
|
</View> |
|
{showBottomSheet && product && ( |
|
<View style={styles.bottomSheetOverlay}> |
|
<Animated.View style={[styles.bottomSheet]}> |
|
<ProductCard |
|
onClose={() => setShowBottomSheet(false)} |
|
product={product} |
|
groupList={groupList} |
|
></ProductCard> |
|
</Animated.View> |
|
</View> |
|
)} |
|
</> |
|
)} |
|
</View> |
|
</View> |
|
|
|
{/* Image Picker Modal */} |
|
<Modal |
|
visible={showImagePickerModal} |
|
animationType="slide" |
|
transparent={true} |
|
onRequestClose={() => setShowImagePickerModal(false)} |
|
> |
|
<TouchableOpacity |
|
style={styles.imagePickerOverlay} |
|
activeOpacity={1} |
|
onPress={() => setShowImagePickerModal(false)} |
|
> |
|
<View style={styles.imagePickerContent}> |
|
{!galleryUsed ? ( |
|
// 正常状态,显示相机选项 |
|
<TouchableOpacity |
|
style={styles.imagePickerOption} |
|
onPress={handleTakePhoto} |
|
> |
|
<CameraIcon size={24} color="#333" /> |
|
<Text style={styles.imagePickerText}>拍照</Text> |
|
</TouchableOpacity> |
|
) : ( |
|
// 已使用相册状态,显示重置选项 |
|
<TouchableOpacity |
|
style={styles.imagePickerOption} |
|
onPress={resetAppState} |
|
> |
|
<Text style={styles.imagePickerText}>重置相机功能</Text> |
|
</TouchableOpacity> |
|
)} |
|
<View style={styles.imagePickerDivider} /> |
|
<TouchableOpacity |
|
style={styles.imagePickerOption} |
|
onPress={handleChooseFromGallery} |
|
> |
|
<Text style={styles.imagePickerText}>从相册选择</Text> |
|
</TouchableOpacity> |
|
<TouchableOpacity |
|
style={styles.imagePickerCancelButton} |
|
onPress={() => setShowImagePickerModal(false)} |
|
> |
|
<Text style={styles.imagePickerCancelText}>取消</Text> |
|
</TouchableOpacity> |
|
</View> |
|
</TouchableOpacity> |
|
</Modal> |
|
</SafeAreaView> |
|
); |
|
}; |
|
const styles = StyleSheet.create({ |
|
safeArea: { |
|
flex: 1, |
|
backgroundColor: "#fff", |
|
}, |
|
safeAreaContent: { |
|
flex: 1, |
|
paddingTop: Platform.OS === "android" ? 0 : 0, |
|
}, |
|
container: { |
|
flex: 1, |
|
backgroundColor: "#fff", |
|
}, |
|
scrollView: { |
|
flex: 1, |
|
backgroundColor: "white", |
|
}, |
|
headerBox: { |
|
width: "100%", |
|
padding: 10, |
|
justifyContent: "space-between", |
|
flexDirection: "row", |
|
alignItems: "center", |
|
backgroundColor: "#fff", |
|
}, |
|
backIcon: { |
|
width: "5%", |
|
alignItems: "flex-end", |
|
}, |
|
search: { |
|
width: "70%", |
|
padding: 15, |
|
backgroundColor: "#f4f4f4", |
|
borderWidth: 1, |
|
borderColor: "#eeeeee", |
|
borderRadius: 25, |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "space-between", |
|
}, |
|
searchText: { |
|
fontSize: fontSize(16), |
|
color: "#747474", |
|
fontWeight: "600", |
|
}, |
|
searchIcon: { |
|
alignItems: "center", |
|
justifyContent: "space-between", |
|
flexDirection: "row", |
|
width: "15%", |
|
}, |
|
scrollViewContent: {}, |
|
productDetailsContainer3: { |
|
flexDirection: "column", |
|
alignItems: "stretch", |
|
justifyContent: "flex-start", |
|
width: "100%", |
|
backgroundColor: "white", |
|
}, |
|
timeCardContainer: { |
|
flexDirection: "column", |
|
alignItems: "stretch", |
|
justifyContent: "flex-start", |
|
paddingTop: 3, |
|
paddingBottom: 15, |
|
paddingLeft: 18, |
|
}, |
|
timeInfoContainer: { |
|
flexDirection: "row", |
|
gap: 8, |
|
alignItems: "center", |
|
justifyContent: "space-between", |
|
paddingLeft: 38, |
|
}, |
|
timeDisplay: { |
|
width: 42, |
|
fontWeight: "600", |
|
fontSize: fontSize(17), |
|
color: "black", |
|
textAlign: "center", |
|
}, |
|
timeDisplayContainer: { |
|
width: widthUtils(54, 154).width, |
|
height: widthUtils(54, 54).height, |
|
}, |
|
searchContainer1: { |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "space-between", |
|
marginTop: 2, |
|
width: "100%", |
|
}, |
|
backButtonContainer: { |
|
width: "10%", |
|
alignItems: "flex-start", |
|
}, |
|
searchContainer2: { |
|
width: "70%", |
|
flexDirection: "row", |
|
alignItems: "center", |
|
height: widthUtils(50, 50).height, |
|
paddingRight: 10, |
|
paddingLeft: 10, |
|
backgroundColor: "#f4f4f4", |
|
borderWidth: 1, |
|
borderColor: "#eeeeee", |
|
borderRadius: 25, |
|
marginRight: 10, |
|
}, |
|
iconsContainer: { |
|
width: "20%", |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "flex-start", |
|
}, |
|
svgContainer: { |
|
width: widthUtils(18, 18).width, |
|
height: widthUtils(18, 18).height, |
|
}, |
|
svgContainer1: { |
|
width: widthUtils(24, 24).width, |
|
height: widthUtils(24, 24).height, |
|
color: "#373737", |
|
justifyContent: "center", |
|
alignItems: "center", |
|
}, |
|
searchTitleTextStyle: { |
|
fontWeight: "600", |
|
fontSize: fontSize(16), |
|
color: "#747474", |
|
flex: 1, |
|
}, |
|
svgContainer2: { |
|
width: widthUtils(24, 24).width, |
|
height: widthUtils(24, 24).height, |
|
marginLeft: 11, |
|
color: "#373737", |
|
}, |
|
productDetailsContainer2: { |
|
backgroundColor: "#f4f4f4", |
|
}, |
|
centerColumnWithPagination: { |
|
flexDirection: "column", |
|
alignItems: "stretch", |
|
justifyContent: "center", |
|
width: "100%", |
|
backgroundColor: "#f4f4f4", |
|
}, |
|
centerContentWithPaginationButton: { |
|
flexDirection: "column", |
|
alignItems: "center", |
|
justifyContent: "center", |
|
}, |
|
sidebarContainer: { |
|
paddingLeft: 350, |
|
}, |
|
centerIconContainer: { |
|
flexDirection: "column", |
|
alignItems: "center", |
|
justifyContent: "center", |
|
width: widthUtils(40, 40).width, |
|
height: widthUtils(40, 40).height, |
|
backgroundColor: "#efefef", |
|
borderRadius: 25, |
|
}, |
|
centerBox1: { |
|
flexDirection: "column", |
|
alignItems: "center", |
|
justifyContent: "center", |
|
width: widthUtils(60, 60).width, |
|
height: widthUtils(60, 60).height, |
|
marginTop: 125, |
|
backgroundColor: "rgba(92, 92, 92, 0.6)", |
|
borderWidth: 1, |
|
borderColor: "white", |
|
borderRadius: 35, |
|
}, |
|
svgContainer3: { |
|
width: widthUtils(20, 20).width, |
|
height: widthUtils(20, 20).height, |
|
color: "#ffffff", |
|
}, |
|
darkButton: { |
|
alignSelf: "flex-end", |
|
width: widthUtils(26, 50).width, |
|
height: widthUtils(26, 50).height, |
|
minWidth: 50, |
|
marginTop: 147, |
|
fontWeight: "600", |
|
fontSize: fontSize(12), |
|
color: "white", |
|
backgroundColor: "rgba(44, 44, 44, 0.7)", |
|
borderRadius: 13, |
|
}, |
|
nightLampProductCard: { |
|
width: "100%", |
|
padding: 16, |
|
paddingLeft: 19, |
|
paddingBottom: 23, |
|
backgroundColor: "white", |
|
}, |
|
creativeHeading: { |
|
width: "100%", |
|
fontWeight: "600", |
|
fontSize: fontSize(18), |
|
lineHeight: 22, |
|
color: "black", |
|
textAlign: "left", |
|
}, |
|
productInfoContainer1: { |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "flex-start", |
|
}, |
|
productInfoContainer: { |
|
alignSelf: "flex-start", |
|
}, |
|
salesInfoContainer: { |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "flex-start", |
|
}, |
|
highlightedText: { |
|
fontWeight: "700", |
|
fontSize: fontSize(30), |
|
color: "#ff5100", |
|
}, |
|
orangeHighlightedText: { |
|
fontWeight: "700", |
|
fontSize: fontSize(14), |
|
marginLeft: 1.25, |
|
color: "#ff5100", |
|
lineHeight: 28, |
|
}, |
|
salesCountLabel: { |
|
marginTop: 6.75, |
|
fontWeight: "600", |
|
fontSize: fontSize(14), |
|
color: "#7c7c7c", |
|
}, |
|
priceBox: { |
|
marginTop: 15, |
|
marginBottom: 5, |
|
}, |
|
priceLabel: { |
|
fontWeight: "600", |
|
fontSize: fontSize(12), |
|
color: "#9a9a9a", |
|
textDecorationLine: "line-through", |
|
}, |
|
priceContainer: { |
|
width: "100%", |
|
marginTop: -4.75, |
|
borderTopWidth: 1, |
|
borderTopColor: "#9a9a9a", |
|
}, |
|
discountInfoContainer: { |
|
flexDirection: "column", |
|
alignItems: "center", |
|
justifyContent: "center", |
|
marginLeft: 10, |
|
}, |
|
emphasizedTextWidget: { |
|
fontStyle: "italic", |
|
fontWeight: "900", |
|
fontSize: fontSize(11), |
|
color: "#4e2000", |
|
backgroundColor: "#FFE4D6", |
|
padding: 3, |
|
borderRadius: 3, |
|
}, |
|
vipStatusContainer: { |
|
marginLeft: 10, |
|
}, |
|
vipBadgeContainer: { |
|
flexDirection: "column", |
|
alignItems: "stretch", |
|
justifyContent: "center", |
|
paddingHorizontal: 10, |
|
paddingVertical: 3, |
|
backgroundColor: "#3b3b3b", |
|
borderRadius: 5, |
|
borderBottomLeftRadius: 0, |
|
}, |
|
vipStatusNumeric: { |
|
fontStyle: "italic", |
|
fontWeight: "900", |
|
fontSize: fontSize(18), |
|
color: "#f1c355", |
|
textAlign: "center", |
|
marginLeft: 2, |
|
}, |
|
emphasizedTextVip: { |
|
fontStyle: "italic", |
|
fontWeight: "900", |
|
fontSize: fontSize(14), |
|
}, |
|
emphasizedText: { |
|
fontStyle: "italic", |
|
fontWeight: "900", |
|
fontSize: fontSize(14), |
|
letterSpacing: -2, |
|
}, |
|
productDetailsContainer: { |
|
flexDirection: "column", |
|
alignItems: "stretch", |
|
justifyContent: "flex-start", |
|
width: "100%", |
|
padding: 10, |
|
paddingLeft: 19, |
|
paddingBottom: 13, |
|
marginTop: 8, |
|
backgroundColor: "white", |
|
}, |
|
productDetailsContainer1: { |
|
flexDirection: "column", |
|
alignItems: "stretch", |
|
justifyContent: "flex-start", |
|
}, |
|
blackThemeContainer: {}, |
|
uniqueTextBlock: { |
|
fontWeight: "600", |
|
fontSize: fontSize(16), |
|
lineHeight: 20, |
|
color: "black", |
|
}, |
|
horizontalFlexContainer: { |
|
width: "100%", |
|
flexDirection: "row", |
|
flexWrap: "wrap", |
|
gap: 10, |
|
alignItems: "center", |
|
justifyContent: "flex-start", |
|
marginTop: 8, |
|
}, |
|
imageContainer: { |
|
width: widthUtils(40, 40).width, |
|
height: widthUtils(40, 40).height, |
|
borderRadius: 5, |
|
}, |
|
centerBox: { |
|
flexDirection: "column", |
|
alignItems: "stretch", |
|
justifyContent: "center", |
|
width: widthUtils(40, 40).width, |
|
backgroundColor: "#e0e0e0", |
|
borderRadius: 5, |
|
}, |
|
imageContainerStyles: { |
|
height: widthUtils(40, 40).height, |
|
}, |
|
svgContainer6: { |
|
alignSelf: "flex-end", |
|
width: widthUtils(18, 18).width, |
|
height: widthUtils(18, 18).height, |
|
}, |
|
sizeSelector: { |
|
marginTop: 0, |
|
}, |
|
numericHighlightedTextContainer: { |
|
alignItems: "center", |
|
justifyContent: "center", |
|
height: widthUtils(30, 30).height, |
|
paddingHorizontal: 11, |
|
fontWeight: "400", |
|
fontSize: fontSize(14), |
|
color: "#ff5100", |
|
backgroundColor: "#fff5f0", |
|
borderWidth: 1, |
|
borderColor: "#ff5100", |
|
borderRadius: 5, |
|
}, |
|
numberBadge: { |
|
alignItems: "center", |
|
justifyContent: "center", |
|
height: widthUtils(30, 40).height, |
|
paddingHorizontal: 11, |
|
fontWeight: "400", |
|
fontSize: fontSize(14), |
|
color: "#373737", |
|
backgroundColor: "#efefef", |
|
borderRadius: 5, |
|
lineHeight: widthUtils(40, 40).height, |
|
marginBottom: 10, |
|
}, |
|
sizeButton: { |
|
alignItems: "center", |
|
justifyContent: "center", |
|
height: widthUtils(30, 40).height, |
|
paddingHorizontal: 11, |
|
backgroundColor: "#efefef", |
|
borderRadius: 5, |
|
marginBottom: 10, |
|
}, |
|
priceInfoVip: { |
|
width: widthUtils(21, 63).width, |
|
height: widthUtils(21, 63).height, |
|
marginLeft: 10, |
|
}, |
|
priceInfoVipImg: { |
|
width: "100%", |
|
height: "100%", |
|
justifyContent: "center", |
|
alignItems: "center", |
|
}, |
|
sizeButtonText: { |
|
fontWeight: "400", |
|
fontSize: fontSize(14), |
|
color: "#373737", |
|
lineHeight: widthUtils(30, 40).height, |
|
}, |
|
selectedSizeButton: { |
|
backgroundColor: "#fff5f0", |
|
borderWidth: 1, |
|
borderColor: "#ff5217", |
|
}, |
|
selectedSizeText: { |
|
color: "#ff5217", |
|
fontWeight: "600", |
|
}, |
|
expandButton: { |
|
alignItems: "center", |
|
justifyContent: "center", |
|
height: widthUtils(38, 38).height, |
|
paddingHorizontal: 11, |
|
fontWeight: "600", |
|
fontSize: fontSize(14), |
|
color: "#ff5100", |
|
borderRadius: 5, |
|
lineHeight: widthUtils(40, 40).height, |
|
marginBottom: 10, |
|
backgroundColor: "#efefef", |
|
}, |
|
expandButtonText: { |
|
color: "#b7b7b7", |
|
fontWeight: "600", |
|
}, |
|
storeRecommendationsContainer: { |
|
width: "100%", |
|
padding: 10, |
|
paddingLeft: 19, |
|
paddingBottom: 19, |
|
marginTop: 8, |
|
backgroundColor: "white", |
|
}, |
|
storeInfoContainer: { |
|
flexDirection: "row", |
|
gap: 8, |
|
alignItems: "center", |
|
justifyContent: "space-between", |
|
width: "100%", |
|
}, |
|
storeSectionTitle: { |
|
fontWeight: "600", |
|
fontSize: fontSize(16), |
|
lineHeight: 20, |
|
color: "black", |
|
}, |
|
storeMoreLink: { |
|
fontWeight: "600", |
|
fontSize: fontSize(12), |
|
color: "#747474", |
|
}, |
|
productGridContainer: { |
|
flexDirection: "row", |
|
alignItems: "flex-start", |
|
justifyContent: "flex-start", |
|
marginTop: 12, |
|
paddingRight: 10, |
|
}, |
|
productCard: { |
|
width: widthUtils(115, 90).width, |
|
height: widthUtils(115, 90).height, |
|
marginRight: 10, |
|
}, |
|
cardContainerWithPrice: { |
|
flexDirection: "column", |
|
alignItems: "stretch", |
|
justifyContent: "center", |
|
width: "100%", |
|
backgroundColor: "#e0e0e0", |
|
borderRadius: 5, |
|
}, |
|
imageContainerCompact: { |
|
height: widthUtils(90, 90).height, |
|
width: widthUtils(90, 90).width, |
|
}, |
|
priceContainerFlex: { |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "flex-start", |
|
marginTop: 2, |
|
}, |
|
highlightedText1: { |
|
fontWeight: "700", |
|
fontSize: fontSize(16), |
|
lineHeight: 20, |
|
color: "#ff5100", |
|
}, |
|
highlightedTextWithBorder: { |
|
fontWeight: "700", |
|
fontSize: fontSize(10), |
|
marginLeft: 1.25, |
|
color: "#ff5100", |
|
}, |
|
productImageContainer: { |
|
width: "100%", |
|
height: widthUtils(90, 90).height, |
|
borderRadius: 5, |
|
}, |
|
orangeHighlightTextStyle: { |
|
fontWeight: "700", |
|
fontSize: fontSize(16), |
|
lineHeight: widthUtils(20, 20).height, |
|
marginTop: 2, |
|
color: "#ff5100", |
|
}, |
|
productDetailsContainer4: { |
|
flexDirection: "column", |
|
alignItems: "stretch", |
|
justifyContent: "flex-start", |
|
width: "100%", |
|
marginTop: 8, |
|
backgroundColor: "white", |
|
}, |
|
productDetailsContainer5: { |
|
padding: 10, |
|
paddingLeft: 19, |
|
paddingBottom: 183, |
|
}, |
|
productDetailsDescription: { |
|
width: "100%", |
|
marginTop: 8, |
|
fontWeight: "400", |
|
fontSize: fontSize(14), |
|
lineHeight: widthUtils(20, 20).height, |
|
color: "#373737", |
|
textAlign: "left", |
|
}, |
|
imageContainer1: { |
|
marginTop: -165, |
|
marginRight: 20, |
|
marginLeft: 20, |
|
}, |
|
imageContainerStyles1: { |
|
width: widthUtils(229, 390).width, |
|
height: widthUtils(229, 390).height, |
|
}, |
|
flexCenterButtons: { |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "center", |
|
height: widthUtils(64, 64).height, |
|
paddingRight: 20, |
|
paddingLeft: 20, |
|
marginTop: -64, |
|
backgroundColor: "white", |
|
}, |
|
gradientButton: { |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "center", |
|
gap: 4, |
|
width: widthUtils(50, 160).width, |
|
height: widthUtils(50, 160).height, |
|
minWidth: 160, |
|
fontWeight: "700", |
|
fontSize: fontSize(18), |
|
lineHeight: 22, |
|
color: "white", |
|
backgroundColor: |
|
"linear-gradient(90deg, rgba(0, 183, 68, 1) 0%, rgba(28, 207, 95, 1) 100%)", |
|
borderRadius: 30, |
|
}, |
|
svgContainer7: { |
|
width: widthUtils(24, 24).width, |
|
height: widthUtils(24, 24).height, |
|
color: "#ffffff", |
|
}, |
|
orangeGradientButton: { |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "center", |
|
gap: 7, |
|
width: widthUtils(50, 220).width, |
|
height: widthUtils(50, 220).height, |
|
minWidth: 220, |
|
marginLeft: 10, |
|
fontWeight: "700", |
|
fontSize: fontSize(18), |
|
lineHeight: 22, |
|
color: "white", |
|
backgroundColor: |
|
"linear-gradient(90deg, rgba(255, 128, 0, 1) 0%, rgba(255, 81, 0, 1) 100%)", |
|
borderRadius: 30, |
|
}, |
|
activeIndexText: { |
|
color: "white", |
|
fontSize: fontSize(12), |
|
width: widthUtils(26, 50).width, |
|
height: widthUtils(26, 50).height, |
|
textAlign: "center", |
|
lineHeight: widthUtils(26, 50).height + 2, |
|
}, |
|
colorImageContainer: { |
|
padding: 2, |
|
borderRadius: 5, |
|
}, |
|
selectedColorImageContainer: { |
|
backgroundColor: "#fff5f0", |
|
borderWidth: 1, |
|
borderColor: "#ff5217", |
|
}, |
|
fixedBottomBar: { |
|
position: "absolute", |
|
bottom: 10, |
|
left: 0, |
|
right: 0, |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "center", |
|
paddingHorizontal: 15, |
|
backgroundColor: "transparent", |
|
zIndex: 100, |
|
height: widthUtils(60, 60).height, |
|
}, |
|
chatNowButton: { |
|
width: "40%", |
|
height: widthUtils(50, 50).height, |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "center", |
|
paddingVertical: 0, |
|
borderRadius: 30, |
|
backgroundColor: "#4CAF50", |
|
marginRight: 10, |
|
elevation: 4, |
|
shadowColor: "#000", |
|
shadowOffset: { width: 0, height: 2 }, |
|
shadowOpacity: 0.2, |
|
shadowRadius: 3, |
|
}, |
|
chatNowText: { |
|
fontSize: fontSize(18), |
|
color: "#fff", |
|
fontWeight: "bold", |
|
marginLeft: 8, |
|
}, |
|
addToCartButton: { |
|
width: "60%", |
|
height: widthUtils(50, 50).height, |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "center", |
|
paddingVertical: 0, |
|
borderRadius: 30, |
|
backgroundColor: "#FF5722", |
|
marginLeft: 10, |
|
elevation: 4, |
|
shadowColor: "#000", |
|
shadowOffset: { width: 0, height: 2 }, |
|
shadowOpacity: 0.2, |
|
shadowRadius: 3, |
|
}, |
|
addToCartText: { |
|
fontSize: fontSize(18), |
|
color: "#fff", |
|
fontWeight: "bold", |
|
marginLeft: 8, |
|
}, |
|
modalContainer: { |
|
backgroundColor: "rgba(0, 0, 0, 0.5)", |
|
justifyContent: "flex-end", |
|
}, |
|
modalContent: { |
|
height: "90%", |
|
backgroundColor: "white", |
|
borderTopLeftRadius: 20, |
|
borderTopRightRadius: 20, |
|
padding: 20, |
|
}, |
|
closeButton: { |
|
alignSelf: "flex-end", |
|
padding: 10, |
|
}, |
|
closeButtonText: { |
|
fontSize: fontSize(16), |
|
color: "#333", |
|
}, |
|
bottomSheetOverlay: { |
|
position: "absolute", |
|
top: 0, |
|
left: 0, |
|
right: 0, |
|
bottom: 0, |
|
justifyContent: "flex-end", |
|
zIndex: 200, |
|
}, |
|
bottomSheet: { |
|
backgroundColor: "#fff", |
|
borderTopLeftRadius: 20, |
|
borderTopRightRadius: 20, |
|
height: "85%", |
|
zIndex: 1, |
|
}, |
|
loadingContainer: { |
|
flex: 1, |
|
justifyContent: "center", |
|
alignItems: "center", |
|
backgroundColor: "white", |
|
}, |
|
loadingText: { |
|
marginTop: 10, |
|
fontSize: fontSize(16), |
|
color: "#666", |
|
}, |
|
skeletonBox: { |
|
backgroundColor: "#e0e0e0", |
|
height: widthUtils(90, 90).height, |
|
width: widthUtils(90, 90).width, |
|
borderRadius: 5, |
|
}, |
|
skeletonText: { |
|
height: 16, |
|
backgroundColor: "#e0e0e0", |
|
borderRadius: 3, |
|
}, |
|
imagePickerOverlay: { |
|
flex: 1, |
|
backgroundColor: "rgba(0, 0, 0, 0.5)", |
|
justifyContent: "flex-end", |
|
}, |
|
imagePickerContent: { |
|
backgroundColor: "#fff", |
|
borderTopLeftRadius: 10, |
|
borderTopRightRadius: 10, |
|
paddingTop: 20, |
|
}, |
|
imagePickerOption: { |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "center", |
|
paddingVertical: 15, |
|
}, |
|
imagePickerText: { |
|
fontSize: fontSize(16), |
|
color: "#333", |
|
marginLeft: 10, |
|
}, |
|
imagePickerDivider: { |
|
height: 1, |
|
backgroundColor: "#eee", |
|
marginHorizontal: 20, |
|
}, |
|
imagePickerCancelButton: { |
|
alignItems: "center", |
|
paddingVertical: 15, |
|
borderTopWidth: 1, |
|
borderTopColor: "#eee", |
|
marginTop: 10, |
|
}, |
|
imagePickerCancelText: { |
|
fontSize: fontSize(16), |
|
color: "#333", |
|
}, |
|
});
|
|
|