//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, 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; } 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(); }, []); // Memoize the route components // const FirstRoute = React.useMemo( // () => // React.memo(() => ( // // {isLoading ? ( // // // // ) : ( // } // estimatedItemSize={10} // /> // )} // // )), // [isLoading, tabItems] // ); //i unmemoed it const FirstRoute = () => ( {isLoading ? ( ) : ( item.actual_total_power && item.actual_total_power !== 0)} renderItem={({ item }) => } estimatedItemSize={10} /> )} ); const SecondRoute = React.useMemo( () => React.memo(() => ( item.actual_total_power && item.actual_total_power > 1 )} renderItem={({ item }) => } estimatedItemSize={20} /> )), [completedReservationTabItems] ); // Use useCallback for renderScene // const renderScene = React.useCallback( // SceneMap({ // firstRoute: FirstRoute, // secondRoute: SecondRoute // }), // [FirstRoute, SecondRoute] // ); //uncallbacked it const renderScene = SceneMap({ firstRoute: FirstRoute, secondRoute: SecondRoute }); // const routes = React.useMemo( // () => [ // { key: 'firstRoute', title: titles[0] }, // { key: 'secondRoute', title: titles[1] } // ], // [titles] // ); const routes = [ { key: 'firstRoute', title: titles[0] }, { key: 'secondRoute', title: titles[1] } ]; const [index, setIndex] = React.useState(0); // const renderTabBar = React.useCallback( // (props: any) => ( // ( // // {route.title} // // )} // indicatorStyle={{ // backgroundColor: '#025c72' // }} // style={{ // backgroundColor: 'white', // borderColor: '#DBE4E8', // elevation: 0, // marginHorizontal: 15, // borderBottomWidth: 0.5 // }} // /> // ), // [] // ); const renderTabBar = (props: any) => ( ( {route.title} )} indicatorStyle={{ backgroundColor: '#025c72' }} style={{ backgroundColor: 'white', borderColor: '#DBE4E8', elevation: 0, marginHorizontal: 15, borderBottomWidth: 0.5 }} /> ); return ( ); }; // Separate memoedTabItem component // const TabItem = React.memo( // ({ 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 ( // // // // // {`${item.date} - ${item.time}`} // // // {item.chargeStationName} // // // {item.chargeStationAddress} // // // // {distance !== null ? formatDistance(distance) : ''} // // // ); // } // ); 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 }, 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 } });