-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathlocation-picker.tsx
More file actions
141 lines (127 loc) · 4.53 KB
/
Copy pathlocation-picker.tsx
File metadata and controls
141 lines (127 loc) · 4.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import Mapbox from '@rnmapbox/maps';
import * as Location from 'expo-location';
import React, { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { StyleSheet, TouchableOpacity } from 'react-native';
import { Box } from '@/components/ui/box';
import { Button, ButtonText } from '@/components/ui/button';
import { Text } from '@/components/ui/text';
interface LocationPickerProps {
initialLocation?: {
latitude: number;
longitude: number;
};
onLocationSelected: (location: { latitude: number; longitude: number; address?: string }) => void;
height?: number;
}
const LocationPicker: React.FC<LocationPickerProps> = ({ initialLocation, onLocationSelected, height = 200 }) => {
const { t } = useTranslation();
const mapRef = useRef<Mapbox.MapView>(null);
const cameraRef = useRef<Mapbox.Camera>(null);
const [currentLocation, setCurrentLocation] = useState<{
latitude: number;
longitude: number;
} | null>(initialLocation || null);
const [isLoading, setIsLoading] = useState(false);
const getUserLocation = React.useCallback(async () => {
setIsLoading(true);
try {
const { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') {
console.error('Location permission not granted');
setIsLoading(false);
return;
}
const location = await Location.getCurrentPositionAsync({});
setCurrentLocation({
latitude: location.coords.latitude,
longitude: location.coords.longitude,
});
// Move camera to user location
if (cameraRef.current) {
cameraRef.current.setCamera({
centerCoordinate: [location.coords.longitude, location.coords.latitude],
zoomLevel: 15,
animationDuration: 1000,
});
}
} catch (error) {
console.error('Error getting location:', error);
} finally {
setIsLoading(false);
}
}, []);
useEffect(() => {
if (initialLocation) {
setCurrentLocation(initialLocation);
// Move camera to the new location
if (cameraRef.current) {
cameraRef.current.setCamera({
centerCoordinate: [initialLocation.longitude, initialLocation.latitude],
zoomLevel: 15,
animationDuration: 1000,
});
}
} else {
getUserLocation().catch((error) => {
console.error('Failed to get user location:', error);
});
}
}, [initialLocation, getUserLocation]);
const handleMapPress = (event: any) => {
const { coordinates } = event.geometry;
setCurrentLocation({
latitude: coordinates[1],
longitude: coordinates[0],
});
};
const handleConfirmLocation = () => {
if (currentLocation) {
onLocationSelected(currentLocation);
}
};
if (isLoading) {
return (
<Box style={[styles.container, { height }]} className="items-center justify-center bg-gray-200">
<Text className="text-gray-500">{t('common.loading')}</Text>
</Box>
);
}
return (
<Box style={[styles.container, { height }]}>
{currentLocation ? (
<Mapbox.MapView ref={mapRef} style={styles.map} logoEnabled={false} attributionEnabled={false} compassEnabled={true} zoomEnabled={true} rotateEnabled={true} onPress={handleMapPress}>
<Mapbox.Camera ref={cameraRef} zoomLevel={15} centerCoordinate={[currentLocation.longitude, currentLocation.latitude]} animationMode="flyTo" animationDuration={1000} />
{/* Marker for the selected location */}
<Mapbox.PointAnnotation id="selectedLocation" coordinate={[currentLocation.longitude, currentLocation.latitude]} title="Selected Location">
<Box />
</Mapbox.PointAnnotation>
</Mapbox.MapView>
) : (
<Box className="items-center justify-center bg-gray-200" style={{ flex: 1 }}>
<Text className="text-gray-500">{t('common.no_location')}</Text>
<TouchableOpacity onPress={getUserLocation} className="mt-2">
<Text className="text-blue-500">{t('common.get_my_location')}</Text>
</TouchableOpacity>
</Box>
)}
<Box className="absolute inset-x-4 bottom-4">
<Button onPress={handleConfirmLocation} disabled={!currentLocation}>
<ButtonText>{t('common.confirm_location')}</ButtonText>
</Button>
</Box>
</Box>
);
};
const styles = StyleSheet.create({
container: {
width: '100%',
position: 'relative',
overflow: 'hidden',
borderRadius: 8,
},
map: {
flex: 1,
},
});
export default LocationPicker;