import React, { useEffect } from 'react'; import { IcClose, IcFilter, IcShare, IcLocation, IcNavBack, IcNavigation, InfoCircleIcon, } from '../../res/icons'; import { useMapStrings } from '../../hooks/useMapStrings'; import { isCurrentLocationRoutePoint, type RouteInfo, type RoutePoint, type RouteStep } from '../../hooks/useRouting'; import { useMapBackHandler } from '../../hooks/useMapBackHandler'; import { useMapStore } from '../../state'; import { formatShortDisplayAddress, stripHtml } from '../../utils/placeUtils'; type ModeTab = { key: string; mode: google.maps.TravelMode | undefined; icon: React.ComponentType<{ size?: number; className?: string; strokeWidth?: number; fill?: string }>; label: string; subLabel: string; }; export const RouteDetailSheet: React.FC<{ routeSheetHeight: number; isRouteDragging: boolean; routeSheetPointerHandlers: { onPointerDown: React.PointerEventHandler; onPointerMove: React.PointerEventHandler; onPointerUp: React.PointerEventHandler; onPointerCancel: React.PointerEventHandler; }; selectedTransportMode: 'driving' | 'transit' | 'walking' | 'cycling'; setSelectedTransportMode: (m: 'driving' | 'transit' | 'walking' | 'cycling') => void; modes: ModeTab[]; modeDurations: Record; routeError: string | null; routeInfo: RouteInfo | null; isCollapsed: boolean; isExpanded: boolean; destination: RoutePoint; routeSteps: RouteStep[]; origin: { lat: number; lng: number; name: string } | null; mapInstance: google.maps.Map | null; clearRoutePolyline: () => void; setRouteEndLocation: (v: { lat: number; lng: number } | null) => void; setRouteInfo: (v: RouteInfo | null) => void; setOrigin: (v: RoutePoint | null) => void; setTravelMode: (m: google.maps.TravelMode) => void; replaceState: (state: Record) => void; setIsNavigating: (v: boolean) => void; }> = ({ routeSheetHeight, isRouteDragging, routeSheetPointerHandlers, selectedTransportMode, setSelectedTransportMode, modes, modeDurations, routeError, routeInfo, isCollapsed, isExpanded, destination, routeSteps, origin, mapInstance, clearRoutePolyline, setRouteEndLocation, setRouteInfo, setOrigin, setTravelMode, replaceState, setIsNavigating, }) => { const setRouteSheetOpen = useMapStore((s) => s.setRouteSheetOpen); const s = useMapStrings(); const shortDestinationAddress = formatShortDisplayAddress(destination.address); const lastRouteStep = routeSteps[routeSteps.length - 1]; const lastRouteInstruction = stripHtml(lastRouteStep?.instructions || ''); const destinationSideHint = (() => { const matched = lastRouteInstruction.match(/目的地在[左右]侧|destination (?:will be|is) on (?:the )?(?:left|right)/i); return matched?.[0] ?? null; })(); const isArrivalStep = Boolean(lastRouteStep) && ( lastRouteInstruction === s.route_arrive_destination || /arrive at destination/i.test(lastRouteInstruction) || Boolean(destinationSideHint) ); const visibleRouteSteps = isArrivalStep ? routeSteps.slice(0, -1) : routeSteps; useEffect(() => { setRouteSheetOpen(true); return () => setRouteSheetOpen(false); }, [setRouteSheetOpen]); const getRouteLabelText = (routeLabels?: string[]) => { const labels = new Set(routeLabels || []); if (labels.has('FUEL_EFFICIENT')) return s.route_fuel_efficient_route; if (labels.has('SHORTER_DISTANCE')) return s.route_shorter_distance_route; if (labels.has('DEFAULT_ROUTE_ALTERNATE')) return s.route_alternative_route; if (labels.has('DEFAULT_ROUTE')) return s.route_recommended_route; return s.route_recommended_route; }; const handleCloseRoute = () => { clearRoutePolyline(); setRouteEndLocation(null); setRouteInfo(null); setOrigin(null); setTravelMode('DRIVING' as google.maps.TravelMode); replaceState({}); }; useMapBackHandler( () => { handleCloseRoute(); return true; }, { priority: 500 }, ); return (
{selectedTransportMode === 'driving' ? s.route_driving : selectedTransportMode === 'transit' ? s.route_transit : selectedTransportMode === 'walking' ? s.route_walking : s.route_cycling}
{!isCollapsed && (
{modes.map((m) => { const duration = modeDurations[m.mode!] || ''; const isDisabled = duration === 'N/A'; return ( ); })}
)} {routeError ? (
{s.route_not_found}
{s.route_not_found_detail}
{selectedTransportMode !== 'driving' && ( )}
) : isExpanded ? (
{selectedTransportMode === 'driving' && ( <> )} {selectedTransportMode === 'transit' && ( <> )} {selectedTransportMode === 'cycling' && ( )} {selectedTransportMode === 'walking' && ( )}
{!isCollapsed && routeInfo && ( <>
{routeInfo.duration} ({routeInfo.distance})
{getRouteLabelText(routeInfo.routeLabels)}
)}
{destination.name}
{shortDestinationAddress ? (
{shortDestinationAddress}
) : null}
{s.route_detailed_steps}
{isCurrentLocationRoutePoint(origin) ? s.your_current_location : origin?.name}
{visibleRouteSteps.map((step, idx) => (
{idx !== visibleRouteSteps.length - 1 && (
)}
{step.maneuver?.includes('right') ? ( ) : step.maneuver?.includes('left') ? ( ) : ( )}
{step.instructions || ''}
{step.distanceText}
))}
{destination.name}
{shortDestinationAddress ? (
{shortDestinationAddress}
) : null} {destinationSideHint ? (
{destinationSideHint}
) : null}
) : (
{!isCollapsed && routeInfo && ( <>
{routeInfo.duration} ({routeInfo.distance})
{getRouteLabelText(routeInfo.routeLabels)}
)}
)}
); };