//the size of the TabView will follow its parent-container's size. import * as React from 'react'; import * as Location from 'expo-location'; import { View, Text, useWindowDimensions, Dimensions, StyleSheet, Image, ImageSourcePropType, ActivityIndicator, Pressable } from 'react-native'; import { TabView, SceneMap, TabBar } from 'react-native-tab-view'; import { FlashList } from '@shopify/flash-list'; import { useEffect, useState } from 'react'; import { calculateDistance } from './distanceCalculator'; import { router } from 'expo-router'; export interface TabItem { imgURL: ImageSourcePropType; date: string; time: string; chargeStationName: string; chargeStationAddress: string; stationLat: string | number; stationLng: string | number; distance: string; format_order_id: string; actual_total_power?: number; actual_end_time?: string; actual_fee?: number; current_price?: number; } interface TabViewComponentProps { titles: string[]; tabItems: TabItem[]; completedReservationTabItems: TabItem[]; isLoading?: boolean; } const TabViewComponent: React.FC = ({ titles, isLoading, tabItems, completedReservationTabItems }) => { const layout = useWindowDimensions(); const [currentLocation, setCurrentLocation] = useState(null); useEffect(() => { const getCurrentLocation = async () => { let { status } = await Location.requestForegroundPermissionsAsync(); if (status !== 'granted') { console.error('Permission to access location was denied'); return; } let location = await Location.getLastKnownPositionAsync({}); setCurrentLocation(location); }; getCurrentLocation(); }, []); // 修复 FirstRoute 组件 const FirstRoute = ({ tabItems, isLoading, currentLocation }: { tabItems: TabItem[]; isLoading?: boolean; currentLocation: Location.LocationObject | null }) => ( {isLoading ? ( ) : ( item?.actual_total_power && item?.actual_total_power !== 0)} renderItem={({ item }) => } keyExtractor={(item, index) => index.toString()} /> )} ); // 修复 SecondRoute 组件 const SecondRoute = ({ completedReservationTabItems, currentLocation }: { completedReservationTabItems: TabItem[]; currentLocation: Location.LocationObject | null }) => ( item.actual_total_power && item.actual_total_power > 1 )} renderItem={({ item }) => } keyExtractor={(item, index) => index.toString()} /> ); // 更新 renderScene const renderScene = SceneMap({ firstRoute: () => , secondRoute: () => }); const routes = [ { key: 'firstRoute', title: titles[0] }, { key: 'secondRoute', title: titles[1] } ]; const [index, setIndex] = React.useState(0); const renderTabBar = (props: any) => ( ); return ( ); }; const TabItem = ({ item, currentLocation }: { item: TabItem; currentLocation: Location.LocationObject | null }) => { const [distance, setDistance] = useState(null); useEffect(() => { const getDistance = async () => { if (currentLocation) { const result = await calculateDistance( Number(item.stationLat), Number(item.stationLng), currentLocation ); setDistance(result); } }; getDistance(); }, [currentLocation, item.stationLat, item.stationLng]); const formatDistance = (distanceInMeters: number): string => { if (distanceInMeters < 1000) { return `${Math.round(distanceInMeters)}米`; } else { const distanceInKm = distanceInMeters / 1000; return `${distanceInKm.toFixed(1)}公里`; } }; return ( { console.log(item.format_order_id); }} > {`${item.date}日 - ${item.time}至${item.actual_end_time}`} 已充電度數:{' '} {item.actual_total_power ? item.actual_total_power % 1 === 0 ? item.actual_total_power : item.actual_total_power.toFixed(1) : ''} 應付金額:{' '} {item.actual_fee !== undefined && item.actual_fee !== null ? item.actual_fee <= 0 ? '$0' : item.actual_fee % 1 === 0 ? `$${item.actual_fee}` : `$${item.actual_fee.toFixed(1)}` : ''} 每度電金額: ${item.current_price} {item.chargeStationName} ); }; export default TabViewComponent; const styles = StyleSheet.create({ container: { flexDirection: 'row', width: '100%', flex: 1, alignItems: 'center' }, image: { width: 100, height: 100, margin: 15, borderRadius: 10 }, textContainer: { flex: 1, flexDirection: 'column', gap: 8, marginTop: 20, marginRight: 8 // Add right margin to prevent text from touching the edge } });