import React, { useEffect, useRef, useState } from 'react'; import { View, Text, TouchableOpacity, KeyboardAvoidingView, TouchableWithoutFeedback, Keyboard, ScrollView } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import MapView, { Marker } from 'react-native-maps'; import ReactModal from 'react-native-modal'; import axios from 'axios'; import 'react-native-get-random-values'; import { GooglePlaceData, GooglePlaceDetail, GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete'; import { FlashList } from '@shopify/flash-list'; import { Formik } from 'formik'; import * as yup from 'yup'; import { styles } from './styles'; import { Header, Input, Button, WarningModal } from 'src/components'; import { GOOGLE_MAP_PLACES_APIKEY } from 'src/constants'; import { Colors } from 'src/theme'; import { SubmitSuggestionTypes, useGetDataFromPoint, useGetSuggestionData, useSubmitSuggestionMutation } from '@api/series'; import { StoreType, storage } from 'src/storage'; import { ButtonVariants } from 'src/types/components'; import SeriesSelector from './SeriesSelector'; import SearchIcon from 'assets/icons/search.svg'; import InfoIcon from 'assets/icons/info-solid.svg'; import Tooltip from 'react-native-walkthrough-tooltip'; import { GooglePlacesAutocompleteDefaultProps } from './GooglePlacesAutocompleteProps'; interface Series { id: number; name: string; group_name: string | null; } const SuggestionSchema = yup.object({ comment: yup.string().required('comment is required') }); const SuggestSeriesScreen = ({ navigation }: { navigation: any }) => { const token = storage.get('token', StoreType.STRING) as string; const [isModalVisible, setIsModalVisible] = useState(false); const [seriesVisible, setSeriesVisible] = useState(false); const [marker, setMarker] = useState(null); const [coordinates, setCoordinates] = useState(null); const [groupedSeries, setGroupedSeries] = useState(null); const [region, setRegion] = useState({ nmRegion: null, dareRegion: null }); const [selectedSeries, setSelectedSeries] = useState(null); const [submitedModalVisible, setSubmitedModalVisible] = useState(false); const [keyboardVisible, setKeyboardVisible] = useState(false); const { data: suggestionData } = useGetSuggestionData(); const { data } = useGetDataFromPoint( token, coordinates?.lat, coordinates?.lng, coordinates ? true : false ); const { mutateAsync: submitSuggestion } = useSubmitSuggestionMutation(); const [tooltipVisible, setTooltipVisible] = useState(false); const mapRef = useRef(null); useEffect(() => { const keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', () => { setKeyboardVisible(true); }); const keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', () => { setKeyboardVisible(false); }); return () => { keyboardDidHideListener.remove(); keyboardDidShowListener.remove(); }; }, []); useEffect(() => { if (data && data.result === 'OK') { const nmRegion = data.nm ? suggestionData?.nm.find((item) => item.id === data.nm.id) : null; const dareRegion = data.dare ? suggestionData?.dare.find((item) => item.id === data.dare.id) : null; setRegion({ nmRegion, dareRegion }); setSelectedSeries(null); setIsModalVisible(true); } }, [data]); useEffect(() => { if (suggestionData && suggestionData.result === 'OK') { const groupedData = Object.keys(suggestionData.grouped).map((key) => ({ title: key, data: suggestionData.grouped[key] })); setGroupedSeries(groupedData); } }, [suggestionData]); const findPlace = async (placeId: string) => { const response = await axios.get( `https://maps.googleapis.com/maps/api/place/details/json?place_id=${placeId}&key=${GOOGLE_MAP_PLACES_APIKEY}` ); return { url: response.data.result.url, name: response.data.result.name }; }; const animateMapToRegion = (latitude: number, longitude: number) => { const region = { latitude, longitude, latitudeDelta: 0.015, longitudeDelta: 0.0121 }; mapRef.current?.animateToRegion(region, 500); }; const handlePoiClick = async (event: any) => { const { placeId, coordinate } = event.nativeEvent; const { url, name } = await findPlace(placeId); setMarker({ placeId, name, coordinate, url }); setCoordinates({ lat: coordinate.latitude, lng: coordinate.longitude }); animateMapToRegion(coordinate.latitude, coordinate.longitude); }; const handlePlaceSelection = (data: GooglePlaceData, details: GooglePlaceDetail | null) => { if (details) { const { geometry } = details; setMarker({ placeId: data.place_id, name: data.structured_formatting.main_text, coordinate: { latitude: geometry.location.lat, longitude: geometry.location.lng }, url: details.url }); setCoordinates({ lat: geometry.location.lat, lng: geometry.location.lng }); animateMapToRegion(geometry.location.lat, geometry.location.lng); } }; const renderGroup = ({ item }: { item: { title: string; data: Series[] } }) => { return ( {item.title !== '-' && {item.title}} {item.data.map((series: Series) => ( { setSelectedSeries(series); setSeriesVisible(false); }} > {series.name} ))} ); }; const handleClose = () => { setSubmitedModalVisible(false); setIsModalVisible(false); navigation.goBack(); }; return (
setTooltipVisible(false)} content={ We value the enthusiasm of travelers who want to share their favorite places with the NomadMania community. Every suggestion reflects passion for exploration, and we appreciate the time and thought that goes into each contribution to the series. {'\n\n'}At the same time, not all submissions will be added to the map. We have a dedicated team that is tasked to review all suggestions and maintain an overall balance across regions and topics and to prevent overcrowding in certain areas. {'\n\n'}For this reason, even good suggestions may occasionally be declined. We hope you understand this approach, and we thank you for helping us shape a map that highlights the richness of travel across the world.{'\n\n'}Best regards, the Series Team } contentStyle={{ backgroundColor: Colors.WHITE }} backgroundColor="transparent" allowChildInteraction={false} placement="bottom" > setTooltipVisible(true)} style={{ width: 30 }}> } /> ( )} /> {marker && ( setIsModalVisible(true)} /> )} setIsModalVisible(false)} style={styles.modal} statusBarTranslucent={true} presentationStyle="overFullScreen" > { const { comment, name, link, lat, lng, item } = values; if (!selectedSeries) return; const submitData: SubmitSuggestionTypes = { token, comment, name, link, lat, lng, item, nm: region.nmRegion.id, dare: region.dareRegion ? region.dareRegion.id : 0, series: selectedSeries.id }; submitSuggestion(submitData, { onSuccess: () => { setSubmitedModalVisible(true); } }); }} > {(props) => (