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.

1314 lines
43 KiB

import React, { useState } from "react";
import {
View,
Text,
Image,
StyleSheet,
TouchableOpacity,
TextInput,
KeyboardAvoidingView,
Platform,
ScrollView,
SafeAreaView,
StatusBar,
Modal,
Alert,
} from "react-native";
import BackIcon from "../../components/BackIcon";
import fontSize from "../../utils/fontsizeUtils";
import { LinearGradient } from "expo-linear-gradient";
import widthUtils from "../../utils/widthUtils";
import TrapezoidIcon from "../../components/TrapezoidIcon";
import { useNavigation } from "@react-navigation/native";
import * as ImagePicker from "expo-image-picker";
import * as FileSystem from "expo-file-system";
import { inquiriesApi, InquiryFormData } from "../../services/api/inquiries";
import DownArrowIcon from "../../components/DownArrowIcon";
export const InquiryScreen = () => {
const [searchImg, setSearchImg] = useState("");
const [showImagePickerModal, setShowImagePickerModal] = useState(false);
const [status, setStatus] = useState(0);
const [galleryUsed, setGalleryUsed] = useState(false);
const [formData, setFormData] = useState({
name: "",
quantity: "",
material: "",
link: "",
remark: "",
});
const [isSubmitting, setIsSubmitting] = useState(false);
const [inquiryStatus, setInquiryStatus] = useState(0); // 0: 请求报价, 1: 进行中
const [lastInquiry, setLastInquiry] = useState<any>(null);
const [activeTab, setActiveTab] = useState(0); // 0: 请求报价, 1: 进行中, 2: 已完成
const [inquiries, setInquiries] = useState<any[]>([]); // 询盘列表
const [completedInquiries, setCompletedInquiries] = useState<any[]>([]); // 已完成询盘列表
const [page, setPage] = useState(1); // 当前页码
const [loading, setLoading] = useState(false); // 加载状态
const [hasMore, setHasMore] = useState(true); // 是否还有更多数据
const [refreshing, setRefreshing] = useState(false); // 下拉刷新状态
const navigation = useNavigation();
// 清理expo-image-picker临时文件
const cleanupImagePickerCache = async () => {
try {
const cacheDir = `${FileSystem.cacheDirectory}ImagePicker`;
await FileSystem.deleteAsync(cacheDir, { idempotent: true });
console.log("已清理ImagePicker缓存");
setGalleryUsed(false);
} catch (error) {
console.log("清理缓存错误", error);
}
};
// 处理从相册选择
const handleChooseFromGallery = 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);
setSearchImg(result.assets[0].uri);
await cleanupImagePickerCache();
}
} catch (error: any) {
console.error("相册错误:", error);
await cleanupImagePickerCache();
}
}, 500);
};
// 处理相机拍照
const handleTakePhoto = 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);
setSearchImg(result.assets[0].uri);
}
await cleanupImagePickerCache();
} catch (error: any) {
console.error("相机错误:", error);
await cleanupImagePickerCache();
}
}, 500);
};
// 重置应用状态函数
const resetAppState = () => {
setGalleryUsed(false);
cleanupImagePickerCache();
Alert.alert("已重置", "现在您可以使用相机功能了");
};
const updataImg = () => {
setShowImagePickerModal(true);
};
const handleSubmit = async () => {
if (!searchImg) {
Alert.alert("提示", "请先上传图片");
return;
}
if (!formData.quantity) {
Alert.alert("提示", "请输入数量");
return;
}
try {
setIsSubmitting(true);
// Create FormData object
const submitData = new FormData() as InquiryFormData;
// Add image to FormData
const imageUri = searchImg;
const filename = imageUri.split("/").pop() || "image.jpg";
const match = /\.(\w+)$/.exec(filename);
const type = match ? `image/${match[1]}` : "image/jpeg";
// 创建图片对象
const imageObject = {
uri: Platform.OS === "ios" ? imageUri.replace("file://", "") : imageUri,
name: filename,
type: type,
};
// 将图片对象转换为 Blob
const imageFetchResponse = await fetch(imageObject.uri);
const imageBlob = await imageFetchResponse.blob();
// 添加图片到 FormData
submitData.append("image", imageBlob, filename);
// Add other form fields
submitData.append("name", formData.name);
submitData.append("quantity", formData.quantity);
submitData.append("material", formData.material);
submitData.append("link", formData.link);
submitData.append("remark", formData.remark);
console.log("Submitting form data:", {
image: imageUri,
name: formData.name,
quantity: formData.quantity,
material: formData.material,
link: formData.link,
remark: formData.remark,
});
// Submit the inquiry
try {
const response = await inquiriesApi.createInquiry(submitData);
console.log("Inquiry created:", response);
setStatus(response.status);
if (response.status === 1) {
setLastInquiry(response);
}
} catch (error) {
Alert.alert("错误", "提交失败,请重试");
}
// Reset form and show success message
setSearchImg("");
setFormData({
name: "",
quantity: "",
material: "",
link: "",
remark: "",
});
} catch (error) {
console.error("Error creating inquiry:", error);
Alert.alert("错误", "提交失败,请重试");
} finally {
setIsSubmitting(false);
}
};
// 获取询盘列表
const fetchInquiries = async (pageNum = 1, refresh = false) => {
try {
if (!hasMore && !refresh) return; // 没有更多数据且不是刷新操作,直接返回
setLoading(true);
const response = await inquiriesApi.getInquiries(pageNum,10);
console.log("Inquiries fetched:", response);
// 处理响应数据,兼容不同格式
const inquiryData = response.items.filter(item => {
return item.status === (activeTab === 1 ? 1 : 2);
});
if (inquiryData && inquiryData.length >= 0) {
if (refresh) {
if (activeTab === 1) {
setInquiries(inquiryData);
} else {
setCompletedInquiries(inquiryData);
}
} else {
if (activeTab === 1) {
setInquiries(prev => [...prev, ...inquiryData]);
} else {
setCompletedInquiries(prev => [...prev, ...inquiryData]);
}
}
// 判断是否还有更多数据
setHasMore(inquiryData.length > 0);
setPage(pageNum);
}
} catch (error) {
console.error("Error fetching inquiries:", error);
Alert.alert("错误", "获取询盘列表失败");
} finally {
setLoading(false);
setRefreshing(false);
}
};
// 加载更多
const handleLoadMore = () => {
if (loading || !hasMore) return;
fetchInquiries(page + 1);
};
// 检测滚动到底部
const handleScroll = (event: any) => {
if ((activeTab !== 1 && activeTab !== 2) || loading || !hasMore) return;
const { layoutMeasurement, contentOffset, contentSize } = event.nativeEvent;
const paddingToBottom = 20; // 距离底部多少触发加载
if (layoutMeasurement.height + contentOffset.y >=
contentSize.height - paddingToBottom) {
handleLoadMore();
}
};
// Tab切换时加载对应数据
React.useEffect(() => {
if (activeTab === 1 || activeTab === 2) {
fetchInquiries(1, true);
}
}, [activeTab]);
return (
<SafeAreaView style={styles.safeArea}>
<StatusBar barStyle="dark-content" backgroundColor="#C8DFFF" />
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : "height"}
style={styles.keyboardAvoidingContainer}
keyboardVerticalOffset={Platform.OS === "ios" ? 100 : 0}
>
<View style={styles.productInquirySection1}>
<LinearGradient
colors={["#C8DFFF", "#ECF5FF"]}
style={styles.headerGradient}
start={{ x: 0, y: 0 }}
end={{ x: 0, y: 1 }}
>
<View>
<View style={styles.titleContainer}>
<TouchableOpacity
style={styles.backButton}
onPress={() => navigation.goBack()}
>
<BackIcon size={fontSize(24)} />
</TouchableOpacity>
<View style={styles.titleTextContainer}>
<Text style={styles.titleText}></Text>
</View>
<View style={styles.placeholder} />
</View>
<View style={styles.heardContainer}>
<View>
<Text style={styles.heardContainer1Text}>
{"\n"}
</Text>
</View>
<View>
<Text style={styles.heardContainer1Img}>
<Image
source={require("../../../assets/img/image_7a9fbefc.png")}
style={styles.heardContainer1Img}
/>
</Text>
</View>
</View>
</View>
</LinearGradient>
<View style={styles.productQuoteSection}>
<View style={styles.tabContainer}>
{[
{ label: "请求报价", id: 0 },
{ label: "进行中", id: 1 },
{ label: "已完成", id: 2 }
].map((tab) => (
<TouchableOpacity
key={tab.id}
onPress={() => setActiveTab(tab.id)}
style={[
styles.tabButton,
activeTab === tab.id && styles.activeTabButton
]}
>
<Text
style={[
styles.tabButtonText,
activeTab === tab.id && styles.activeTabButtonText
]}
>
{tab.label}
</Text>
</TouchableOpacity>
))}
</View>
{activeTab === 0 && (
<ScrollView
contentContainerStyle={styles.scrollContent}
keyboardShouldPersistTaps="handled"
showsVerticalScrollIndicator={false}
>
{searchImg ? (
<View style={styles.container}>
<View style={styles.cardContainerWithButtons}>
<View style={styles.productCardContainer}>
<View style={styles.productCardContainer1}>
<Image
source={
searchImg
? { uri: searchImg }
: require("../../../assets/img/image_8f3bf967.png")
}
style={styles.articleThumbnailContainer}
/>
<View style={styles.articleTitleContainer}>
<Text style={styles.elegantText}></Text>
<TextInput
style={styles.articleTitleContainer1}
value={formData.name}
onChangeText={(text) =>
setFormData((prev) => ({ ...prev, name: text }))
}
placeholder="请输入商品名称"
/>
</View>
</View>
<View style={styles.flexRowWithContent}>
<View style={styles.centerColumnWithText}>
<Text style={styles.quantityLabelTextStyle}>
<Text style={styles.highlightedText}>*</Text>
<Text></Text>
</Text>
<TextInput
style={styles.quantityContainer}
value={formData.quantity}
onChangeText={(text) =>
setFormData((prev) => ({
...prev,
quantity: text,
}))
}
placeholder="请输入数量"
keyboardType="numeric"
/>
</View>
<View style={styles.matiereContainer}>
<Text style={styles.quantityLabelTextStyle}>
</Text>
<TextInput
style={styles.quantityContainer}
value={formData.material}
onChangeText={(text) =>
setFormData((prev) => ({
...prev,
material: text,
}))
}
placeholder="请输入材质"
/>
</View>
</View>
<View style={styles.linkContainer}>
<Text style={styles.elegantText}></Text>
<TextInput
style={styles.contentWrapper}
value={formData.link}
onChangeText={(text) =>
setFormData((prev) => ({ ...prev, link: text }))
}
placeholder="请输入链接"
multiline={true}
/>
</View>
<View style={styles.linkContainer}>
<Text style={styles.elegantText}></Text>
<TextInput
style={styles.contentWrapper}
value={formData.remark}
onChangeText={(text) =>
setFormData((prev) => ({ ...prev, remark: text }))
}
placeholder="请输入备注"
multiline={true}
/>
</View>
</View>
<View style={styles.buttonGroupConfirmation}>
<TouchableOpacity
style={styles.cancelButtonStyle}
onPress={() => setSearchImg("")}
>
<Text style={styles.cancelButtonText}></Text>
</TouchableOpacity>
<TouchableOpacity
style={[
styles.confirmButtonStyle,
isSubmitting && styles.disabledButton,
]}
onPress={handleSubmit}
disabled={isSubmitting}
>
<Text style={styles.confirmButtonText}>
{isSubmitting ? "提交中..." : "确认"}
</Text>
</TouchableOpacity>
</View>
</View>
</View>
) : (
<View style={styles.productInfoContainer}>
<View style={styles.productImageUploadSection}>
<View style={styles.productInfoContainer1}>
<Image
source={require("../../../assets/img/image_fac2b0a9.png")}
style={styles.productImageIcon}
resizeMode="cover"
/>
<View style={styles.productQuoteContainer}>
<Text style={styles.productInfoHeading}>
</Text>
<Text style={styles.productInfoMessage1}>
{"\n"}{"\n"}
</Text>
</View>
</View>
<View style={styles.photoUploadContainer}>
<TouchableOpacity
style={styles.photoUploadContainer1}
onPress={updataImg}
>
<LinearGradient
colors={["#F5F9FF", "#D8E8FF", "#B9D6FF"]}
style={styles.gradientBackground}
start={{ x: 0, y: 0 }}
end={{ x: 0, y: 1 }}
>
<View style={styles.photoUploadPromptContainer}>
<Text style={styles.centerHeadingBoldWhite}>
</Text>
</View>
</LinearGradient>
</TouchableOpacity>
</View>
</View>
</View>
)}
</ScrollView>
)}
</View>
</View>
{activeTab === 1 && (
<ScrollView
style={{ flex: 1, backgroundColor: "white" }}
contentContainerStyle={{ paddingBottom: 16 }}
onScroll={handleScroll}
scrollEventThrottle={16}
>
{inquiries.length > 0 ? (
<>
{inquiries.map((inquiry, index) => (
<View
key={inquiry.id || index}
style={{
backgroundColor: "#f2f6ff",
borderRadius: 16,
margin: 16,
marginBottom: 8,
shadowColor: "#000",
shadowOpacity: 0.05,
shadowRadius: 4,
elevation: 2,
}}
>
{/* 顶部蓝色条 */}
<View
style={{
backgroundColor: "#c8e0ff",
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: 20,
paddingVertical: 10,
}}
>
<Text
style={{ color: "#006fe1", fontWeight: "bold", fontSize: fontSize(16) }}
>
Devis en cours
</Text>
<Text style={{ color: "#006fe1", fontSize: fontSize(14) }}>
{inquiry.create_time || new Date().toLocaleString()}
</Text>
</View>
{/* 内容区 */}
<View
style={{
flexDirection: "row",
padding: 20,
backgroundColor: "#f2f6ff",
borderBottomLeftRadius: 16,
borderBottomRightRadius: 16,
}}
>
<Image
source={
inquiry.image_url
? { uri: inquiry.image_url }
: require("../../../assets/img/image_8f3bf967.png")
}
style={{
width: 80,
height: 80,
borderRadius: 8,
marginRight: 18,
backgroundColor: "#fff",
}}
/>
<View style={{ flex: 1 }}>
<Text
style={{
fontWeight: "bold",
fontSize: fontSize(18),
marginBottom: 8,
}}
>
{inquiry.name || "Nom d'article"}
</Text>
<View style={{ flexDirection: "row", marginBottom: 8 }}>
<View>
<Text style={{ color: "#888", fontSize: fontSize(14) }}>
Quantité
</Text>
<Text style={{ fontSize: fontSize(16), fontWeight: "bold" }}>
{inquiry.quantity || "--"}
</Text>
</View>
<View style={{ marginLeft: 32 }}>
<Text style={{ color: "#888", fontSize: fontSize(14) }}>
Matière
</Text>
<Text style={{ fontSize: fontSize(16), fontWeight: "bold" }}>
{inquiry.material || "--"}
</Text>
</View>
</View>
<View
style={{
flexDirection: "row",
alignItems: "center",
marginBottom: 4,
}}
>
<Text
style={{ color: "#888", fontSize: fontSize(14), marginRight: 8 }}
>
Lien
</Text>
<Text style={{ flex: 1, fontSize: fontSize(14) }} numberOfLines={1}>
{inquiry.link || "无"}
</Text>
<View style={{ flexDirection: "row", alignItems: "center", marginLeft: 8 }}>
<Text style={{ color: "#888" }}>Plus</Text>
<View style={{ marginLeft: 4 }}>
<DownArrowIcon size={12} color="#888" rotation={0} />
</View>
</View>
</View>
<View style={{ flexDirection: "row", alignItems: "center" }}>
<Text
style={{ color: "#888", fontSize: fontSize(14), marginRight: 8 }}
>
Remarque
</Text>
<Text style={{ flex: 1, fontSize: fontSize(14) }} numberOfLines={1}>
{inquiry.remark || "无"}
</Text>
<View style={{ flexDirection: "row", alignItems: "center", marginLeft: 8 }}>
<Text style={{ color: "#888" }}>Plus</Text>
<View style={{ marginLeft: 4 }}>
<DownArrowIcon size={12} color="#888" rotation={0} />
</View>
</View>
</View>
</View>
</View>
</View>
))}
{/* 底部加载更多 */}
{loading && (
<View style={styles.loadingContainer}>
<Text style={styles.loadingText}>...</Text>
</View>
)}
{!hasMore && inquiries.length > 0 && (
<Text style={styles.noMoreText}></Text>
)}
</>
) : loading ? (
<View style={styles.loadingContainer}>
<Text style={styles.loadingText}>...</Text>
</View>
) : (
<View style={styles.emptyContainer}>
<Text style={styles.emptyText}></Text>
</View>
)}
</ScrollView>
)}
{activeTab === 2 && (
<ScrollView
style={{ flex: 1, backgroundColor: "white" }}
contentContainerStyle={{ paddingBottom: 16 }}
onScroll={handleScroll}
scrollEventThrottle={16}
>
{completedInquiries.length > 0 ? (
<>
{completedInquiries.map((inquiry, index) => (
<View
key={inquiry.id || index}
style={{
backgroundColor: "#f2f6ff",
borderRadius: 16,
margin: 16,
marginBottom: 8,
shadowColor: "#000",
shadowOpacity: 0.05,
shadowRadius: 4,
elevation: 2,
}}
>
{/* 顶部蓝色条 */}
<View
style={{
backgroundColor: "#c8e0ff",
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: 20,
paddingVertical: 10,
}}
>
<Text
style={{ color: "#006fe1", fontWeight: "bold", fontSize: fontSize(16) }}
>
Devis terminé
</Text>
<Text style={{ color: "#006fe1", fontSize: fontSize(14) }}>
{inquiry.create_time || new Date().toLocaleString()}
</Text>
</View>
{/* 内容区 */}
<View
style={{
flexDirection: "row",
padding: 20,
backgroundColor: "#f2f6ff",
borderBottomLeftRadius: 16,
borderBottomRightRadius: 16,
}}
>
<Image
source={
inquiry.image_url
? { uri: inquiry.image_url }
: require("../../../assets/img/image_8f3bf967.png")
}
style={{
width: 80,
height: 80,
borderRadius: 8,
marginRight: 18,
backgroundColor: "#fff",
}}
/>
<View style={{ flex: 1 }}>
<Text
style={{
fontWeight: "bold",
fontSize: fontSize(18),
marginBottom: 8,
}}
>
{inquiry.name || "Nom d'article"}
</Text>
<View style={{ flexDirection: "row", marginBottom: 8 }}>
<View>
<Text style={{ color: "#888", fontSize: fontSize(14) }}>
Quantité
</Text>
<Text style={{ fontSize: fontSize(16), fontWeight: "bold" }}>
{inquiry.quantity || "--"}
</Text>
</View>
<View style={{ marginLeft: 32 }}>
<Text style={{ color: "#888", fontSize: fontSize(14) }}>
Matière
</Text>
<Text style={{ fontSize: fontSize(16), fontWeight: "bold" }}>
{inquiry.material || "--"}
</Text>
</View>
</View>
<View
style={{
flexDirection: "row",
alignItems: "center",
marginBottom: 4,
}}
>
<Text
style={{ color: "#888", fontSize: fontSize(14), marginRight: 8 }}
>
Lien
</Text>
<Text style={{ flex: 1, fontSize: fontSize(14) }} numberOfLines={1}>
{inquiry.link || "无"}
</Text>
<View style={{ flexDirection: "row", alignItems: "center", marginLeft: 8 }}>
<Text style={{ color: "#888" }}>Plus</Text>
<View style={{ marginLeft: 4 }}>
<DownArrowIcon size={12} color="#888" rotation={0} />
</View>
</View>
</View>
<View style={{ flexDirection: "row", alignItems: "center" }}>
<Text
style={{ color: "#888", fontSize: fontSize(14), marginRight: 8 }}
>
Remarque
</Text>
<Text style={{ flex: 1, fontSize: fontSize(14) }} numberOfLines={1}>
{inquiry.remark || "无"}
</Text>
<View style={{ flexDirection: "row", alignItems: "center", marginLeft: 8 }}>
<Text style={{ color: "#888" }}>Plus</Text>
<View style={{ marginLeft: 4 }}>
<DownArrowIcon size={12} color="#888" rotation={0} />
</View>
</View>
</View>
</View>
</View>
</View>
))}
{/* 底部加载更多 */}
{loading && (
<View style={styles.loadingContainer}>
<Text style={styles.loadingText}>...</Text>
</View>
)}
{!hasMore && completedInquiries.length > 0 && (
<Text style={styles.noMoreText}></Text>
)}
</>
) : loading ? (
<View style={styles.loadingContainer}>
<Text style={styles.loadingText}>...</Text>
</View>
) : (
<View style={styles.emptyContainer}>
<Text style={styles.emptyText}></Text>
</View>
)}
</ScrollView>
)}
</KeyboardAvoidingView>
{/* 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}
>
<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: "#C8DFFF",
},
keyboardAvoidingContainer: {
flex: 1,
width: "100%",
},
container: {
flex: 1,
width: "100%",
},
scrollContent: {
flexGrow: 1,
},
productInquirySection1: {
flexDirection: "column",
alignItems: "stretch",
backgroundColor: "#f0f0f0",
},
titleContainer: {
paddingHorizontal: 16,
paddingTop: 16,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
},
backButton: {
width: widthUtils(24, 24).width,
},
titleTextContainer: {
flex: 1,
alignItems: "center",
},
titleText: {
fontSize: fontSize(18),
fontWeight: "600",
textAlign: "center",
},
placeholder: {
width: widthUtils(24, 24).width,
opacity: 0,
},
heardContainer: {
paddingLeft: 16,
paddingRight: 16,
flexDirection: "row",
justifyContent: "space-between",
height: 234,
marginTop: 50,
},
heardContainer1Text: {
fontSize: 16,
fontWeight: 400,
color: "#000",
},
heardContainer1Img: {
width: 116,
height: 116,
},
productQuoteSection: {
paddingRight: 16,
paddingLeft: 16,
marginTop: -110,
},
tabContainer: {
flexDirection: "row",
justifyContent: "space-between",
paddingHorizontal: 16,
marginBottom: 16,
},
tabButton: {
width: (widthUtils(375, 375).width - 64) / 3,
height: 44,
backgroundColor: "#f5f8ff",
borderRadius: 8,
alignItems: "center",
justifyContent: "center",
borderWidth: 1,
borderColor: "#e0e0e0",
},
activeTabButton: {
backgroundColor: "#006fe1",
borderColor: "#006fe1",
shadowColor: "#006fe1",
shadowOpacity: 0.2,
shadowRadius: 4,
elevation: 2,
},
tabButtonText: {
color: "#888",
fontWeight: "500",
fontSize: 14,
},
activeTabButtonText: {
color: "#fff",
fontWeight: "bold",
},
productInfoContainer: {
flexDirection: "column",
alignItems: "stretch",
justifyContent: "center",
backgroundColor: "#0766e9",
borderBottomLeftRadius: 10,
borderBottomRightRadius: 10,
paddingHorizontal: 16,
paddingTop: 16,
},
productImageUploadSection: {
flexDirection: "column",
alignItems: "stretch",
justifyContent: "flex-start",
maxWidth: "100%",
height: 300,
paddingBottom: 24,
borderBottomLeftRadius: 10,
borderBottomRightRadius: 10,
},
productInfoContainer1: {
flexDirection: "column",
alignItems: "center",
justifyContent: "flex-start",
paddingTop: 24,
paddingBottom: 22,
paddingLeft: 29,
paddingRight: 29,
},
productImageIcon: {
width: 60,
height: 60,
borderWidth: 0,
},
productQuoteContainer: {
flexDirection: "column",
alignItems: "center",
justifyContent: "flex-start",
marginTop: 15,
},
productInfoHeading: {
fontWeight: "900",
fontSize: 16,
lineHeight: 20,
color: "white",
},
productInfoMessage1: {
marginTop: 7,
fontWeight: "400",
fontSize: 12,
lineHeight: 16,
color: "white",
textAlign: "center",
},
photoUploadContainer: {
flexDirection: "column",
alignItems: "stretch",
justifyContent: "center",
height: widthUtils(80, 80).height,
paddingRight: 29,
paddingLeft: 29,
},
photoUploadContainer1: {
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
borderRadius: 30,
shadowColor: "#fd5000",
shadowOffset: { width: 2, height: 3 },
shadowOpacity: 0.2,
shadowRadius: 4,
elevation: 3,
overflow: "hidden",
height: "100%",
},
gradientBackground: {
width: "100%",
height: "100%",
justifyContent: "center",
alignItems: "center",
},
photoUploadPromptContainer: {
flexDirection: "column",
alignItems: "flex-end",
justifyContent: "center",
height: "100%",
paddingRight: 20,
},
centerHeadingBoldWhite: {
fontWeight: "700",
fontSize: 16,
lineHeight: 20,
color: "#002FA7",
textAlign: "right",
},
headerGradient: {
paddingBottom: 20,
},
labelItemTextThree: {
position: "absolute",
color: "#808080",
fontSize: 14,
fontWeight: "600",
width: "33%",
textAlign: "center",
paddingHorizontal: 10,
flexWrap: "wrap",
lineHeight: 16,
right: 0,
top: "50%",
transform: [{ translateY: -8 }],
},
cardContainerWithButtons: {
flexDirection: "column",
alignItems: "stretch",
justifyContent: "center",
paddingVertical: 20,
paddingHorizontal: 16,
paddingBottom: 38,
backgroundColor: "white",
borderBottomLeftRadius: 10,
borderBottomRightRadius: 10,
},
productCardContainer: {
flexDirection: "column",
gap: 18,
alignItems: "stretch",
justifyContent: "flex-start",
paddingTop: 26,
paddingRight: 28,
paddingBottom: 23,
paddingLeft: 24,
backgroundColor: "#f2f6ff",
},
productCardContainer1: {
flexDirection: "row",
alignItems: "flex-end",
justifyContent: "flex-start",
},
articleThumbnailContainer: {
width: 76,
height: 76,
borderWidth: 0,
borderRadius: 5,
resizeMode: "cover",
},
articleTitleContainer: {
width: widthUtils(221, 221).width,
marginLeft: 11,
},
elegantText: {
padding: 0,
margin: 0,
fontFamily: "PingFang SC",
fontSize: 12,
fontWeight: "500",
color: "#676b74",
},
articleTitleContainer1: {
width: "100%",
height: 50,
marginTop: 9,
backgroundColor: "white",
},
flexRowWithContent: {
flexDirection: "row",
alignItems: "center",
justifyContent: "flex-start",
},
centerColumnWithText: {
flexDirection: "column",
alignItems: "stretch",
justifyContent: "center",
width: widthUtils(152, 152).width,
},
quantityLabelTextStyle: {
padding: 0,
margin: 0,
fontFamily: "PingFang SC",
fontSize: 12,
fontWeight: "500",
color: "#676b74",
},
highlightedText: {
fontFamily: "PingFang SC",
fontSize: 12,
fontWeight: "500",
color: "#fe1e00",
},
quantityContainer: {
height: 40,
backgroundColor: "white",
},
matiereContainer: {
flexDirection: "column",
alignItems: "stretch",
justifyContent: "center",
width: widthUtils(151, 151).width,
marginLeft: 7,
},
linkContainer: {},
contentWrapper: {
width: "100%",
height: 70,
backgroundColor: "white",
},
buttonGroupConfirmation: {
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
marginTop: 26,
marginRight: 14,
marginLeft: 9,
},
cancelButtonStyle: {
width: 160,
minWidth: 160,
height: 46,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#f2f3f5",
borderRadius: 43,
},
confirmButtonStyle: {
width: 160,
minWidth: 160,
height: 46,
marginLeft: 19,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#002fa7",
borderRadius: 43,
},
cancelButtonText: {
fontFamily: "Source Han Sans CN",
fontSize: 16,
fontWeight: "500",
lineHeight: 22,
color: "#333333",
},
confirmButtonText: {
fontFamily: "Source Han Sans CN",
fontSize: 16,
fontWeight: "500",
lineHeight: 22,
color: "white",
},
imagePickerOverlay: {
flex: 1,
backgroundColor: "rgba(0, 0, 0, 0.5)",
justifyContent: "flex-end",
},
imagePickerContent: {
backgroundColor: "#fff",
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
paddingTop: 20,
},
imagePickerOption: {
flexDirection: "row",
alignItems: "center",
paddingVertical: 16,
paddingHorizontal: 20,
},
imagePickerText: {
fontSize: fontSize(16),
marginLeft: 12,
color: "#333",
},
imagePickerDivider: {
height: 1,
backgroundColor: "#f0f0f0",
marginHorizontal: 20,
},
imagePickerCancelButton: {
alignItems: "center",
paddingVertical: 16,
marginTop: 8,
borderTopWidth: 1,
borderTopColor: "#f0f0f0",
},
imagePickerCancelText: {
fontSize: fontSize(16),
color: "#999",
},
disabledButton: {
opacity: 0.7,
},
loadingContainer: {
padding: 16,
alignItems: "center",
justifyContent: "center",
},
loadingText: {
color: "#888",
fontSize: 14,
},
noMoreText: {
textAlign: "center",
color: "#888",
fontSize: 14,
padding: 16,
},
emptyContainer: {
flex: 1,
padding: 32,
alignItems: "center",
justifyContent: "center",
backgroundColor: "white",
margin: 16,
borderRadius: 16,
},
emptyText: {
color: "#888",
fontSize: 16,
},
});