diff --git a/app/screens/ProductDetailScreen.tsx b/app/screens/ProductDetailScreen.tsx
index 5443d71..dacfc39 100644
--- a/app/screens/ProductDetailScreen.tsx
+++ b/app/screens/ProductDetailScreen.tsx
@@ -16,7 +16,7 @@ import {
Platform,
StatusBar,
SafeAreaView,
- Modal
+ Modal,
} from "react-native";
import fontSize from "../utils/fontsizeUtils";
import widthUtils from "../utils/widthUtils";
@@ -29,13 +29,12 @@ 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 { getSubjectTransLanguage,getSkuTransLanguage } 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 {
productApi,
ProductDetailParams,
@@ -91,18 +90,18 @@ export const ProductDetailScreen = () => {
// 遍历数据
res.skus.forEach((item) => {
item.attributes.forEach((attribute) => {
- const { attribute_name, value } = attribute;
+ const { attribute_name_trans, value } = attribute;
// 如果结果对象中没有对应的属性名,则创建一个空数组
- if (!result[attribute_name]) {
- result[attribute_name] = [];
+ if (!result[attribute_name_trans]) {
+ result[attribute_name_trans] = [];
}
// 如果当前属性的值(value)已经存在于该组内,跳过
if (
- !result[attribute_name].some(
+ !result[attribute_name_trans].some(
(existingAttribute: any) => existingAttribute.value === value
)
) {
- result[attribute_name].push(attribute);
+ result[attribute_name_trans].push(attribute);
}
});
});
@@ -128,7 +127,10 @@ export const ProductDetailScreen = () => {
// 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
+ attribute_name_trans: attributeName,
+ attribute_name_trans_ar: attributeName,
+ attribute_name_trans_en: attributeName,
+ has_image: withImage.length > 0,
attributes: [...withImage, ...withoutImage],
});
}
@@ -325,9 +327,9 @@ export const ProductDetailScreen = () => {
imageUrls.length > 5 ? imageUrls.slice(0, 5) : imageUrls;
setImageUrls(limitedImageUrls);
setGroupList(list);
-
- const previousScreen = navigation.getState().routes[navigation.getState().index - 1];
+ const previousScreen =
+ navigation.getState().routes[navigation.getState().index - 1];
const data = {
offer_id: res.offer_id,
category_id: res.category_id,
@@ -337,12 +339,9 @@ export const ProductDetailScreen = () => {
product_name: res.subject,
product_img: res.product_image_urls[0],
timestamp: new Date().toISOString(),
- }
- logViewProduct(data,previousScreen?.name as string);
-
+ };
+ logViewProduct(data, previousScreen?.name as string);
console.log(getBurialPointData());
-
-
} catch (error) {
console.error("Error fetching product details:", error);
} finally {
@@ -389,7 +388,6 @@ export const ProductDetailScreen = () => {
navigation.navigate("Search");
}, [navigation]);
-
const handleCameraPress = useCallback(() => {
setShowImagePickerModal(true);
}, []);
@@ -404,36 +402,35 @@ export const ProductDetailScreen = () => {
},
[navigation]
);
-
// Add this function to render skeleton UI
const renderSkeletonItems = () => {
// Create an array of 5 skeleton items
- return Array(5).fill(0).map((_, index) => (
-
-
-
-
-
+ return Array(5)
+ .fill(0)
+ .map((_, index) => (
+
+
+
+
+
+
-
- ));
+ ));
};
-
// 清理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');
+ 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) {
@@ -442,12 +439,10 @@ export const ProductDetailScreen = () => {
setGalleryUsed(false);
}
};
-
// 处理从相册选择
const handleChooseFromGallery = useCallback(async () => {
console.log("handleChooseFromGallery");
setShowImagePickerModal(false);
-
// 等待模态窗关闭后再执行
setTimeout(async () => {
try {
@@ -458,7 +453,6 @@ export const ProductDetailScreen = () => {
console.log("相册权限被拒绝");
return;
}
-
// 打开相册
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
@@ -466,10 +460,8 @@ export const ProductDetailScreen = () => {
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,
@@ -483,12 +475,10 @@ export const ProductDetailScreen = () => {
}
}, 500);
}, [navigation, userStore.user]);
-
// 处理相机拍照
const handleTakePhoto = useCallback(async () => {
console.log("handleTakePhoto");
setShowImagePickerModal(false);
-
// 等待模态窗关闭后再执行
setTimeout(async () => {
try {
@@ -498,17 +488,14 @@ export const ProductDetailScreen = () => {
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", {
@@ -523,19 +510,15 @@ export const ProductDetailScreen = () => {
}
}, 500);
}, [navigation, userStore.user]);
-
// 重置应用状态函数
const resetAppState = useCallback(() => {
// 重置标记
setGalleryUsed(false);
-
// 清理缓存
cleanupImagePickerCache();
-
// 提示用户
Alert.alert("已重置", "现在您可以使用相机功能了");
}, []);
-
return (
@@ -555,18 +538,17 @@ export const ProductDetailScreen = () => {
>
-
-
-
+
{t("search")}
-
{
@@ -660,7 +642,8 @@ export const ProductDetailScreen = () => {
}}
>
- {activeIndex + 1}/{product?.product_image_urls?.length}
+ {activeIndex + 1}/
+ {product?.product_image_urls?.length}
@@ -693,9 +676,10 @@ export const ProductDetailScreen = () => {
{userStore.user?.vip_level > 0 && (
<>
- -5%
+
+ -5%
+
-
{
{groupList.map((item, index) =>
item.has_image ? (
-
+
- {item.attribute_name} :{" "}
+ {item.attribute_name_trans} :{" "}
{
- item.attributes.find((item) => item.has_color)
- ?.value
+ // getSkuTransLanguage()
+ item.attributes.find(
+ (item) => item.has_color
+ )?.value
}
{getDisplayAttributes(
item.attributes,
- item.attribute_name
+ item.attribute_name_trans
).map((attribute) => (
- handleColorSelect(attribute.value, index)
+ handleColorSelect(
+ attribute.value,
+ index
+ )
}
style={[
styles.colorImageContainer,
@@ -740,17 +729,19 @@ export const ProductDetailScreen = () => {
]}
>
))}
- {!expandedGroups[item.attribute_name] &&
+ {!expandedGroups[item.attribute_name_trans] &&
item.attributes.length > 6 && (
- toggleExpand(item.attribute_name)
+ toggleExpand(item.attribute_name_trans)
}
>
@@ -758,11 +749,11 @@ export const ProductDetailScreen = () => {
)}
- {expandedGroups[item.attribute_name] && (
+ {expandedGroups[item.attribute_name_trans] && (
- toggleExpand(item.attribute_name)
+ toggleExpand(item.attribute_name_trans)
}
>
@@ -793,14 +784,14 @@ export const ProductDetailScreen = () => {
)}
) : (
-
+
- {item.attribute_name}
+ {item.attribute_name_trans}
{getDisplayAttributes(
item.attributes,
- item.attribute_name
+ item.attribute_name_trans
).map((attribute) => (
{
))}
- {!expandedGroups[item.attribute_name] &&
+ {!expandedGroups[item.attribute_name_trans] &&
item.attributes.length > 6 && (
- toggleExpand(item.attribute_name)
+ toggleExpand(item.attribute_name_trans)
}
>
@@ -837,11 +828,11 @@ export const ProductDetailScreen = () => {
)}
- {expandedGroups[item.attribute_name] && (
+ {expandedGroups[item.attribute_name_trans] && (
- toggleExpand(item.attribute_name)
+ toggleExpand(item.attribute_name_trans)
}
>
@@ -888,31 +879,32 @@ export const ProductDetailScreen = () => {
showsHorizontalScrollIndicator={false}
contentContainerStyle={styles.productGridContainer}
>
- {isSimilarsFlag ?
- similars?.map((item) => (
- handleProductPress(item)}
- >
-
-
-
-
-
- {item.max_price}
-
-
- FCFA
-
-
-
- ))
- : renderSkeletonItems()
- }
+ {isSimilarsFlag
+ ? similars?.map((item) => (
+ handleProductPress(item)}
+ >
+
+
+
+
+
+ {item.max_price}
+
+
+ FCFA
+
+
+
+ ))
+ : renderSkeletonItems()}
@@ -962,7 +954,7 @@ export const ProductDetailScreen = () => {
)}
-
+
{/* Image Picker Modal */}
{
重置相机功能
)}
-
-
从相册选择
-
setShowImagePickerModal(false)}
@@ -1019,15 +1008,15 @@ export const ProductDetailScreen = () => {
const styles = StyleSheet.create({
safeArea: {
flex: 1,
- backgroundColor: '#fff',
+ backgroundColor: "#fff",
},
safeAreaContent: {
flex: 1,
- paddingTop: Platform.OS === 'android' ? 0 : 0,
+ paddingTop: Platform.OS === "android" ? 0 : 0,
},
container: {
flex: 1,
- backgroundColor: '#fff',
+ backgroundColor: "#fff",
},
scrollView: {
flex: 1,
@@ -1306,7 +1295,7 @@ const styles = StyleSheet.create({
fontSize: fontSize(18),
color: "#f1c355",
textAlign: "center",
- marginLeft:2
+ marginLeft: 2,
},
emphasizedTextVip: {
fontStyle: "italic",
@@ -1733,14 +1722,14 @@ const styles = StyleSheet.create({
color: "#666",
},
skeletonBox: {
- backgroundColor: '#e0e0e0',
+ backgroundColor: "#e0e0e0",
height: widthUtils(90, 90).height,
width: widthUtils(90, 90).width,
borderRadius: 5,
},
skeletonText: {
height: 16,
- backgroundColor: '#e0e0e0',
+ backgroundColor: "#e0e0e0",
borderRadius: 3,
},
imagePickerOverlay: {
diff --git a/app/screens/setting/SettingList.tsx b/app/screens/setting/SettingList.tsx
index 6e92820..c16eb80 100644
--- a/app/screens/setting/SettingList.tsx
+++ b/app/screens/setting/SettingList.tsx
@@ -1,4 +1,12 @@
-import { View, Text, StyleSheet, TouchableOpacity, SafeAreaView, StatusBar, Platform } from "react-native";
+import {
+ View,
+ Text,
+ StyleSheet,
+ TouchableOpacity,
+ SafeAreaView,
+ StatusBar,
+ Platform,
+} from "react-native";
import BackIcon from "../../components/BackIcon";
import fontSize from "../../utils/fontsizeUtils";
import LeftArrowIcon from "../../components/DownArrowIcon";
@@ -8,24 +16,26 @@ import { useState, useEffect } from "react";
import { settingApi, MySetting } from "../../services/api/setting";
import { RootStackParamList } from "../../navigation/types";
import { eventBus } from "../../utils/eventBus";
-import AsyncStorage from '@react-native-async-storage/async-storage';
+import AsyncStorage from "@react-native-async-storage/async-storage";
import { useTranslation } from "react-i18next";
+import useUserStore from "../../store/user";
export const SettingList = () => {
const { t } = useTranslation();
const [mySetting, setMySetting] = useState();
+ const { user } = useUserStore();
const getMySetting = async () => {
- const res = await settingApi.getMySetting()
- console.log("MySetting:");
- console.log(res);
+ const res = await settingApi.getMySetting();
setMySetting(res);
- }
+ };
useEffect(() => {
- getMySetting();
- const refreshSetting = () => {
+ if (user?.user_id) {
getMySetting();
}
+ const refreshSetting = () => {
+ getMySetting();
+ };
eventBus.on("refreshSetting", refreshSetting);
return () => {
eventBus.off("refreshSetting", refreshSetting);
@@ -39,15 +49,13 @@ export const SettingList = () => {
- navigation.goBack()}
- >
+ navigation.goBack()}>
{t("settings.title")}
-
+
{t("settings.profile")}
@@ -70,19 +78,19 @@ export const SettingList = () => {
- {
- if (mySetting?.language && mySetting?.currency) {
- navigation.navigate("MyAddress");
- }
- }}
- style={styles.item}
- >
- {t("settings.my_address")}
-
-
-
-
+ {
+ if (mySetting?.language && mySetting?.currency) {
+ navigation.navigate("MyAddress");
+ }
+ }}
+ style={styles.item}
+ >
+ {t("settings.my_address")}
+
+
+
+
{t("settings.feedback")}
@@ -102,10 +110,13 @@ export const SettingList = () => {
- {
- AsyncStorage.clear();
- navigation.navigate("CountrySelect");
- }}>
+ {
+ AsyncStorage.clear();
+ navigation.navigate("CountrySelect");
+ }}
+ >
{t("settings.clear_cache")}
@@ -115,9 +126,9 @@ export const SettingList = () => {
{
- // if (mySetting?.language && mySetting?.currency) {
- navigation.navigate("CountrySetting", { mySetting });
- // }
+ // if (mySetting?.language && mySetting?.currency) {
+ navigation.navigate("CountrySetting", { mySetting });
+ // }
}}
style={styles.item}
>
@@ -136,7 +147,7 @@ export const SettingList = () => {
const styles = StyleSheet.create({
safeArea: {
flex: 1,
- backgroundColor: '#fff',
+ backgroundColor: "#fff",
},
safeAreaContent: {
flex: 1,
diff --git a/app/services/api/productApi.ts b/app/services/api/productApi.ts
index ae08871..1102af1 100644
--- a/app/services/api/productApi.ts
+++ b/app/services/api/productApi.ts
@@ -178,6 +178,9 @@ export type Products = Product[]
export interface ProductGroupList {
attribute_name:string,
has_image:boolean,
+ attribute_name_trans:string,
+ attribute_name_trans_ar:string,
+ attribute_name_trans_en:string,
attributes:SkuAttribute[],
value?:string
}
diff --git a/app/utils/languageUtils.ts b/app/utils/languageUtils.ts
index 486696a..5dab337 100644
--- a/app/utils/languageUtils.ts
+++ b/app/utils/languageUtils.ts
@@ -30,28 +30,28 @@ export const getSubjectTransLanguage = >(data: T):
-// export const getSkuTransLanguage = >(data: T): string => {
-// // 获取当前i18n语言
-// const currentLang = getCurrentLanguage();
+export const getSkuTransLanguage = >(data: T): string => {
+ // 获取当前i18n语言
+ const currentLang = getCurrentLanguage();
-// // 特殊处理中文
-// if (currentLang === 'zh' && 'value' in data) {
-// return data.value as string;
-// }
-
-// // 获取所有subject_trans开头的字段
-// const translationFields = Object.keys(data).filter(key =>
-// key.startsWith('value_trans')
-// );
-
-// // 查找匹配的字段
-// const matchedField = translationFields.find(field => {
-// // 从字段名中提取语言代码
-// const langCode = field.replace('value_trans_', '');
-// // 如果没有后缀,则为法语
-// return langCode === '' ? currentLang === 'fr' : langCode === currentLang;
-// });
-
-// // 返回匹配的翻译值,如果没有匹配则返回法语
-// return (data[matchedField || 'value_trans'] as string) || '';
-// };
+ // 特殊处理中文
+ if (currentLang === 'zh' && 'value' in data) {
+ return data.value as string;
+ }
+
+ // 获取所有subject_trans开头的字段
+ const translationFields = Object.keys(data).filter(key =>
+ key.startsWith('value_trans')
+ );
+
+ // 查找匹配的字段
+ const matchedField = translationFields.find(field => {
+ // 从字段名中提取语言代码
+ const langCode = field.replace('value_trans_', '');
+ // 如果没有后缀,则为法语
+ return langCode === '' ? currentLang === 'fr' : langCode === currentLang;
+ });
+
+ // 返回匹配的翻译值,如果没有匹配则返回法语
+ return (data[matchedField || 'value_trans'] as string) || '';
+};