/** * @ai-summary Form for searching nearby gas stations */ import React, { useState, useEffect } from 'react'; import { Box, TextField, Button, Slider, FormControl, FormLabel, Alert, CircularProgress, InputAdornment } from '@mui/material'; import LocationIcon from '@mui/icons-material/LocationOn'; import MyLocationIcon from '@mui/icons-material/MyLocation'; import { StationSearchRequest, GeolocationError } from '../types/stations.types'; import { useGeolocation } from '../hooks'; interface StationsSearchFormProps { onSearch: (request: StationSearchRequest) => void; isSearching?: boolean; } /** * Search form with manual location input and geolocation button * Radius slider: 1-25 miles, default 5 miles */ export const StationsSearchForm: React.FC = ({ onSearch, isSearching = false }) => { const [latitude, setLatitude] = useState(''); const [longitude, setLongitude] = useState(''); const [radius, setRadius] = useState(5); // Miles const [locationError, setLocationError] = useState(null); const { coordinates, isPending: isGeolocating, error: geoError, requestPermission, clearError: clearGeoError } = useGeolocation(); // Update form when geolocation succeeds useEffect(() => { if (coordinates) { setLatitude(coordinates.latitude); setLongitude(coordinates.longitude); setLocationError(null); } }, [coordinates]); // Handle geolocation errors useEffect(() => { if (geoError) { if (geoError === GeolocationError.PERMISSION_DENIED) { setLocationError('Location permission denied. Please enable it in browser settings.'); } else if (geoError === GeolocationError.TIMEOUT) { setLocationError('Location request timed out. Try again.'); } else if (geoError === GeolocationError.POSITION_UNAVAILABLE) { setLocationError('Location not available. Try a different device.'); } else { setLocationError('Unable to get location. Please enter manually.'); } } }, [geoError]); const handleUseCurrentLocation = () => { clearGeoError(); requestPermission(); }; const handleSearch = () => { if (latitude === '' || longitude === '') { setLocationError('Please enter coordinates or use current location'); return; } const request: StationSearchRequest = { latitude: typeof latitude === 'number' ? latitude : 0, longitude: typeof longitude === 'number' ? longitude : 0, radius: radius * 1609.34 // Convert miles to meters }; onSearch(request); }; const handleRadiusChange = ( _event: Event, newValue: number | number[] ) => { if (typeof newValue === 'number') { setRadius(newValue); } }; return ( { e.preventDefault(); handleSearch(); }} sx={{ padding: 2, display: 'flex', flexDirection: 'column', gap: 2 }} > {/* Geolocation Button */} {/* Or Divider */} or {/* Manual Latitude Input */} { const val = e.target.value; setLatitude(val === '' ? '' : parseFloat(val)); }} placeholder="37.7749" inputProps={{ step: '0.0001', min: '-90', max: '90' }} fullWidth InputProps={{ startAdornment: ( ) }} /> {/* Manual Longitude Input */} { const val = e.target.value; setLongitude(val === '' ? '' : parseFloat(val)); }} placeholder="-122.4194" inputProps={{ step: '0.0001', min: '-180', max: '180' }} fullWidth InputProps={{ startAdornment: ( ) }} /> {/* Radius Slider */} Search Radius: {radius} mi {/* Error Messages */} {locationError && ( {locationError} )} {/* Search Button */} ); }; export default StationsSearchForm;