You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
393 lines
18 KiB
393 lines
18 KiB
import React, {useState, useEffect, useRef} from "react"; |
|
import { View, Text, StyleSheet, Alert, TouchableOpacity, Image, Pressable, FlatList, LogBox, StatusBar, TextInput } from "react-native"; |
|
|
|
import MapLibreGL from '@maplibre/maplibre-react-native'; |
|
import { MapView,ShapeSource,Camera,UserLocation,PointAnnotation,FillLayer,LineLayer,VectorSource } from "@maplibre/maplibre-react-native"; |
|
import Geolocation from "@react-native-community/geolocation"; |
|
import AsyncStorage from '@react-native-async-storage/async-storage'; |
|
// import { TextInput } from "react-native-paper"; |
|
import adminCountry from '../../assets/geojson/admKabKota.json'; |
|
import Modal from "react-native-modal"; |
|
|
|
// MapLibreGL.setAccessToken(null); |
|
type MapCollectProps = {route: any,navigation: any} |
|
|
|
function MapCollectScreen({route,navigation}:MapCollectProps):React.JSX.Element{ |
|
const apiKey = "JoJs2pcDv5o0yQlQLMfI"; |
|
const [basemap, setBasemap] = useState("streets"); |
|
const styleURL = `https://api.maptiler.com/maps/${basemap}/style.json?key=${apiKey}`; |
|
|
|
const [currentPosition, setCurrentPosition] = useState<[number,number] | []>([0,0]); |
|
const [FixCoor, setFixCoor] = useState<{long:Number,lat:Number} | {}>({}); |
|
const [delayRender, setDelayRender] = useState(true); |
|
const [long,setLong] = useState(0); |
|
const [lat,setLat] = useState(0); |
|
const [modalInputLocation, setmodalInputLocation] = useState(false); |
|
const [modalBasemap, setmodalBasemap] = useState(false); |
|
const [modalLayerList, setmodalLayerList] = useState(false); |
|
const getLocation = () => { |
|
Geolocation.getCurrentPosition( |
|
position => { |
|
const {latitude, longitude } = position.coords; |
|
setFixCoor({long:longitude,lat:latitude}) |
|
setCurrentPosition([longitude,latitude]) |
|
setLat(latitude) |
|
setLong(longitude) |
|
}, |
|
error => { |
|
console.log('Error Getting current position', error); |
|
}, |
|
{enableHighAccuracy: false, timeout: 15000, maximumAge: 10000}, |
|
); |
|
}; |
|
|
|
|
|
useEffect(()=> { |
|
|
|
getLocation() |
|
|
|
const timeoutId = setTimeout(()=> { |
|
setDelayRender(false) |
|
}, 2000) |
|
|
|
return ()=> clearTimeout(timeoutId); |
|
},[]); |
|
|
|
const SelectPosition = () => { |
|
navigation.navigate('PJU Collecting', { screen: 'PJU Collecting', fixCoordinate: FixCoor}) |
|
}; |
|
|
|
const [zoom, setZoom] = useState(15); |
|
const MAX_ZOOM_LEVEL = 20; |
|
const MIN_ZOOM_LEVEL = 5; |
|
|
|
const handleZoom = (isZoomIn = false) => { |
|
let currentZoomLevel = zoom; |
|
if (!isZoomIn && currentZoomLevel === MAX_ZOOM_LEVEL) { |
|
currentZoomLevel -= 1; |
|
} |
|
else if (isZoomIn && currentZoomLevel === MIN_ZOOM_LEVEL) { |
|
currentZoomLevel += 1; |
|
} |
|
if ( |
|
currentZoomLevel >= MAX_ZOOM_LEVEL || |
|
currentZoomLevel <= MIN_ZOOM_LEVEL |
|
) { |
|
return; |
|
} |
|
currentZoomLevel = isZoomIn ? currentZoomLevel + 1 : currentZoomLevel - 1; |
|
setZoom(currentZoomLevel); |
|
} |
|
|
|
const gotoCoordinate = () => { |
|
setCurrentPosition([long,lat]) |
|
setFixCoor({long:long,lat:lat}) |
|
} |
|
|
|
|
|
return ( |
|
<View style={{flex:1}}> |
|
<StatusBar backgroundColor="#34A6F8" barStyle={'light-content'} /> |
|
<View key={"mainBackground"} style={{backgroundColor:'#34A6F8',width:'100%',height:'100%'}} /> |
|
{/* <View style={{flexDirection:'row',backgroundColor:'#34A6F8'}}> |
|
<View style={{flexDirection:'column',width:'80%',paddingLeft:5,paddingBottom:10,paddingEnd:5,paddingTop:5}}> |
|
<Text style={{color:'white',fontSize:16,fontWeight:'bold'}}>Longitude</Text> |
|
<TextInput style={{height:20, borderRadius:5, backgroundColor:'white'}} |
|
inputMode="decimal" |
|
value={long.toString()} |
|
onChangeText={setLong} |
|
/> |
|
<View |
|
style={{ |
|
marginTop: 15 |
|
}} |
|
/> |
|
<Text style={{color:'white',fontSize:16,fontWeight:'bold'}}>Latitude</Text> |
|
<TextInput style={{height:20, borderRadius:5, backgroundColor:'white'}} |
|
inputMode="decimal" |
|
value={lat.toString()} |
|
onChangeText={setLat} |
|
/> |
|
</View> |
|
<TouchableOpacity style={{width:'20%',alignItems:'center',justifyContent:'center'}} onPress={gotoCoordinate}> |
|
<View style={{backgroundColor:'white',width:35,height:35,borderRadius:100,alignItems:'center',justifyContent:'center'}}> |
|
<Image |
|
source={require('../../assets/icon/check.png')} |
|
style={styles.buttonImageIconStyle} |
|
/> |
|
</View> |
|
</TouchableOpacity> |
|
</View> */} |
|
<MapView |
|
style={{width:'100%',height:'100%',position:'absolute',marginTop:10,borderTopRightRadius:50,borderTopLeftRadius:35,overflow:'hidden'}} |
|
mapStyle={styleURL} |
|
zoomEnabled={true} |
|
compassEnabled={false} |
|
> |
|
{/* <ShapeSource |
|
id="nyc" |
|
shape={adminCountry} |
|
onPress={(e)=>{ |
|
const props = e.features[0].properties |
|
Alert.alert(props.NAME_2) |
|
|
|
} |
|
} |
|
> |
|
<FillLayer |
|
id="nycFill" |
|
style={{fillColor:'grey',fillOpacity:0.5}} |
|
filter={['!=', 'avail', 'A']} |
|
/> |
|
<LineLayer |
|
sourceID="nyc" |
|
id="nycFillLine" |
|
style={{lineColor: 'white', lineWidth:1}} |
|
/> |
|
</ShapeSource> */} |
|
{!delayRender ? |
|
<> |
|
<PointAnnotation |
|
children={<></>} |
|
style={{zIndex:-1}} |
|
id={"pjuCoordinate"} |
|
coordinate={currentPosition!} |
|
draggable={true} |
|
onDrag={(e)=> { |
|
setFixCoor({long:e.geometry.coordinates[0].toFixed(6),lat:e.geometry.coordinates[1].toFixed(6)}) |
|
console.log(e.geometry); |
|
setLong(e.geometry.coordinates[0].toFixed(6)) |
|
setLat(e.geometry.coordinates[1].toFixed(6)) |
|
|
|
}} |
|
/> |
|
<Camera |
|
centerCoordinate={currentPosition!} |
|
zoomLevel={zoom} |
|
minZoomLevel={5} |
|
maxZoomLevel={20} |
|
/> |
|
<UserLocation |
|
key={"userLoc"} |
|
androidRenderMode='compass' |
|
renderMode='native' |
|
animated={true} |
|
showsUserHeadingIndicator={true} |
|
children={ |
|
<Pressable onPress={()=>{ |
|
Alert.alert('aaa') |
|
}}> |
|
<View style={{width:20,height:20,backgroundColor:'red'}}> |
|
|
|
</View> |
|
</Pressable> |
|
} |
|
|
|
/> |
|
|
|
</> |
|
: |
|
<Camera |
|
minZoomLevel={0} |
|
maxZoomLevel={20} |
|
/> |
|
} |
|
</MapView> |
|
|
|
<TouchableOpacity onPress={()=>setmodalBasemap(true)} style={{position:'absolute',backgroundColor:'#FFFFFF',width:50,height:50,borderRadius:25,alignItems:'center',justifyContent:'center',top:'7%',left:'4%'}}> |
|
<Image |
|
source={require('../../assets/icon/layerList.png')} |
|
// style={styles.buttonImageIconStyle} |
|
/> |
|
</TouchableOpacity> |
|
<TouchableOpacity onPress={()=>setmodalLayerList(true)} style={{position:'absolute',backgroundColor:'#FFFFFF',width:50,height:50,borderRadius:25,alignItems:'center',justifyContent:'center',top:'15%',left:'4%'}}> |
|
<Image |
|
source={require('../../assets/icon/mapOutline.png')} |
|
// style={styles.buttonImageIconStyle} |
|
/> |
|
</TouchableOpacity> |
|
<TouchableOpacity onPress={()=>getLocation()} style={{position:'absolute',backgroundColor:'#FFFFFF',width:50,height:50,borderRadius:25,alignItems:'center',justifyContent:'center',top:'23%',left:'4%'}}> |
|
<Image |
|
source={require('../../assets/icon/findmyloc.png')} |
|
// style={styles.buttonImageIconStyle} |
|
/> |
|
</TouchableOpacity> |
|
<TouchableOpacity onPress={()=>{ |
|
setmodalInputLocation(true) |
|
}} style={{position:'absolute',backgroundColor:'#FFFFFF',width:50,height:50,borderRadius:25,alignItems:'center',justifyContent:'center',top:'7%',right:'4%'}}> |
|
<Image |
|
source={require('../../assets/icon/map_16.png')} |
|
// style={styles.buttonImageIconStyle} |
|
/> |
|
</TouchableOpacity> |
|
|
|
|
|
{!delayRender ? |
|
<TouchableOpacity style={{position:'absolute',alignSelf:'center',bottom:20}} onPress={SelectPosition}> |
|
<View style={{backgroundColor:'#0386D0',flexDirection:'row',width:350,height:50,borderRadius:10,justifyContent:'center'}}> |
|
<Text style={{alignSelf:'center',fontWeight:'bold',fontSize:20,color:'white'}}>Select Position</Text> |
|
</View> |
|
</TouchableOpacity> |
|
: |
|
<TouchableOpacity disabled={true} style={{position:'absolute',alignSelf:'center',bottom:20}}> |
|
<View style={{backgroundColor:'#0386D0',flexDirection:'row',width:350,height:50,borderRadius:10,justifyContent:'center',opacity:0.5}}> |
|
<Text style={{alignSelf:'center',fontWeight:'bold',fontSize:20,color:'white'}}>Waiting Get Position</Text> |
|
</View> |
|
</TouchableOpacity> |
|
} |
|
|
|
<Modal isVisible={modalInputLocation} animationIn={'fadeInUp'} animationOut={'fadeOutDown'} backdropOpacity={0} onBackdropPress={()=>setmodalInputLocation(false)} style={{top:'18%',alignSelf:'center'}}> |
|
<View key={"modal container"} style={{width:330,height:333,backgroundColor:'#FFFFFF',borderRadius:25}}> |
|
<View style={{flexDirection:'row',alignItems:'center',justifyContent:'space-between',paddingLeft:30,paddingTop:20,paddingRight:10}}> |
|
<Text style={{fontSize:20,fontWeight:'semibold'}}> |
|
Input Point |
|
</Text> |
|
<Pressable onPress={()=>setmodalInputLocation(false)} style={{alignSelf:'flex-end',padding:10}}> |
|
<Image |
|
source={require('../../assets/icon/x.png')} |
|
/> |
|
</Pressable> |
|
</View> |
|
<View style={{alignItems:'flex-start',paddingLeft:30,paddingTop:20,paddingRight:30}}> |
|
<Text style={{fontSize:14,fontWeight:'semibold',marginBottom:10}}>Longitude</Text> |
|
<TextInput |
|
inputMode="decimal" |
|
value={long.toString()} |
|
onChangeText={setLong} |
|
selectionHandleColor={'white'} |
|
style={{ |
|
backgroundColor:'white', |
|
color:'black', |
|
height : 50, |
|
paddingHorizontal : 20, |
|
borderWidth: 1, |
|
borderColor: "#A6A6A6", |
|
borderRadius: 10, |
|
width:'100%' |
|
}} |
|
placeholderTextColor={'grey'} |
|
placeholder='Longitude' |
|
/> |
|
<Text style={{fontSize:14,fontWeight:'semibold',marginBottom:10,marginTop:20}}>Latitude</Text> |
|
<TextInput |
|
inputMode="decimal" |
|
value={lat.toString()} |
|
onChangeText={setLat} |
|
selectionHandleColor={'white'} |
|
style={{ |
|
backgroundColor:'white', |
|
color:'black', |
|
height : 50, |
|
paddingHorizontal : 20, |
|
borderWidth: 1, |
|
borderColor: "#A6A6A6", |
|
borderRadius: 10, |
|
width:'100%' |
|
}} |
|
placeholderTextColor={'grey'} |
|
placeholder='Latitude' |
|
/> |
|
<TouchableOpacity |
|
onPress={gotoCoordinate} |
|
style={{ |
|
flexDirection:'row', |
|
width:'100%', |
|
marginTop:20, |
|
backgroundColor:'#0386D0', |
|
borderRadius: 10, |
|
height : 50, |
|
alignItems:'center', |
|
justifyContent:'center' |
|
}} |
|
> |
|
<Text style={{color:'#F5F5F5',fontSize:16,fontWeight:600}}>Ok</Text> |
|
<Image |
|
source={require('../../assets/icon/ceklis.png')} |
|
/> |
|
</TouchableOpacity> |
|
</View> |
|
</View> |
|
</Modal> |
|
|
|
<Modal isVisible={modalBasemap} animationIn={'fadeInUp'} animationOut={'fadeOutDown'} backdropOpacity={0} onBackdropPress={()=>setmodalBasemap(false)} style={{top:'18%',alignSelf:'center'}}> |
|
<View key={"modal container"} style={{width:330,height:333,backgroundColor:'#FFFFFF',borderRadius:25}}> |
|
<View style={{flexDirection:'row',alignItems:'center',justifyContent:'space-between',paddingLeft:30,paddingTop:20,paddingRight:10}}> |
|
<Text style={{fontSize:20,fontWeight:'semibold'}}> |
|
Basemap Gallery |
|
</Text> |
|
<Pressable onPress={()=>setmodalBasemap(false)} style={{alignSelf:'flex-end',padding:10}}> |
|
<Image |
|
source={require('../../assets/icon/x.png')} |
|
/> |
|
</Pressable> |
|
</View> |
|
</View> |
|
</Modal> |
|
|
|
<Modal isVisible={modalLayerList} animationIn={'fadeInUp'} animationOut={'fadeOutDown'} backdropOpacity={0} onBackdropPress={()=>setmodalLayerList(false)} style={{top:'18%',alignSelf:'center'}}> |
|
<View key={"modal container"} style={{width:330,height:333,backgroundColor:'#FFFFFF',borderRadius:25}}> |
|
<View style={{flexDirection:'row',alignItems:'center',justifyContent:'space-between',paddingLeft:30,paddingTop:20,paddingRight:10}}> |
|
<Text style={{fontSize:20,fontWeight:'semibold'}}> |
|
Layer List |
|
</Text> |
|
<Pressable onPress={()=>setmodalLayerList(false)} style={{alignSelf:'flex-end',padding:10}}> |
|
<Image |
|
source={require('../../assets/icon/x.png')} |
|
/> |
|
</Pressable> |
|
</View> |
|
</View> |
|
</Modal> |
|
|
|
{/* Widget Map */} |
|
{/* <View style={styles.gotoLocate}> |
|
<TouchableOpacity onPress={() => handleZoom(true)}> |
|
<Image |
|
source={require('../../assets/icon/plus.png')} |
|
style={styles.buttonImageIconStyle} |
|
/> |
|
</TouchableOpacity> |
|
<TouchableOpacity onPress={() => handleZoom()}> |
|
<Image |
|
source={require('../../assets/icon/minus.png')} |
|
style={styles.buttonImageIconStyle} |
|
/> |
|
</TouchableOpacity> |
|
<TouchableOpacity onPress={()=> { |
|
getLocation() |
|
}}> |
|
<Image |
|
source={require('../../assets/icon/MyLoc.png')} |
|
style={styles.buttonImageIconStyle} |
|
/> |
|
</TouchableOpacity> |
|
</View> */} |
|
</View> |
|
) |
|
} |
|
const styles = StyleSheet.create({ |
|
buttonImageIconStyle: { |
|
padding: 10, |
|
margin: 5, |
|
height: 25, |
|
width: 25, |
|
resizeMode: 'stretch', |
|
}, |
|
gotoLocate: { |
|
opacity: 0.6, |
|
position: 'absolute', |
|
top:120, |
|
right: 5, |
|
borderRadius:8, |
|
paddingHorizontal:7, |
|
width: 50, |
|
// height: 50, |
|
backgroundColor: "white", |
|
flexDirection: 'column', |
|
gap: 10 |
|
|
|
|
|
} |
|
}); |
|
|
|
export default MapCollectScreen; |