import { useState, useCallback } from 'react'; import { Slider } from '../ui/Slider'; import { IconButton } from '../ui/IconButton'; import { PillToggle } from '../ui/PillToggle'; import { DestinationDropdown } from '../ui/DestinationDropdown'; import InfoPopup from '../ui/InfoPopup'; import { TravelTimeInfoPopup } from '../ui/TravelTimeInfoPopup'; import { CloseIcon } from '../ui/icons/CloseIcon'; import { EyeIcon } from '../ui/icons/EyeIcon'; import { InfoIcon } from '../ui/icons/InfoIcon'; import { formatFilterValue } from '../../lib/format'; import { useTravelDestinations } from '../../hooks/useTravelDestinations'; import { MODE_LABELS, MODE_ICONS, type TransportMode } from '../../hooks/useTravelTime'; interface TravelTimeCardProps { mode: TransportMode; slug: string; label: string; timeRange: [number, number] | null; useBest: boolean; isPinned: boolean; isActive: boolean; dragValue: [number, number] | null; onTogglePin: () => void; onSetDestination: (slug: string, label: string, lat: number, lon: number) => void; onTimeRangeChange: (range: [number, number]) => void; onDragStart: () => void; onDragChange: (value: [number, number]) => void; onDragEnd: () => void; onToggleBest: () => void; onRemove: () => void; } export function TravelTimeCard({ mode, slug, label, timeRange, useBest, isPinned, isActive, dragValue, onTogglePin, onSetDestination, onTimeRangeChange, onDragStart, onDragChange, onDragEnd, onToggleBest, onRemove, }: TravelTimeCardProps) { const { destinations, loading: destinationsLoading } = useTravelDestinations(mode); const [showInfo, setShowInfo] = useState(false); const [showBestInfo, setShowBestInfo] = useState(false); const handleDestinationSelect = useCallback( (selectedSlug: string, selectedLabel: string, lat: number, lon: number) => { onSetDestination(selectedSlug, selectedLabel, lat, lon); }, [onSetDestination] ); const sliderMin = 0; const sliderMax = 120; const displayRange = isActive && dragValue ? dragValue : (timeRange ?? [sliderMin, sliderMax]); const ModeIcon = MODE_ICONS[mode]; return (
{/* Header */}
Travel Time ({MODE_LABELS[mode]})
setShowInfo(true)} title="Feature info"> {slug && ( )} onRemove()} title="Remove travel time">
{/* Destination */} onSetDestination('', '', 0, 0)} placeholder="Select destination..." /> {/* Best-case toggle — transit only, shown when destination is set */} {slug && mode === 'transit' && (
setShowBestInfo(true)} title="What is best case?">
)} {showInfo && setShowInfo(false)} />} {showBestInfo && ( setShowBestInfo(false)}>

Uses the fastest realistic journey time (if you time your departure well and catch good connections). The default uses the median, representing a typical journey regardless of when you leave.

)} {/* Time range slider — only show when we have data */} {slug && (
Max time onDragChange([min, max])} onPointerDown={() => onDragStart()} onPointerUp={() => onDragEnd()} />
{formatFilterValue(displayRange[0])} min {formatFilterValue(displayRange[1])} min
)}
); }