|
|
|
import React, { useEffect, useCallback } from "react";
|
|
|
|
import {
|
|
|
|
View,
|
|
|
|
Text,
|
|
|
|
Image,
|
|
|
|
StyleSheet,
|
|
|
|
TouchableOpacity,
|
|
|
|
ScrollView,
|
|
|
|
Dimensions,
|
|
|
|
useWindowDimensions,
|
|
|
|
Animated,
|
|
|
|
BackHandler,
|
|
|
|
ActivityIndicator,
|
|
|
|
Alert,
|
|
|
|
InteractionManager,
|
|
|
|
Platform,
|
|
|
|
StatusBar,
|
|
|
|
SafeAreaView
|
|
|
|
} 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 { useState } from "react";
|
|
|
|
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 {
|
|
|
|
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 groupData = (
|
|
|
|
res: ProductDetailParams,
|
|
|
|
priceSelectedSku: SkuAttribute[]
|
|
|
|
) => {
|
|
|
|
let result = {} as any;
|
|
|
|
// 遍历数据
|
|
|
|
res.skus.forEach((item) => {
|
|
|
|
item.attributes.forEach((attribute) => {
|
|
|
|
const { attribute_name, value } = attribute;
|
|
|
|
// 如果结果对象中没有对应的属性名,则创建一个空数组
|
|
|
|
if (!result[attribute_name]) {
|
|
|
|
result[attribute_name] = [];
|
|
|
|
}
|
|
|
|
// 如果当前属性的值(value)已经存在于该组内,跳过
|
|
|
|
if (
|
|
|
|
!result[attribute_name].some(
|
|
|
|
(existingAttribute: any) => existingAttribute.value === value
|
|
|
|
)
|
|
|
|
) {
|
|
|
|
result[attribute_name].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,
|
|
|
|
has_image: withImage.length > 0, // If there are any items with images, set has_image to true
|
|
|
|
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) => {
|
|
|
|
const { width: imageWidth, height: imageHeight } = event.nativeEvent.source;
|
|
|
|
const aspectRatio = imageHeight / imageWidth;
|
|
|
|
const calculatedHeight = width * aspectRatio;
|
|
|
|
setImageHeights((prev) => ({
|
|
|
|
...prev,
|
|
|
|
[src]: calculatedHeight,
|
|
|
|
}));
|
|
|
|
};
|
|
|
|
const handleSearchPress = useCallback(() => {
|
|
|
|
InteractionManager.runAfterInteractions(() => {
|
|
|
|
navigation.navigate("Search");
|
|
|
|
});
|
|
|
|
}, [navigation]);
|
|
|
|
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>
|
|
|
|
));
|
|
|
|
};
|
|
|
|
|
|
|
|
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}>
|
|
|
|
<Text style={styles.searchText}>搜索</Text>
|
|
|
|
<CameraIcon size={fontSize(20)} />
|
|
|
|
</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={() => {
|
|
|
|
setIsHeartRed(!isHeartRed);
|
|
|
|
Alert.alert("收藏成功", "是否我的查看收藏", [
|
|
|
|
{
|
|
|
|
text: "取消",
|
|
|
|
onPress: () => console.log("取消 pressed"),
|
|
|
|
style: "cancel",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text: "确定",
|
|
|
|
onPress: () => console.log("确定 pressed"),
|
|
|
|
},
|
|
|
|
]);
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{isHeartRed ? (
|
|
|
|
<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}>
|
|
|
|
<Text style={styles.uniqueTextBlock}>
|
|
|
|
{item.attribute_name} :{" "}
|
|
|
|
{
|
|
|
|
item.attributes.find((item) => item.has_color)
|
|
|
|
?.value
|
|
|
|
}
|
|
|
|
</Text>
|
|
|
|
<View style={styles.horizontalFlexContainer}>
|
|
|
|
{getDisplayAttributes(
|
|
|
|
item.attributes,
|
|
|
|
item.attribute_name
|
|
|
|
).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] &&
|
|
|
|
item.attributes.length > 6 && (
|
|
|
|
<TouchableOpacity
|
|
|
|
style={styles.expandButton}
|
|
|
|
onPress={() =>
|
|
|
|
toggleExpand(item.attribute_name)
|
|
|
|
}
|
|
|
|
>
|
|
|
|
<Text style={styles.expandButtonText}>
|
|
|
|
+{item.attributes.length - 6}
|
|
|
|
</Text>
|
|
|
|
</TouchableOpacity>
|
|
|
|
)}
|
|
|
|
{expandedGroups[item.attribute_name] && (
|
|
|
|
<TouchableOpacity
|
|
|
|
style={styles.expandButton}
|
|
|
|
onPress={() =>
|
|
|
|
toggleExpand(item.attribute_name)
|
|
|
|
}
|
|
|
|
>
|
|
|
|
<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}>
|
|
|
|
<Text style={styles.uniqueTextBlock}>
|
|
|
|
{item.attribute_name}
|
|
|
|
</Text>
|
|
|
|
<View style={styles.horizontalFlexContainer}>
|
|
|
|
{getDisplayAttributes(
|
|
|
|
item.attributes,
|
|
|
|
item.attribute_name
|
|
|
|
).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] &&
|
|
|
|
item.attributes.length > 6 && (
|
|
|
|
<TouchableOpacity
|
|
|
|
style={styles.expandButton}
|
|
|
|
onPress={() =>
|
|
|
|
toggleExpand(item.attribute_name)
|
|
|
|
}
|
|
|
|
>
|
|
|
|
<Text style={styles.expandButtonText}>
|
|
|
|
更多
|
|
|
|
</Text>
|
|
|
|
</TouchableOpacity>
|
|
|
|
)}
|
|
|
|
{expandedGroups[item.attribute_name] && (
|
|
|
|
<TouchableOpacity
|
|
|
|
style={styles.expandButton}
|
|
|
|
onPress={() =>
|
|
|
|
toggleExpand(item.attribute_name)
|
|
|
|
}
|
|
|
|
>
|
|
|
|
<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>
|
|
|
|
</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,
|
|
|
|
},
|
|
|
|
});
|