summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/(tabs)/index.tsx115
-rw-r--r--package-lock.json40
-rw-r--r--package.json1
3 files changed, 137 insertions, 19 deletions
diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx
index c631903..b1eac11 100644
--- a/app/(tabs)/index.tsx
+++ b/app/(tabs)/index.tsx
@@ -1,16 +1,19 @@
import { Alert, Platform, Pressable, StyleSheet, Text, TextInput, View } from 'react-native';
-
import ParallaxScrollView from '@/components/ParallaxScrollView';
import { ThemedText } from '@/components/ThemedText';
import { ThemedView } from '@/components/ThemedView';
-import React, { useState, useEffect } from 'react';
-import AsyncStorage from '@react-native-async-storage/async-storage';
-
+import React, { useState, useEffect, useRef } from 'react';
+import AsyncStorage from '@react-native-async-storage/async-storage';
+import MapView, { Marker } from 'react-native-maps';
export default function HomeScreen() {
- const [username, setUsername] = useState('');
+ const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [token, setToken] = useState('');
+ const [userId, setUserId] = useState('');
+ const [coordinates, setCoordinates] = useState({ latitude: 44.49738301084014, longitude: 11.356121722966094 });
+ const [region, setRegion] = useState({ latitude: 44.49738301084014, longitude: 11.356121722966094, latitudeDelta: 0.03, longitudeDelta: 0.03 });
+ const mapRef = useRef(null);
const storeToken = async (token: string) => {
if (Platform.OS === 'web') {
@@ -20,9 +23,17 @@ export default function HomeScreen() {
}
};
+ const storeUserId = async (userId: string) => {
+ if (Platform.OS === 'web') {
+ localStorage.setItem('userId', userId);
+ } else {
+ await AsyncStorage.setItem('userId', userId);
+ }
+ };
+
const handleLogin = async () => {
- if (!username || !password) {
- Alert.alert('Error', 'Username and password are required.');
+ if (!email || !password) {
+ Alert.alert('Error', 'Email and password are required.');
return;
}
@@ -38,11 +49,12 @@ export default function HomeScreen() {
login(input: $input) {
accessToken
tokenType
+ userId
}
}`,
variables: {
input: {
- email: username,
+ email: email,
password,
},
},
@@ -55,9 +67,11 @@ export default function HomeScreen() {
const errorMessages = data.errors.map((error: any) => error.message);
Alert.alert('Error', errorMessages.join('\n'));
} else {
- const { accessToken } = data.data.login;
+ const { accessToken, userId } = data.data.login;
await storeToken(accessToken);
+ await storeUserId(String(userId));
setToken(accessToken);
+ setUserId(String(userId));
}
} catch (err) {
console.error('Login Error:', err);
@@ -73,8 +87,42 @@ export default function HomeScreen() {
const removeToken = async () => {
if (Platform.OS === 'web') {
localStorage.removeItem('token');
+ localStorage.removeItem('userId');
} else {
await AsyncStorage.removeItem('token');
+ await AsyncStorage.removeItem('userId');
+ }
+ };
+
+ const fetchMapData = async () => {
+ if (!token || !userId) return;
+
+ try {
+ const response = await fetch(`${process.env.EXPO_PUBLIC_API_URL}/graphql`, {
+ method: 'POST',
+ headers: {
+ 'Authorization': `Bearer ${token}`,
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ query: `{ positions(userId: ${userId}) { id, userId, createdAt, latitude, longitude } }`,
+ }),
+ });
+
+ const data = await response.json();
+
+ if (data.data.positions && data.data.positions.length > 0) {
+ const position = data.data.positions[0];
+ setCoordinates({ latitude: position.latitude, longitude: position.longitude });
+ setRegion({
+ latitude: position.latitude,
+ longitude: position.longitude,
+ latitudeDelta: 0.03,
+ longitudeDelta: 0.03,
+ });
+ }
+ } catch (err) {
+ console.error('Fetch Map Data Error:', err);
}
};
@@ -82,19 +130,46 @@ export default function HomeScreen() {
const retrieveToken = async () => {
const storedToken = Platform.OS === 'web' ? localStorage.getItem('token') : await AsyncStorage.getItem('token');
setToken(storedToken || '');
+ const storedUserId = Platform.OS === 'web' ? localStorage.getItem('userId') : await AsyncStorage.getItem('userId');
+ setUserId(storedUserId || '');
};
retrieveToken();
}, []);
+ useEffect(() => {
+ if (token && userId) {
+ const intervalId = setInterval(fetchMapData, 10000); // Fetch map data every 10 seconds
+
+ return () => clearInterval(intervalId);
+ }
+ }, [token, userId]);
+
+ useEffect(() => {
+ if (mapRef.current && region) {
+ mapRef.current.animateToRegion(region, 1000); // Smoothly animate to the new region
+ }
+ }, [region]);
+
return (
<ParallaxScrollView>
- {token ? (
- <ThemedView>
- <Pressable onPress={handleLogout} style={styles.formButton}>
- <Text style={{ color: 'white', textAlign: 'center' }}>Logout</Text>
- </Pressable>
- </ThemedView>
+ {token && userId ? (
+ <>
+ <ThemedView>
+ <Pressable onPress={handleLogout} style={styles.formButton}>
+ <Text style={{ color: 'white', textAlign: 'center' }}>Logout</Text>
+ </Pressable>
+ </ThemedView>
+ <View>
+ <MapView
+ ref={mapRef}
+ initialRegion={region}
+ style={styles.map}
+ >
+ <Marker coordinate={coordinates} title="Start Point" />
+ </MapView>
+ </View>
+ </>
) : (
<>
<ThemedView style={styles.titleContainer}>
@@ -102,11 +177,11 @@ export default function HomeScreen() {
</ThemedView>
<ThemedView style={styles.formContainer}>
<View>
- <ThemedText style={styles.text}>Username</ThemedText>
+ <ThemedText style={styles.text}>Email</ThemedText>
<TextInput
style={styles.formInput}
- onChangeText={setUsername}
- value={username}
+ onChangeText={setEmail}
+ value={email}
/>
</View>
<View>
@@ -166,6 +241,8 @@ const styles = StyleSheet.create({
textAlign: 'center',
borderRadius: 8,
color: 'white',
+ },
+ map: {
+ height: 400,
}
});
-
diff --git a/package-lock.json b/package-lock.json
index 210cbfc..442b266 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -24,6 +24,7 @@
"react-dom": "18.2.0",
"react-native": "0.74.5",
"react-native-gesture-handler": "~2.16.1",
+ "react-native-maps": "^1.18.0",
"react-native-reanimated": "~3.10.1",
"react-native-safe-area-context": "4.10.5",
"react-native-screens": "3.31.1",
@@ -6656,6 +6657,11 @@
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="
},
+ "node_modules/@types/geojson": {
+ "version": "7946.0.14",
+ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz",
+ "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg=="
+ },
"node_modules/@types/graceful-fs": {
"version": "4.1.9",
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
@@ -15720,6 +15726,27 @@
"react": "^16.6.0 || ^17.0.0 || ^18.0.0"
}
},
+ "node_modules/react-native-maps": {
+ "version": "1.18.0",
+ "resolved": "https://registry.npmjs.org/react-native-maps/-/react-native-maps-1.18.0.tgz",
+ "integrity": "sha512-S17nYUqeMptgIPaAZuVRo+eRelPreBBYQWw6jsxU7qQ12p+THSfFaqabcNn7fBmsXhT3T27iIl8ek8v1H8BaGw==",
+ "dependencies": {
+ "@types/geojson": "^7946.0.13"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "react": ">= 17.0.1",
+ "react-native": ">= 0.64.3",
+ "react-native-web": ">= 0.11"
+ },
+ "peerDependenciesMeta": {
+ "react-native-web": {
+ "optional": true
+ }
+ }
+ },
"node_modules/react-native-reanimated": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.10.1.tgz",
@@ -23068,6 +23095,11 @@
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="
},
+ "@types/geojson": {
+ "version": "7946.0.14",
+ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz",
+ "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg=="
+ },
"@types/graceful-fs": {
"version": "4.1.9",
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
@@ -29809,6 +29841,14 @@
"shallowequal": "^1.1.0"
}
},
+ "react-native-maps": {
+ "version": "1.18.0",
+ "resolved": "https://registry.npmjs.org/react-native-maps/-/react-native-maps-1.18.0.tgz",
+ "integrity": "sha512-S17nYUqeMptgIPaAZuVRo+eRelPreBBYQWw6jsxU7qQ12p+THSfFaqabcNn7fBmsXhT3T27iIl8ek8v1H8BaGw==",
+ "requires": {
+ "@types/geojson": "^7946.0.13"
+ }
+ },
"react-native-reanimated": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.10.1.tgz",
diff --git a/package.json b/package.json
index b366c93..313993c 100644
--- a/package.json
+++ b/package.json
@@ -31,6 +31,7 @@
"react-dom": "18.2.0",
"react-native": "0.74.5",
"react-native-gesture-handler": "~2.16.1",
+ "react-native-maps": "^1.18.0",
"react-native-reanimated": "~3.10.1",
"react-native-safe-area-context": "4.10.5",
"react-native-screens": "3.31.1",