diff --git a/app/(tabs)/MapScreen.tsx b/app/(tabs)/MapScreen.tsx index 3b0a09b..3254600 100644 --- a/app/(tabs)/MapScreen.tsx +++ b/app/(tabs)/MapScreen.tsx @@ -1,3 +1,6 @@ +// 박물관 위치마커 + 구 나누기 + + import React, { useState, useEffect } from 'react'; import { Text, View } from 'react-native'; import MapView, { Marker, Callout, Polygon } from 'react-native-maps'; diff --git a/app/(tabs)/bookmarks.tsx b/app/(tabs)/bookmarks.tsx index e8b8a6e..d126469 100644 --- a/app/(tabs)/bookmarks.tsx +++ b/app/(tabs)/bookmarks.tsx @@ -1,20 +1,138 @@ -import { StyleSheet, Text, View } from 'react-native' -import React from 'react' +//공원 + 내위치 + 구글앱페이지 +import React, { useEffect, useState } from 'react'; +import { StyleSheet, View, FlatList, Text, TouchableOpacity, Linking } from 'react-native'; +import MapView, { Marker, PROVIDER_GOOGLE } from 'react-native-maps'; +import * as Location from 'expo-location'; +import axios from 'axios'; + +const ParkScreen: React.FC = () => { + const [parks, setParks] = useState([]); + const [visibleParks, setVisibleParks] = useState([]); + const [userLocation, setUserLocation] = useState(null); + const [initialRegion, setInitialRegion] = useState(null); + + useEffect(() => { + (async () => { + let { status } = await Location.requestForegroundPermissionsAsync(); + if (status !== 'granted') { + alert('Permission to access location was denied'); + return; + } + + try { + const location = await Location.getCurrentPositionAsync({}); + setUserLocation({ + latitude: location.coords.latitude, + longitude: location.coords.longitude + }); + setInitialRegion({ + latitude: location.coords.latitude, + longitude: location.coords.longitude, + latitudeDelta: 0.0922, + longitudeDelta: 0.0421 + }); + } catch (error) { + alert('Failed to get user location'); + } + })(); + fetchParks(); + }, []); + + const fetchParks = async () => { + const seoul_key = '57524f76506d656e3732636a52457a'; + const url = `http://openAPI.seoul.go.kr:8088/${seoul_key}/json/SearchParkInfoService/1/1000/`; + + try { + const response = await axios.get(url); + const data = response.data.SearchParkInfoService.row; + const cleanedData = data.map((park, index) => ({ + id: `${park.LATITUDE}-${park.LONGITUDE}-${index}`, + name: park.P_PARK, + latitude: parseFloat(park.LATITUDE), + longitude: parseFloat(park.LONGITUDE) + })).filter(park => park.latitude && park.longitude); + setParks(cleanedData); + } catch (error) { + console.error('Failed to fetch Seoul park data', error); + } + }; + + const onRegionChangeComplete = (region) => { + const visible = parks.filter(park => + park.latitude >= region.latitude - region.latitudeDelta / 2 && + park.latitude <= region.latitude + region.latitudeDelta / 2 && + park.longitude >= region.longitude - region.longitudeDelta / 2 && + park.longitude <= region.longitude + region.longitudeDelta / 2 + ); + setVisibleParks(visible); + }; -const Page = () => { return ( - Bookmarks + {initialRegion && ( + + {userLocation && ( + + )} + {visibleParks.map((park) => ( + + ))} + + )} + item.id} + renderItem={({ item }) => ( + { + const encodedName = encodeURIComponent(item.name); + const url = `https://www.google.com/maps/search/?api=1&query=${encodedName}`; + Linking.openURL(url); + }}> + {item.name} + + )} + style={styles.list} + /> - ) -} - -export default Page + ); +}; const styles = StyleSheet.create({ - container: { - flex: 1, - justifyContent: 'center', - alignItems: 'center', + container: { + flex: 1, + flexDirection: 'column' + }, + map: { + height: '70%' + }, + list: { + height: '30%' + }, + listItem: { + padding: 10, + borderBottomWidth: 1, + borderBottomColor: '#ccc' + }, + listItemText: { + fontSize: 16 } -}) \ No newline at end of file +}); + +export default ParkScreen; diff --git a/app/(tabs)/category.tsx b/app/(tabs)/category.tsx index a29ba6b..374641c 100644 --- a/app/(tabs)/category.tsx +++ b/app/(tabs)/category.tsx @@ -1,3 +1,5 @@ +//사용 ㄴㄴ + import React from 'react'; import { StyleSheet, View } from 'react-native'; import MapView from 'react-native-maps'; diff --git a/app/(tabs)/home.tsx b/app/(tabs)/home.tsx index 213104e..3c0d4d7 100644 --- a/app/(tabs)/home.tsx +++ b/app/(tabs)/home.tsx @@ -1,60 +1,118 @@ +// 도서관 + 내위치 + 리스트 + 상세페이지 import React, { useEffect, useState } from 'react'; +import { StyleSheet, View, FlatList, Text, TouchableOpacity, Linking } from 'react-native'; import MapView, { Marker, PROVIDER_GOOGLE } from 'react-native-maps'; -import { StyleSheet, View } from 'react-native'; import * as Location from 'expo-location'; +import axios from 'axios'; -const MapPage: React.FC = () => { - const [userLocation, setUserLocation] = useState(null); // 사용자 위치 정보를 저장 - const [locationErrorMsg, setLocationErrorMsg] = useState(null); // 위치 정보 가져오기 실패 시 오류 메시지 저장 +const HomeScreen: React.FC = ({ navigation }) => { + const [libraries, setLibraries] = useState([]); + const [visibleLibraries, setVisibleLibraries] = useState([]); + const [userLocation, setUserLocation] = useState(null); + const [initialRegion, setInitialRegion] = useState(null); useEffect(() => { (async () => { let { status } = await Location.requestForegroundPermissionsAsync(); if (status !== 'granted') { - setLocationErrorMsg('Permission to access location was denied'); + alert('Permission to access location was denied'); return; } try { const location = await Location.getCurrentPositionAsync({}); setUserLocation(location.coords); + setInitialRegion({ + latitude: location.coords.latitude, + longitude: location.coords.longitude, + latitudeDelta: 0.0922, + longitudeDelta: 0.0421 + }); } catch (error) { - setLocationErrorMsg('Failed to get user location'); + alert('Failed to get user location'); } })(); + fetchLibraries(); }, []); + const fetchLibraries = async () => { + const api_key = '57524f76506d656e3732636a52457a'; + const urls = [ + `http://openAPI.seoul.go.kr:8088/${api_key}/json/SeoulLibraryTimeInfo/1/1000/`, + `http://openAPI.seoul.go.kr:8088/${api_key}/json/SeoulLibraryTimeInfo/1001/2000/` + ]; + + try { + const responses = await Promise.all(urls.map(url => axios.get(url))); + const allData = responses.map(response => response.data.SeoulLibraryTimeInfo.row); + const cleanedData = allData.flat().map((lib, index) => ({ + id: `${lib.XCNTS}-${lib.YDNTS}-${index}`, // 고유 ID 생성 방식 + name: lib.LBRRY_NAME, + latitude: parseFloat(lib.XCNTS), + longitude: parseFloat(lib.YDNTS) + })).filter(lib => lib.latitude && lib.longitude); + setLibraries(cleanedData); + } catch (error) { + console.error('Failed to fetch library data', error); + } + }; + + const onRegionChangeComplete = (region) => { + const visible = libraries.filter(library => + library.latitude >= region.latitude - region.latitudeDelta / 2 && + library.latitude <= region.latitude + region.latitudeDelta / 2 && + library.longitude >= region.longitude - region.longitudeDelta / 2 && + library.longitude <= region.longitude + region.longitudeDelta / 2 + ); + setVisibleLibraries(visible); + }; + return ( - - {userLocation && ( - + {initialRegion && ( + + {userLocation && ( + + )} + {libraries.map((library, index) => ( + + ))} + + )} + item.id} // 고유 ID 사용 + renderItem={({ item }) => ( + { + const encodedName = encodeURIComponent(item.name); + const url = `https://www.google.com/maps/search/?api=1&query=${encodedName}`; + Linking.openURL(url); + }}> + {item.name} + )} - - + style={styles.list} + /> ); }; @@ -62,10 +120,22 @@ const MapPage: React.FC = () => { const styles = StyleSheet.create({ container: { flex: 1, + flexDirection: 'column' }, map: { - flex: 1, + height: '70%' + }, + list: { + height: '30%' + }, + listItem: { + padding: 10, + borderBottomWidth: 1, + borderBottomColor: '#ccc' }, + listItemText: { + fontSize: 16 + } }); -export default MapPage; +export default HomeScreen; diff --git a/app/(tabs)/prepocess.tsx b/app/(tabs)/prepocess.tsx index 8f5c6f7..d5ec6ed 100644 --- a/app/(tabs)/prepocess.tsx +++ b/app/(tabs)/prepocess.tsx @@ -1,29 +1,41 @@ -import React, { useEffect, useState } from 'react' -import MapView, { Marker, PROVIDER_GOOGLE } from 'react-native-maps'; -import { StyleSheet, Text, View} from 'react-native'; +//1,2,3 통합본 : 내위치, 공원, 박물관, 도서관 + +import React, { useEffect, useState } from 'react'; +import { StyleSheet, View, FlatList, Text, TouchableOpacity } from 'react-native'; +import MapView, { Marker, PROVIDER_GOOGLE, Region } from 'react-native-maps'; import * as Location from 'expo-location'; import axios from 'axios'; -const Page : React.FC = () => { +const Page: React.FC = () => { const [parks, setParks] = useState([]); const [libraries, setLibraries] = useState([]); const [museums, setMuseums] = useState([]); - const [userLocation, setUserLocation] = useState(null); // 사용자 위치 정보를 저장 - const [locationErrorMsg, setLocationErrorMsg] = useState(null); // 위치 정보 가져오기 실패 시 오류 메시지 저장 + const [visibleParks, setVisibleParks] = useState([]); + const [visibleLibraries, setVisibleLibraries] = useState([]); + const [visibleMuseums, setVisibleMuseums] = useState([]); + const [userLocation, setUserLocation] = useState(null); + const [locationErrorMsg, setLocationErrorMsg] = useState(null); + const [initialRegion, setInitialRegion] = useState(null); useEffect(() => { (async () => { let { status } = await Location.requestForegroundPermissionsAsync(); if (status !== 'granted') { - setLocationErrorMsg('Permission to access location was denied'); + setLocationErrorMsg('위치 정보 접근 권한이 거부되었습니다'); return; } try { const location = await Location.getCurrentPositionAsync({}); setUserLocation(location.coords); + setInitialRegion({ + latitude: location.coords.latitude, + longitude: location.coords.longitude, + latitudeDelta: 0.0922, + longitudeDelta: 0.0421 + }); } catch (error) { - setLocationErrorMsg('Failed to get user location'); + setLocationErrorMsg('사용자 위치를 가져오는 데 실패했습니다'); } })(); fetchParks(); @@ -34,18 +46,18 @@ const Page : React.FC = () => { const fetchParks = async () => { const seoul_key = '57524f76506d656e3732636a52457a'; const url = `http://openAPI.seoul.go.kr:8088/${seoul_key}/json/SearchParkInfoService/1/1000/`; - try { const response = await axios.get(url); const data = response.data.SearchParkInfoService.row; const cleanedData = data.map((park: any) => ({ - ...park, + name: park.P_PARK, LATITUDE: parseFloat(park.LATITUDE), LONGITUDE: parseFloat(park.LONGITUDE), + color: 'green' })).filter((park: any) => park.LATITUDE && park.LONGITUDE); setParks(cleanedData); } catch (error) { - console.error('서울 공원 데이터를 가져오는데 실패했습니다', error); + console.error('서울 공원 데이터를 가져오는 데 실패했습니다', error); } }; @@ -55,123 +67,151 @@ const Page : React.FC = () => { `http://openAPI.seoul.go.kr:8088/${api_key}/json/SeoulLibraryTimeInfo/1/1000/`, `http://openAPI.seoul.go.kr:8088/${api_key}/json/SeoulLibraryTimeInfo/1001/2000/` ]; - try { const responses = await Promise.all(urls.map(url => axios.get(url))); - const allData = responses.map(response => response.data.SeoulLibraryTimeInfo.row); - const libraries = allData.flat().map((lib: any) => ({ - ...lib, + const allData = responses.flatMap(response => response.data.SeoulLibraryTimeInfo.row); + const cleanedData = allData.map((lib: any) => ({ + name: lib.LBRRY_NAME, LATITUDE: parseFloat(lib.XCNTS), - LONGITUDE: parseFloat(lib.YDNTS) - })); - setLibraries(libraries); + LONGITUDE: parseFloat(lib.YDNTS), + color: 'purple' + })).filter((library: any) => library.LATITUDE && library.LONGITUDE); + setLibraries(cleanedData); } catch (error) { - console.error('서울 도서관 데이터를 가져오는데 실패했습니다', error); + console.error('서울 도서관 데이터를 가져오는 데 실패했습니다', error); } }; const fetchMuseums = async () => { const url = 'https://datasets-server.huggingface.co/rows?dataset=hscrown%2Fseoul_museums&config=default&split=train&offset=0&length=100'; - try { const response = await axios.get(url); const data = response.data; - if (data && data.rows) { // "rows" 키에서 데이터를 확인 + if (data && data.rows) { const cleanedData = data.rows.map((item: any) => ({ - name: item.row['시설명'], // "시설명" 필드 사용 + name: item.row['시설명'], LATITUDE: parseFloat(item.row['위도']), LONGITUDE: parseFloat(item.row['경도']), + color: 'orange' })).filter((museum: any) => museum.LATITUDE && museum.LONGITUDE); setMuseums(cleanedData); } else { console.error('예상한 데이터 구조와 다릅니다:', data); } } catch (error) { - console.error('서울 박물관 데이터를 가져오는데 실패했습니다', error); + console.error('서울 박물관 데이터를 가져오는 데 실패했습니다', error); } }; - - + + const onRegionChangeComplete = (region: Region) => { + setVisibleParks(parks.filter(park => + park.LATITUDE >= region.latitude - region.latitudeDelta / 2 && + park.LATITUDE <= region.latitude + region.latitudeDelta / 2 && + park.LONGITUDE >= region.longitude - region.longitudeDelta / 2 && + park.LONGITUDE <= region.longitude + region.longitudeDelta / 2 + )); + setVisibleLibraries(libraries.filter(library => + library.LATITUDE >= region.latitude - region.latitudeDelta / 2 && + library.LATITUDE <= region.latitude + region.latitudeDelta / 2 && + library.LONGITUDE >= region.longitude - region.longitudeDelta / 2 && + library.LONGITUDE <= region.longitude + region.longitudeDelta / 2 + )); + setVisibleMuseums(museums.filter(museum => + museum.LATITUDE >= region.latitude - region.latitudeDelta / 2 && + museum.LATITUDE <= region.latitude + region.latitudeDelta / 2 && + museum.LONGITUDE >= region.longitude - region.longitudeDelta / 2 && + museum.LONGITUDE <= region.longitude + region.longitudeDelta / 2 + )); + }; return ( - - {userLocation && ( - + {initialRegion && ( + + {userLocation && ( + + )} + {visibleParks.map((park, index) => ( + + ))} + {visibleLibraries.map((library, index) => ( + + ))} + {visibleMuseums.map((museum, index) => ( + + ))} + + )} + `place-${index}`} + renderItem={({ item }) => ( + + {item.name} + )} - - {parks.map((park, index) => ( - - ))} - {libraries.map((library, index) => ( - - ))} - {museums.map((museum, index) => ( - - ))} - + style={styles.list} + /> ); }; -export default Page; - const styles = StyleSheet.create({ container: { flex: 1, - justifyContent: 'center', - alignItems: 'center', - padding: 0 // Updated padding to 0 since the map typically occupies full screen + flexDirection: 'column' }, map: { - width: '100%', // Ensures the map takes up the full width of the container - height: '100%' // Ensures the map takes up the full height of the container + height: '70%' + }, + list: { + height: '30%' + }, + listItem: { + padding: 10, + borderBottomWidth: 1, + borderBottomColor: '#ccc' + }, + listItemText: { + fontSize: 16 } }); + +export default Page; + diff --git a/app/(tabs)/profile.tsx b/app/(tabs)/profile.tsx index 2af8fbc..9a8a959 100644 --- a/app/(tabs)/profile.tsx +++ b/app/(tabs)/profile.tsx @@ -1,20 +1,141 @@ -import { StyleSheet, Text, View } from 'react-native' -import React from 'react' +//필요3)) 박물관마커 + 내위치 + 상세페이지 + +import React, { useEffect, useState } from 'react'; +import { StyleSheet, View, FlatList, Text, TouchableOpacity, Linking } from 'react-native'; +import MapView, { Marker, PROVIDER_GOOGLE, Region } from 'react-native-maps'; +import * as Location from 'expo-location'; +import axios from 'axios'; + +const MuseumScreen: React.FC = () => { + const [museums, setMuseums] = useState([]); + const [visibleMuseums, setVisibleMuseums] = useState([]); + const [userLocation, setUserLocation] = useState(null); + const [locationErrorMsg, setLocationErrorMsg] = useState(null); + const [initialRegion, setInitialRegion] = useState(null); + + useEffect(() => { + (async () => { + let { status } = await Location.requestForegroundPermissionsAsync(); + if (status !== 'granted') { + setLocationErrorMsg('Permission to access location was denied'); + return; + } + + try { + const location = await Location.getCurrentPositionAsync({}); + setUserLocation(location.coords); + setInitialRegion({ + latitude: location.coords.latitude, + longitude: location.coords.longitude, + latitudeDelta: 0.0922, + longitudeDelta: 0.0421 + }); + } catch (error) { + setLocationErrorMsg('Failed to get user location'); + } + })(); + fetchMuseums(); + }, []); + + const fetchMuseums = async () => { + const url = 'https://datasets-server.huggingface.co/rows?dataset=hscrown%2Fseoul_museums&config=default&split=train&offset=0&length=100'; + try { + const response = await axios.get(url); + const data = response.data; + if (data && data.rows) { + const cleanedData = data.rows.map((item) => ({ + name: item.row['시설명'], + latitude: parseFloat(item.row['위도']), + longitude: parseFloat(item.row['경도']), + })).filter(museum => museum.latitude && museum.longitude); + setMuseums(cleanedData); + } else { + console.error('Unexpected data structure:', data); + } + } catch (error) { + console.error('Failed to fetch Seoul museum data', error); + } + }; + + const onRegionChangeComplete = (region: Region) => { + const visible = museums.filter(museum => + museum.latitude >= region.latitude - region.latitudeDelta / 2 && + museum.latitude <= region.latitude + region.latitudeDelta / 2 && + museum.longitude >= region.longitude - region.longitudeDelta / 2 && + museum.longitude <= region.longitude + region.longitudeDelta / 2 + ); + setVisibleMuseums(visible); + }; -const Page = () => { return ( - Profile + {initialRegion && ( + + {userLocation && ( + + )} + {visibleMuseums.map((museum, index) => ( + + ))} + + )} + item.name} + renderItem={({ item }) => ( + { + const encodedName = encodeURIComponent(item.name); + const url = `https://www.google.com/maps/search/?api=1&query=${encodedName}`; + Linking.openURL(url); + }}> + {item.name} + + )} + style={styles.list} + /> - ) -} - -export default Page + ); +}; const styles = StyleSheet.create({ - container: { - flex: 1, - justifyContent: 'center', - alignItems: 'center', - } -}) \ No newline at end of file + container: { + flex: 1, + flexDirection: 'column' + }, + map: { + height: '70%' + }, + list: { + height: '30%' + }, + listItem: { + padding: 10, + borderBottomWidth: 1, + borderBottomColor: '#ccc' + }, + listItemText: { + fontSize: 16 + } +}); + +export default MuseumScreen; diff --git a/package-lock.json b/package-lock.json index 6ac9687..644f1e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,8 @@ "version": "1.0.0", "dependencies": { "@expo/vector-icons": "^14.0.0", - "@react-navigation/native": "^6.0.2", + "@react-navigation/native": "^6.1.17", + "@react-navigation/stack": "^6.3.29", "axios": "^1.6.8", "expo": "~50.0.14", "expo-asset": "^9.0.2", @@ -37,6 +38,7 @@ }, "devDependencies": { "@babel/core": "^7.20.0", + "@expo/cli": "^0.17.10", "@types/react": "~18.2.45", "jest": "^29.2.1", "jest-expo": "~50.0.4", @@ -2205,6 +2207,18 @@ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" }, + "node_modules/@egjs/hammerjs": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", + "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==", + "peer": true, + "dependencies": { + "@types/hammerjs": "^2.0.36" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -2367,14 +2381,15 @@ } }, "node_modules/@expo/cli": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-0.17.8.tgz", - "integrity": "sha512-yfkoghCltbGPDbRI71Qu3puInjXx4wO82+uhW82qbWLvosfIN7ep5Gr0Lq54liJpvlUG6M0IXM1GiGqcCyP12w==", + "version": "0.17.10", + "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-0.17.10.tgz", + "integrity": "sha512-Jw2wY+lsavP9GRqwwLqF/SvB7w2GZ4sWBMcBKTZ8F0lWjwmLGAUt4WYquf20agdmnY/oZUHvWNkrz/t3SflhnA==", + "dev": true, "dependencies": { "@babel/runtime": "^7.20.0", "@expo/code-signing-certificates": "0.0.5", "@expo/config": "~8.5.0", - "@expo/config-plugins": "~7.8.0", + "@expo/config-plugins": "~7.9.0", "@expo/devcert": "^1.0.0", "@expo/env": "~0.2.2", "@expo/image-utils": "^0.4.0", @@ -2383,7 +2398,7 @@ "@expo/osascript": "^2.0.31", "@expo/package-manager": "^1.1.1", "@expo/plist": "^0.1.0", - "@expo/prebuild-config": "6.7.4", + "@expo/prebuild-config": "6.8.1", "@expo/rudder-sdk-node": "1.1.1", "@expo/spawn-async": "1.5.0", "@expo/xcpretty": "^4.3.0", @@ -2452,10 +2467,107 @@ "expo-internal": "build/bin/cli" } }, + "node_modules/@expo/cli/node_modules/@expo/config-plugins": { + "version": "7.9.1", + "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-7.9.1.tgz", + "integrity": "sha512-ICt6Jed1J0tPYMQrJ8K5Qusgih2I6pZ2PU4VSvxsN3T4n97L13XpYV1vyq1Uc/HMl3UhOwldipmgpEbCfeDqsQ==", + "dev": true, + "dependencies": { + "@expo/config-types": "^50.0.0-alpha.1", + "@expo/fingerprint": "^0.6.0", + "@expo/json-file": "~8.3.0", + "@expo/plist": "^0.1.0", + "@expo/sdk-runtime-versions": "^1.0.0", + "@react-native/normalize-color": "^2.0.0", + "chalk": "^4.1.2", + "debug": "^4.3.1", + "find-up": "~5.0.0", + "getenv": "^1.0.0", + "glob": "7.1.6", + "resolve-from": "^5.0.0", + "semver": "^7.5.3", + "slash": "^3.0.0", + "slugify": "^1.6.6", + "xcode": "^3.0.1", + "xml2js": "0.6.0" + } + }, + "node_modules/@expo/cli/node_modules/@expo/config-plugins/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@expo/cli/node_modules/@expo/prebuild-config": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-6.8.1.tgz", + "integrity": "sha512-ptK9e0dcj1eYlAWV+fG+QkuAWcLAT1AmtEbj++tn7ZjEj8+LkXRM73LCOEGaF0Er8i8ZWNnaVsgGW4vjgP5ZsA==", + "dev": true, + "dependencies": { + "@expo/config": "~8.5.0", + "@expo/config-plugins": "~7.9.0", + "@expo/config-types": "^50.0.0-alpha.1", + "@expo/image-utils": "^0.4.0", + "@expo/json-file": "^8.2.37", + "debug": "^4.3.1", + "fs-extra": "^9.0.0", + "resolve-from": "^5.0.0", + "semver": "7.5.3", + "xml2js": "0.6.0" + }, + "peerDependencies": { + "expo-modules-autolinking": ">=0.8.1" + } + }, + "node_modules/@expo/cli/node_modules/@expo/prebuild-config/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/cli/node_modules/@expo/prebuild-config/node_modules/semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@expo/cli/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -2470,6 +2582,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2485,6 +2598,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -2495,20 +2609,35 @@ "node_modules/@expo/cli/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/@expo/cli/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } }, + "node_modules/@expo/cli/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/@expo/cli/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -2520,6 +2649,7 @@ "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -2534,6 +2664,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -2541,10 +2672,20 @@ "node": ">=8" } }, + "node_modules/@expo/cli/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/@expo/cli/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/@expo/code-signing-certificates": { "version": "0.0.5", @@ -7155,6 +7296,24 @@ "nanoid": "^3.1.23" } }, + "node_modules/@react-navigation/stack": { + "version": "6.3.29", + "resolved": "https://registry.npmjs.org/@react-navigation/stack/-/stack-6.3.29.tgz", + "integrity": "sha512-tzlGkoRgB6P7vgw7rHuWo3TL7Gzu6xh5LMf+zSdCuEiKp/qASzxYfnTEr9tOLbVs/gf+qeukEDheCSAJKVpBXw==", + "dependencies": { + "@react-navigation/elements": "^1.3.30", + "color": "^4.2.3", + "warn-once": "^0.1.0" + }, + "peerDependencies": { + "@react-navigation/native": "^6.0.0", + "react": "*", + "react-native": "*", + "react-native-gesture-handler": ">= 1.0.0", + "react-native-safe-area-context": ">= 3.0.0", + "react-native-screens": ">= 3.0.0" + } + }, "node_modules/@remix-run/node": { "version": "1.19.3", "resolved": "https://registry.npmjs.org/@remix-run/node/-/node-1.19.3.tgz", @@ -7393,6 +7552,12 @@ "@types/node": "*" } }, + "node_modules/@types/hammerjs": { + "version": "2.0.45", + "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.45.tgz", + "integrity": "sha512-qkcUlZmX6c4J8q45taBKTL3p+LbITgyx7qhlPYOdOHZB7B31K0mXbP5YA7i7SgDeEGuI9MnumiKPEMrxg8j3KQ==", + "peer": true + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", @@ -11468,6 +11633,186 @@ "expo": "*" } }, + "node_modules/expo/node_modules/@expo/cli": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-0.17.8.tgz", + "integrity": "sha512-yfkoghCltbGPDbRI71Qu3puInjXx4wO82+uhW82qbWLvosfIN7ep5Gr0Lq54liJpvlUG6M0IXM1GiGqcCyP12w==", + "dependencies": { + "@babel/runtime": "^7.20.0", + "@expo/code-signing-certificates": "0.0.5", + "@expo/config": "~8.5.0", + "@expo/config-plugins": "~7.8.0", + "@expo/devcert": "^1.0.0", + "@expo/env": "~0.2.2", + "@expo/image-utils": "^0.4.0", + "@expo/json-file": "^8.2.37", + "@expo/metro-config": "~0.17.0", + "@expo/osascript": "^2.0.31", + "@expo/package-manager": "^1.1.1", + "@expo/plist": "^0.1.0", + "@expo/prebuild-config": "6.7.4", + "@expo/rudder-sdk-node": "1.1.1", + "@expo/spawn-async": "1.5.0", + "@expo/xcpretty": "^4.3.0", + "@react-native/dev-middleware": "^0.73.6", + "@urql/core": "2.3.6", + "@urql/exchange-retry": "0.3.0", + "accepts": "^1.3.8", + "arg": "5.0.2", + "better-opn": "~3.0.2", + "bplist-parser": "^0.3.1", + "cacache": "^15.3.0", + "chalk": "^4.0.0", + "ci-info": "^3.3.0", + "connect": "^3.7.0", + "debug": "^4.3.4", + "env-editor": "^0.4.1", + "find-yarn-workspace-root": "~2.0.0", + "form-data": "^3.0.1", + "freeport-async": "2.0.0", + "fs-extra": "~8.1.0", + "getenv": "^1.0.0", + "glob": "^7.1.7", + "graphql": "15.8.0", + "graphql-tag": "^2.10.1", + "https-proxy-agent": "^5.0.1", + "internal-ip": "4.3.0", + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1", + "js-yaml": "^3.13.1", + "json-schema-deref-sync": "^0.13.0", + "lodash.debounce": "^4.0.8", + "md5hex": "^1.0.0", + "minimatch": "^3.0.4", + "minipass": "3.3.6", + "node-fetch": "^2.6.7", + "node-forge": "^1.3.1", + "npm-package-arg": "^7.0.0", + "open": "^8.3.0", + "ora": "3.4.0", + "picomatch": "^3.0.1", + "pretty-bytes": "5.6.0", + "progress": "2.0.3", + "prompts": "^2.3.2", + "qrcode-terminal": "0.11.0", + "require-from-string": "^2.0.2", + "requireg": "^0.2.2", + "resolve": "^1.22.2", + "resolve-from": "^5.0.0", + "resolve.exports": "^2.0.2", + "semver": "^7.5.3", + "send": "^0.18.0", + "slugify": "^1.3.4", + "source-map-support": "~0.5.21", + "stacktrace-parser": "^0.1.10", + "structured-headers": "^0.4.1", + "tar": "^6.0.5", + "temp-dir": "^2.0.0", + "tempy": "^0.7.1", + "terminal-link": "^2.1.1", + "text-table": "^0.2.0", + "url-join": "4.0.0", + "wrap-ansi": "^7.0.0", + "ws": "^8.12.1" + }, + "bin": { + "expo-internal": "build/bin/cli" + } + }, + "node_modules/expo/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/expo/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/expo/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/expo/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/expo/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/expo/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/expo/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/expo/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/expo/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -12248,6 +12593,15 @@ "node": ">=8" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "peer": true, + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/hosted-git-info": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", @@ -17918,6 +18272,23 @@ "react": "18.2.0" } }, + "node_modules/react-native-gesture-handler": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.16.2.tgz", + "integrity": "sha512-vGFlrDKlmyI+BT+FemqVxmvO7nqxU33cgXVsn6IKAFishvlG3oV2Ds67D5nPkHMea8T+s1IcuMm0bF8ntZtAyg==", + "peer": true, + "dependencies": { + "@egjs/hammerjs": "^2.0.17", + "hoist-non-react-statics": "^3.3.0", + "invariant": "^2.2.4", + "lodash": "^4.17.21", + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/react-native-maps": { "version": "1.14.0", "resolved": "https://registry.npmjs.org/react-native-maps/-/react-native-maps-1.14.0.tgz", diff --git a/package.json b/package.json index 9551c1f..e5eb05f 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ }, "dependencies": { "@expo/vector-icons": "^14.0.0", - "@react-navigation/native": "^6.0.2", + "@react-navigation/native": "^6.1.17", + "@react-navigation/stack": "^6.3.29", "axios": "^1.6.8", "expo": "~50.0.14", "expo-asset": "^9.0.2", @@ -42,6 +43,7 @@ }, "devDependencies": { "@babel/core": "^7.20.0", + "@expo/cli": "^0.17.10", "@types/react": "~18.2.45", "jest": "^29.2.1", "jest-expo": "~50.0.4",