import { View, Text, ScrollView, Image, useWindowDimensions, StyleSheet, Pressable, Platform, Linking, ActivityIndicator, Alert } from 'react-native'; import React, { useEffect, useMemo, useState } from 'react'; import { SceneMap, TabBar, TabView } from 'react-native-tab-view'; import NormalButton from '../global/normal_button'; import { router, 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 = () => ( Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident ); 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 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(''); 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]); const formatDistance = (distanceInMeters: number): string => { if (distanceInMeters < 1000) { return `${Math.round(distanceInMeters)}米`; } else { const distanceInKm = distanceInMeters / 1000; return `${distanceInKm.toFixed(1)}公里`; } }; const handleNavigationPress = () => { if (coordinates) { const { StationLat, StationLng } = coordinates; const googleMapsUrl = `google.navigation:q=${StationLat},${StationLng}`; 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} 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} /> )} 收費 $20 每15分鐘 ${price} 每度電 充電站資訊 ); }; export default ResultDetailPageComponent; const styles = StyleSheet.create({ text: { fontWeight: 300, color: '#000000' } });