import React, { useState, useEffect } from 'react'; import { View, Text, Image, TouchableOpacity, StyleSheet, ImageBackground, ActivityIndicator, SafeAreaView, StatusBar, Platform, Modal, TextInput, FlatList } from 'react-native'; import BackIcon from '../../components/BackIcon'; import fontSize from '../../utils/fontsizeUtils'; import widthUtils from '../../utils/widthUtils'; import { useNavigation } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { settingApi } from '../../services/api/setting'; import { CountryList } from '../../constants/countries'; import { useTranslation } from 'react-i18next'; // Pre-require images to avoid dynamic require issues const MARITIME_BACKGROUND = require('../../../assets/img/image_f67fe9bc.png'); const AIRWAY_BACKGROUND = require('../../../assets/img/feijiback.png'); type RootStackParamList = { Home: undefined; ShippingDetails: undefined; Main: undefined; // Add other screens as needed }; type NavigationProp = NativeStackNavigationProp; export const ShippingDetailsSection = () => { const { t } = useTranslation(); const [shippingMethod, setShippingMethod] = useState('maritime'); // 'maritime' or 'airway' const [isLoading, setIsLoading] = useState(true); const [showCountryModal, setShowCountryModal] = useState(false); const [countries, setCountries] = useState([]); const [selectedCountry, setSelectedCountry] = useState(null); const [parcelVolume, setParcelVolume] = useState(''); const [isCalculating, setIsCalculating] = useState(false); const [showResultModal, setShowResultModal] = useState(false); const [shippingFee, setShippingFee] = useState(null); const [shippingCurrency, setShippingCurrency] = useState(''); const navigation = useNavigation(); useEffect(() => { const preloadImages = async () => { try { await Promise.all([ Image.prefetch(Image.resolveAssetSource(MARITIME_BACKGROUND).uri), Image.prefetch(Image.resolveAssetSource(AIRWAY_BACKGROUND).uri) ]); setIsLoading(false); } catch (error) { console.error('Error preloading images:', error); setIsLoading(false); } }; const fetchCountries = async () => { try { const response = await settingApi.getCountryList(); setCountries(response); } catch (error) { console.error('Error fetching countries:', error); } }; preloadImages(); fetchCountries(); }, []); const handleShippingMethodChange = (method: 'maritime' | 'airway') => { setShippingMethod(method); }; const handleCountrySelect = (country: CountryList) => { setSelectedCountry(country); setShowCountryModal(false); }; // Get background image based on shipping method const getBackgroundImage = () => { return shippingMethod === 'maritime' ? MARITIME_BACKGROUND : AIRWAY_BACKGROUND; }; const handleCalculateShipping = async () => { if (!selectedCountry || !parcelVolume) { // TODO: Show error message return; } setIsCalculating(true); try { const volume = parseFloat(parcelVolume); if (isNaN(volume)) { // TODO: Show error message for invalid input return; } const shippingData = { weight_kg: shippingMethod === 'airway' ? volume : 0, volume_m3: shippingMethod === 'maritime' ? volume : 0, country_code: selectedCountry.country }; const response = await settingApi.getShippingFee(shippingData); const fee = shippingMethod === 'maritime' ? response.estimated_shipping_fee_sea : response.estimated_shipping_fee_air; setShippingFee(fee); setShippingCurrency(response.currency); setShowResultModal(true); } catch (error) { console.error('Error calculating shipping fee:', error); // TODO: Show error message } finally { setIsCalculating(false); } }; const renderCountryItem = ({ item }: { item: CountryList }) => ( handleCountrySelect(item)} > {item.name} {selectedCountry?.country === item.country && ( )} ); const renderResultModal = () => ( setShowResultModal(false)} > {t('banner.shipping.calculation_result')} {t('banner.shipping.estimated_fee')}: {shippingFee?.toFixed(2)} {shippingCurrency} setShowResultModal(false)} > {t('banner.shipping.confirm')} ); return ( {isLoading ? ( ) : ( { navigation.goBack(); }} > {t('banner.shipping.fee')} {/* Calculator Form */} {/* Shipping Method Selection */} {/* Maritime Option */} handleShippingMethodChange('maritime')} > {t('banner.shipping.maritime')} {/* Airway Option */} handleShippingMethodChange('airway')} > {t('banner.shipping.airway')} {/* Parcel Volume Form */} {/* Country Selection */} {t('banner.shipping.select_country')} setShowCountryModal(true)} > {selectedCountry ? selectedCountry.name : t('banner.shipping.select_country')} {/* Parcel Volume Input */} {t('banner.shipping.parcel_volume')} { // 只允许输入数字和小数点 const numericValue = text.replace(/[^0-9.]/g, ''); // 确保只有一个小数点 const parts = numericValue.split('.'); if (parts.length > 2) { setParcelVolume(parts[0] + '.' + parts.slice(1).join('')); } else { setParcelVolume(numericValue); } }} placeholder={t('banner.shipping.enter_parcel_volume')} keyboardType="decimal-pad" placeholderTextColor="#807e7e" /> {shippingMethod === 'maritime' ? 'm³' : 'kg'} {/* Submit Button */} {isCalculating ? ( ) : ( {t('banner.shipping.calculate_shipping')} )} )} {/* Country Selection Modal */} setShowCountryModal(false)} > {t('banner.shipping.select_country_modal_title')} setShowCountryModal(false)}> {t('banner.shipping.close')} item.country.toString()} style={styles.countryList} /> {renderResultModal()} ); }; const styles = StyleSheet.create({ safeArea: { flex: 1, backgroundColor: '#005EE4', }, safeAreaContent: { flex: 1, paddingTop: 0, }, container: { width: '100%', flex: 1, }, backgroundImage: { width: '100%', height: '100%', resizeMode: 'cover', }, contentContainer: { flex: 1, padding: 15, }, timeShippingSection: { flexDirection: 'column', }, timeAndImageContainer: { flexDirection: 'row', gap: 8, alignItems: 'center', justifyContent: 'space-between', paddingLeft: 36, }, timeDisplay: { width: widthUtils(42, 42).width, fontSize: fontSize(17), fontFamily: 'SF Pro', fontWeight: '600', color: 'white', textAlign: 'center', }, timeImageContainer: { width: widthUtils(54, 154).width, height: widthUtils(54, 154).height, }, shippingCostContainer: { flexDirection: 'row', alignItems: 'center', marginTop: 20, justifyContent: 'center', }, svgContainer: { width: widthUtils(18, 18).width, height: widthUtils(18, 18).height, position: 'absolute', left: 0, }, shippingCostLabelTextStyle: { fontSize: fontSize(20), lineHeight: 22, fontFamily: 'Microsoft YaHei UI', fontWeight: '700', color: 'white', textAlign: 'center', textTransform: 'capitalize', width: '100%', }, shippingCalculatorContainer: { marginTop: widthUtils(100,100).height, paddingTop: 18, paddingRight: 20, paddingBottom: 28, paddingLeft: 20, backgroundColor: 'white', borderRadius: 5, justifyContent: 'center', }, flexColumnCenteredWithSelect: { flexDirection: 'column', justifyContent: 'center', }, shippingMethodContainer: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', height: widthUtils(80, 80).height, paddingRight: 10, paddingLeft: 10, backgroundColor: '#f2f6ff', borderRadius: 5, }, maritimeInfoBox: { height: widthUtils(60, 60).height, paddingRight: 19, paddingLeft: 20, backgroundColor: '#f2f6ff', borderRadius: 5, justifyContent: 'center', alignItems: 'center', }, airwayInfoContainer: { height: widthUtils(60, 60).height, paddingRight: 24, paddingLeft: 25, marginLeft: 10, backgroundColor: '#f2f6ff', borderRadius: 5, justifyContent: 'center', alignItems: 'center', }, activeShippingMethod: { backgroundColor: '#005EE4', }, svgContainer1: { width: widthUtils(32, 32).width, height: widthUtils(32, 32).height, }, maritimeHeadingStyle: { marginTop: -5, fontSize: fontSize(14), fontFamily: 'Segoe UI', fontWeight: '700', color: 'white', textTransform: 'capitalize', }, svgContainer2: { width: widthUtils(24, 24).width, height: widthUtils(24, 24).height, }, flightModeLabel: { marginTop: -2, fontSize: fontSize(14), fontFamily: 'Segoe UI', fontWeight: '400', color: '#747474', textTransform: 'capitalize', }, parcelVolumeFormContainer: { marginTop: 16, backgroundColor: 'white', borderWidth: 1, borderColor: '#dbdce0', }, optionContainer: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', height: widthUtils(60, 60).height, paddingRight: 6, paddingLeft: 8, backgroundColor: 'white', borderWidth: 1, borderColor: '#dbdce0', borderTopLeftRadius: 5, borderTopRightRadius: 5, }, pingfangTextSelect: { fontSize: fontSize(12), fontFamily: 'PingFang SC', fontWeight: '500', color: '#646472', }, iconSelectDropdown: { width: widthUtils(24, 24).width, height: widthUtils(24, 24).height, marginLeft: 10, }, parcelVolumeContainer: { width: '100%', paddingTop: 6, paddingRight: 8, paddingBottom: 10, paddingLeft: 8, marginTop: -1, backgroundColor: 'white', borderWidth: 1, borderColor: '#dbdce0', borderBottomLeftRadius: 5, borderBottomRightRadius: 5, }, parcelVolumeLabel: { fontSize: fontSize(12), fontFamily: 'PingFang SC', fontWeight: '600', color: '#646472', }, volumeInputContainer: { flexDirection: 'row', gap: 8, alignItems: 'center', justifyContent: 'space-between', width: '100%', }, volumePromptTextStyle: { fontSize: fontSize(16), lineHeight: 22, fontFamily: 'PingFang SC', fontWeight: '400', color: '#807e7e', }, unitText: { fontSize: fontSize(16), lineHeight: 22, fontFamily: 'PingFang SC', fontWeight: '600', color: '#1c284e', }, primaryButton: { width:'100%', height: widthUtils(50, 50).height, marginTop: 34, backgroundColor: '#002fa7', borderRadius: 25, justifyContent: 'center', alignItems: 'center', }, backButton: { padding: 10, borderRadius: 20, zIndex: 10, }, loadingContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#f2f6ff', }, modalContainer: { flex: 1, backgroundColor: 'rgba(0, 0, 0, 0.5)', justifyContent: 'flex-end', }, modalContent: { backgroundColor: 'white', borderTopLeftRadius: 20, borderTopRightRadius: 20, paddingBottom: Platform.OS === 'ios' ? 34 : 20, maxHeight: '80%', }, modalHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', padding: 16, borderBottomWidth: 1, borderBottomColor: '#dbdce0', }, modalTitle: { fontSize: fontSize(18), fontWeight: '600', color: '#1c284e', }, modalCloseButton: { fontSize: fontSize(16), color: '#005EE4', }, countryList: { paddingHorizontal: 16, }, countryItem: { paddingVertical: 16, borderBottomWidth: 1, borderBottomColor: '#dbdce0', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', }, countryItemText: { fontSize: fontSize(16), color: '#1c284e', }, checkIcon: { fontSize: fontSize(20), color: '#005EE4', fontWeight: 'bold', }, volumeInput: { flex: 1, fontSize: fontSize(16), color: '#1c284e', padding: 0, }, disabledButton: { opacity: 0.6, }, resultModalContainer: { flex: 1, backgroundColor: 'rgba(0, 0, 0, 0.5)', justifyContent: 'center', alignItems: 'center', }, resultModalContent: { backgroundColor: 'white', borderRadius: 10, padding: 20, width: '80%', alignItems: 'center', }, resultTitle: { fontSize: fontSize(18), fontWeight: '600', color: '#1c284e', marginBottom: 15, }, resultText: { fontSize: fontSize(16), color: '#1c284e', marginBottom: 20, }, resultCloseButton: { backgroundColor: '#005EE4', paddingVertical: 10, paddingHorizontal: 30, borderRadius: 5, }, resultCloseButtonText: { color: 'white', fontSize: fontSize(16), fontWeight: '600', }, });