import { View, Text, ScrollView, Image, useWindowDimensions, StyleSheet, Pressable, Platform, Linking, ActivityIndicator, Alert } from 'react-native'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { SceneMap, TabBar, TabView } from 'react-native-tab-view'; import NormalButton from '../global/normal_button'; import { router, useFocusEffect, useLocalSearchParams } from 'expo-router'; import { CheckMarkLogoSvg, DirectionLogoSvg, PreviousPageSvg } from '../global/SVG'; import { SafeAreaView } from 'react-native-safe-area-context'; import { chargeStationService } from '../../service/chargeStationService'; import * as Location from 'expo-location'; import { calculateDistance } from '../global/distanceCalculator'; interface ChargingStationTabViewProps { titles: string[]; } interface StationCoordinates { StationLat: number; StationLng: number; } const ChargingStationTabView: React.FC = ({ titles }) => { const layout = useWindowDimensions(); //tab 1 const FirstRoute = () => ( 由於充電站車流眾多, 敬請客戶務必於預約時間的十五分鐘內到達充電站。 若客戶逾時超過15分鐘,系統將視作自動放棄預約,客戶需要重新預約一次。 本公司有權保留全數費用,恕不退還。 ); //tab 2 const SecondRoute = () => ( ); const renderScene = SceneMap({ firstRoute: FirstRoute, secondRoute: SecondRoute }); const [routes] = React.useState([ { key: 'firstRoute', title: titles[0] }, { key: 'secondRoute', title: titles[1] } ]); const [index, setIndex] = React.useState(0); const renderTabBar = (props: any) => ( ( {route.title} )} indicatorStyle={{ backgroundColor: '#000000', height: 1 }} style={{ backgroundColor: 'white', elevation: 0, marginHorizontal: 15, borderBottomWidth: 0.5 }} /> ); return ( ); }; const ResultDetailPageComponent = () => { const params = useLocalSearchParams(); const chargeStationID = params.chargeStationID as string; const chargeStationName = params.chargeStationName as string; const chargeStationAddress = params.chargeStationAddress as string; const availableConnectorsFromParams = params.availableConnectors; const imageSource = params.imageSource; const stationLng = params.stationLng as string; const stationLat = params.stationLat as string; const [isLoading, setIsLoading] = useState(true); // const chargeStationLat = params.chargeStationLat as string; // const chargeStationLng = params.chargeStationLng as string; const [currentLocation, setCurrentLocation] = useState(null); const [distance, setDistance] = useState(null); const [coordinates, setCoordinates] = useState(null); const [price, setPrice] = useState(''); const [availableConnectors, setAvailableConnectors] = useState( availableConnectorsFromParams ? Number(availableConnectorsFromParams) : null ); const [newAvailableConnectors, setNewAvailableConnectors] = useState([]); 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(); }, []); // useEffect(() => { // const getDistance = async () => { // if (currentLocation) { // let stationLat, stationLng; // if (params.chargeStationLat && params.chargeStationLng) { // stationLat = Number(params.chargeStationLat); // stationLng = Number(params.chargeStationLng); // } else if (coordinates) { // stationLat = coordinates.StationLat; // stationLng = coordinates.StationLng; // } else { // console.log('No station coordinates available'); // return; // } // try { // const distance = await calculateDistance(stationLat, stationLng, currentLocation); // setDistance(formatDistance(distance)); // } catch (error) { // console.error('Error calculating distance:', error); // } // } // }; // getDistance(); // }, [params.chargeStationLat, params.chargeStationLng, coordinates, currentLocation]); useEffect(() => { const fetchPrice = async () => { try { const price = await chargeStationService.fetchChargeStationPrice(chargeStationID); setPrice(price); } catch (error) { console.error('Error fetching price:', error); } }; fetchPrice(); }, []); // console.log(chargeStationLat, chargeStationLng); // const memoizedCoordinates = useMemo(() => { // if (params.chargeStationLat && params.chargeStationLng) { // return { // StationLat: parseFloat(params.chargeStationLat as string), // StationLng: parseFloat(params.chargeStationLng as string) // }; // } // return null; // }, [params.chargeStationLat, params.chargeStationLng]); // useEffect(() => { // const fetchCoordinates = async () => { // // If coordinates are provided in params, use them // if (memoizedCoordinates) { // setCoordinates(memoizedCoordinates); // } else { // // If not provided, fetch from API // try { // const response = await chargeStationService.fetchChargeStations(); // if (response && response.length > 0) { // const station = response.find((s) => s.StationID === chargeStationID); // if (station) { // setCoordinates({ // StationLat: station.StationLat, // StationLng: station.StationLng // }); // } // } // } catch (error) { // console.error('Error fetching coordinates:', error); // } // } // }; // fetchCoordinates(); // }, [chargeStationID, memoizedCoordinates]); // useEffect(() => { // const fetchAvailableConnectors = async () => { // // Skip fetching if we already have the value from params // if (availableConnectorsFromParams) return; // try { // const connectors = await chargeStationService.fetchAvailableConnectors(chargeStationID); // console.log('connectors number from resultDetailPage', connectors); // setAvailableConnectors(connectors); // } catch (error) { // console.error('Error fetching available connectors:', error); // setAvailableConnectors(null); // } // }; // fetchAvailableConnectors(); // }, [chargeStationID, availableConnectorsFromParams]); useFocusEffect( useCallback(() => { setIsLoading(true); let isMounted = true; // Simple cleanup flag const fetchAllConnectors = async () => { try { const newAvailableConnectors = await chargeStationService.NewfetchAvailableConnectors(); // Only update state if component is still mounted if (isMounted) { setNewAvailableConnectors(newAvailableConnectors); } } catch (error) { console.error('Fetch error:', error); } }; fetchAllConnectors(); setIsLoading(false); // Simple cleanup - prevents state updates if component unmounts return () => { isMounted = false; }; }, []) // Add any missing dependencies here if needed ); // const formatDistance = (distanceInMeters: number): string => { // if (distanceInMeters < 1000) { // return `${Math.round(distanceInMeters)}米`; // } else { // const distanceInKm = distanceInMeters / 1000; // return `${distanceInKm.toFixed(1)}公里`; // } // }; const handleNavigationPress = (StationLat: string, StationLng: string) => { console.log('starting navigation press in resultDetail', StationLat, StationLng); if (StationLat && StationLng) { const label = encodeURIComponent(chargeStationName); const googleMapsUrl = `https://www.google.com/maps/search/?api=1&query=${StationLat},${StationLng}`; // Fallback URL for web browser const webUrl = `https://www.google.com/maps/dir/?api=1&destination=${StationLat},${StationLng}`; Linking.canOpenURL(googleMapsUrl) .then((supported) => { if (supported) { Linking.openURL(googleMapsUrl); } else { Linking.openURL(webUrl).catch((err) => { console.error('An error occurred', err); Alert.alert( 'Error', "Unable to open Google Maps. Please make sure it's installed on your device.", [{ text: 'OK' }], { cancelable: false } ); }); } }) .catch((err) => console.error('An error occurred', err)); } }; const handleNavigaationPress = () => { const latitude = chargeStationLat; const longitude = chargeStationLng; console.log('latitude', latitude); console.log('longitude', longitude); const label = encodeURIComponent(chargeStationName); // Google Maps App URL const googleMapsUrl = `https://www.google.com/maps/search/?api=1&query=${latitude},${longitude}`; // Fallback URL for web browser const webUrl = `https://www.google.com/maps/dir/?api=1&destination=${latitude},${longitude}`; Linking.canOpenURL(googleMapsUrl) .then((supported) => { if (supported) { Linking.openURL(googleMapsUrl); } else { Linking.openURL(webUrl).catch((err) => { console.error('An error occurred', err); Alert.alert( 'Error', "Unable to open Google Maps. Please make sure it's installed on your device.", [{ text: 'OK' }], { cancelable: false } ); }); } }) .catch((err) => console.error('An error occurred', err)); }; const handleAddBooking = () => { if (coordinates) { router.push({ pathname: 'makingBookingPage', params: { chargeStationID: chargeStationID, chargeStationAddress: chargeStationAddress, chargeStationName: chargeStationName, chargeStationLat: coordinates.StationLat.toString(), chargeStationLng: coordinates.StationLng.toString() } }); } }; return ( { if (router.canGoBack()) { router.back(); } else { router.replace('./'); } }} > {chargeStationName} {chargeStationAddress} 路線 } onPress={() => handleNavigationPress(stationLat, stationLng)} extendedStyle={{ backgroundColor: '#E3F2F8', borderRadius: 61, paddingHorizontal: 20, paddingVertical: 6 }} /> Walk-In {/* {distance} */} {/* {coordinates ? ( + 新增預約 } // onPress={() => console.log('ab')} onPress={handleAddBooking} /> ) : ( } // onPress={() => console.log('ab')} onPress={handleAddBooking} /> )} */} 收費 ${price} 每度電 現時可用充電槍數目 {isLoading ? ( Loading... ) : ( // { newAvailableConnectors.find( (station: any) => station.stationID === chargeStationID )?.availableConnectors } )} 充電站資訊 ); }; export default ResultDetailPageComponent; const styles = StyleSheet.create({ text: { fontWeight: 300, color: '#000000' } });