DRP_Sajidaat/DRP-App/app/SearchComponent.tsx

172 lines
5.4 KiB
TypeScript

// SearchComponent.tsx
import React, { useState, useRef, useCallback } from 'react';
import { View, TextInput, FlatList, TouchableOpacity, Text, StyleSheet, Alert, Keyboard } from 'react-native'; // Added Keyboard import
const GOOGLE_API_KEY = 'AIzaSyB1WZHDqjGk696AmVw7tA2sMAuOurt552Q'; // Your Google Places API Key
const TARGET_LATITUDE_DELTA = 0.005;
const TARGET_LONGITUDE_DELTA = 0.005;
interface SearchComponentProps {
onSelectPlace: (lat: number, lng: number, name: string) => void;
}
const SearchComponent: React.FC<SearchComponentProps> = ({ onSelectPlace }) => {
const [searchQuery, setSearchQuery] = useState('');
const [addressSuggestions, setAddressSuggestions] = useState<any[]>([]);
const debounceTimeout = useRef<NodeJS.Timeout | null>(null);
// Ref to track if a suggestion is currently being pressed
const isPressingSuggestion = useRef(false);
const handleSearch = useCallback(async (text: string) => {
setSearchQuery(text);
if (debounceTimeout.current) {
clearTimeout(debounceTimeout.current);
}
if (text.length < 3) {
setAddressSuggestions([]);
return;
}
debounceTimeout.current = setTimeout(async () => {
try {
const url = `https://maps.googleapis.com/maps/api/place/autocomplete/json?input=${encodeURIComponent(text)}&key=${GOOGLE_API_KEY}&components=country:gb&location=51.5074,-0.1278&radius=20000`;
const response = await fetch(url);
const data = await response.json();
if (data && data.predictions) {
setAddressSuggestions(data.predictions);
} else {
setAddressSuggestions([]);
}
} catch (error) {
console.error('Google Autocomplete search error:', error);
setAddressSuggestions([]);
}
}, 300);
}, []);
const handleSuggestionPress = useCallback(async (item: any) => {
console.log("Autocomplete suggestion clicked:", item.description);
// NEW: Dismiss the keyboard immediately after a suggestion is selected
Keyboard.dismiss();
setSearchQuery(item.description);
setAddressSuggestions([]); // Hide suggestions after selection
try {
const url = `https://maps.googleapis.com/maps/api/place/details/json?place_id=${item.place_id}&fields=geometry,name&key=${GOOGLE_API_KEY}`;
const response = await fetch(url);
const data = await response.json();
if (data && data.result && data.result.geometry) {
const { lat, lng } = data.result.geometry.location;
const name = data.result.name || item.description;
onSelectPlace(lat, lng, name);
} else {
Alert.alert('Location Error', 'Could not get precise coordinates for selected place.');
}
} catch (error) {
console.error('Google Place Details error:', error);
Alert.alert('Network Error', 'Failed to fetch location details.');
}
}, [onSelectPlace]);
const handleEnterPress = useCallback(() => {
if (addressSuggestions.length > 0) {
handleSuggestionPress(addressSuggestions[0]); // Take the first suggestion
}
}, [addressSuggestions, handleSuggestionPress]);
return (
<View style={styles.searchBarContainer}>
<TextInput
style={styles.searchBar}
placeholder="Search for a location (e.g., Oxford Street)"
placeholderTextColor="black" // Force dark placeholder for all platforms
value={searchQuery}
onChangeText={handleSearch}
onBlur={() => {
setTimeout(() => {
if (!isPressingSuggestion.current) {
setAddressSuggestions([]);
}
}, 100); // Small delay
}}
onSubmitEditing={handleEnterPress}
/>
{addressSuggestions.length > 0 && (
<FlatList
style={styles.suggestionsList}
data={addressSuggestions}
keyExtractor={(item) => item.place_id}
keyboardShouldPersistTaps="handled"
renderItem={({ item }) => (
<TouchableOpacity
style={styles.suggestionItem}
onPressIn={() => { isPressingSuggestion.current = true; }}
onPressOut={() => { isPressingSuggestion.current = false; }}
onPress={() => handleSuggestionPress(item)}
>
<Text style={styles.suggestionText}>{item.description}</Text>
</TouchableOpacity>
)}
initialNumToRender={5}
maxToRenderPerBatch={5}
windowSize={10}
/>
)}
</View>
);
};
const styles = StyleSheet.create({
searchBarContainer: {
position: 'absolute',
top: 20,
left: 10,
right: 10,
zIndex: 10,
backgroundColor: 'white',
borderRadius: 8,
padding: 10,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
},
searchBar: {
height: 40,
borderColor: '#ccc',
borderWidth: 1,
borderRadius: 8,
paddingHorizontal: 10,
fontSize: 16,
color: '#222', // Ensure dark text for visibility
},
suggestionsList: {
maxHeight: 200,
marginTop: 5,
borderRadius: 8,
overflow: 'hidden',
backgroundColor: 'white',
borderWidth: 1,
borderColor: '#eee',
},
suggestionItem: {
padding: 10,
borderBottomWidth: 1,
borderBottomColor: '#eee',
},
suggestionText: {
fontSize: 16,
color: '#222', // Ensure dark text for visibility
},
});
export default SearchComponent;