Przeglądaj źródła

multiple series

Viktoriia 1 tydzień temu
rodzic
commit
ecf83bc9f8

+ 5 - 0
src/components/ErrorModal/index.tsx

@@ -31,6 +31,11 @@ export const ErrorModal = () => {
       storage.remove('currentUserData');
       storage.remove('showNomads');
       storage.remove('filterSettings');
+      storage.remove('visitedRegions');
+      storage.remove('visitedCountries');
+      storage.remove('visitedDares');
+      storage.remove('visitedSeries');
+
       updateNotificationStatus();
       updateUnreadMessagesCount();
 

+ 5 - 0
src/components/MenuDrawer/index.tsx

@@ -59,6 +59,11 @@ export const MenuDrawer = (props: any) => {
     storage.remove('currentUserData');
     storage.remove('showNomads');
     storage.remove('filterSettings');
+    storage.remove('visitedRegions');
+    storage.remove('visitedCountries');
+    storage.remove('visitedDares');
+    storage.remove('visitedSeries');
+
     updateNotificationStatus();
     updateUnreadMessagesCount();
     navigation.dispatch(

+ 177 - 0
src/screens/InAppScreens/MapScreen/MultipleSeriesModal/index.tsx

@@ -0,0 +1,177 @@
+import React, { useRef, useState } from 'react';
+import { View, Text, Image, StyleSheet, TouchableOpacity, Platform } from 'react-native';
+import ActionSheet, { SheetManager } from 'react-native-actions-sheet';
+import { Colors } from 'src/theme';
+import { getFontSize } from 'src/utils';
+import { FlashList } from '@shopify/flash-list';
+
+const MultipleSeriesModal = () => {
+  const [seriesData, setSeriesData] = useState<any>(null);
+  const [markers, setMarkers] = useState<any[]>([]);
+
+  const shouldOpenWarningModalRef = useRef(false);
+
+  const handleSheetOpen = (payload: any) => {
+    setSeriesData(payload);
+    setMarkers(payload?.markers || []);
+  };
+
+  const handleToggleSeries = (item: any) => {
+    if (!seriesData) return;
+
+    if (!seriesData.token) {
+      shouldOpenWarningModalRef.current = true;
+      SheetManager.hide('multiple-series-modal');
+
+      return;
+    }
+    seriesData.setSelectedMarker(item);
+
+    seriesData.toggleSeries(item);
+    setMarkers((prevMarkers) =>
+      prevMarkers.map((marker) =>
+        marker.id === item.id ? { ...marker, visited: item.visited === 1 ? 0 : 1 } : marker
+      )
+    );
+  };
+
+  const handleItemPress = (item: any) => {
+    if (!seriesData) return;
+
+    seriesData.setSelectedMarker(item);
+    SheetManager.hide('multiple-series-modal');
+  };
+
+  return (
+    <ActionSheet
+      id="multiple-series-modal"
+      gestureEnabled={Platform.OS === 'ios'}
+      onBeforeShow={(sheetRef) => {
+        const payload = sheetRef || null;
+        handleSheetOpen(payload);
+      }}
+      onClose={() => {
+        if (shouldOpenWarningModalRef.current) {
+          if (!seriesData) return;
+
+          shouldOpenWarningModalRef.current = false;
+          seriesData.setIsWarningModalVisible(true);
+        }
+      }}
+      containerStyle={styles.sheetContainer}
+      defaultOverlayOpacity={0.5}
+    >
+      {seriesData && (
+        <View style={styles.container}>
+          <FlashList
+            data={markers}
+            keyExtractor={(item, index) => item.id.toString() + index.toString()}
+            showsVerticalScrollIndicator={false}
+            renderItem={({ item }) => (
+              <TouchableOpacity style={styles.option} onPress={() => handleItemPress(item)}>
+                <View style={styles.imageContainer}>
+                  <Image
+                    source={{ uri: item.icon?.uri || '' }}
+                    style={styles.icon}
+                    resizeMode="contain"
+                  />
+                  <View style={{ justifyContent: 'space-between', flex: 1 }}>
+                    <Text style={styles.name}>{item.series_name}</Text>
+                    <Text style={styles.description}>{item.name}</Text>
+                  </View>
+                </View>
+
+                <TouchableOpacity
+                  onPress={() => handleToggleSeries(item)}
+                  style={[styles.markButton, item.visited === 1 && styles.visitedButton]}
+                >
+                  {item.visited === 1 ? (
+                    <View style={styles.completedContainer}>
+                      <Text style={[styles.calloutButtonText, { color: Colors.DARK_BLUE }]}>
+                        Completed
+                      </Text>
+                    </View>
+                  ) : (
+                    <Text style={styles.calloutButtonText}>To Complete</Text>
+                  )}
+                </TouchableOpacity>
+              </TouchableOpacity>
+            )}
+            estimatedItemSize={50}
+          />
+        </View>
+      )}
+    </ActionSheet>
+  );
+};
+
+const styles = StyleSheet.create({
+  sheetContainer: {
+    height: '85%',
+    borderTopLeftRadius: 15,
+    borderTopRightRadius: 15
+  },
+  container: {
+    minHeight: 200,
+    height: '100%',
+    backgroundColor: 'white',
+    paddingHorizontal: 16,
+    paddingTop: 8,
+    gap: 16
+  },
+  completedContainer: { flexDirection: 'row', alignItems: 'center', gap: 6 },
+  calloutButtonText: {
+    color: Colors.WHITE,
+    fontSize: getFontSize(13),
+    fontWeight: '700'
+  },
+  icon: {
+    width: 32,
+    height: 32
+  },
+  markButton: {
+    paddingHorizontal: 12,
+    paddingVertical: 6,
+    backgroundColor: Colors.ORANGE,
+    borderRadius: 6,
+    height: 30,
+    alignItems: 'center',
+    justifyContent: 'center'
+  },
+  visitedButton: {
+    backgroundColor: Colors.WHITE,
+    borderWidth: 1,
+    borderColor: Colors.BORDER_LIGHT
+  },
+  option: {
+    flexDirection: 'row',
+    alignItems: 'center',
+    justifyContent: 'space-between',
+    backgroundColor: Colors.FILL_LIGHT,
+    paddingVertical: 8,
+    paddingHorizontal: 12,
+    borderRadius: 8,
+    marginBottom: 6
+  },
+  imageContainer: {
+    flexDirection: 'row',
+    alignItems: 'center',
+    gap: 8,
+    flex: 1,
+    marginRight: 8
+  },
+  name: {
+    fontSize: getFontSize(14),
+    fontFamily: 'montserrat-700',
+    color: Colors.DARK_BLUE,
+    flex: 1
+  },
+  description: {
+    fontSize: getFontSize(12),
+    fontWeight: '600',
+    color: Colors.DARK_BLUE,
+    flex: 1
+  }
+});
+
+export default MultipleSeriesModal;

+ 37 - 12
src/screens/InAppScreens/MapScreen/index.tsx

@@ -90,6 +90,8 @@ import {
   startBackgroundLocationUpdates,
   stopBackgroundLocationUpdates
 } from 'src/utils/backgroundLocation';
+import { SheetManager } from 'react-native-actions-sheet';
+import MultipleSeriesModal from './MultipleSeriesModal';
 
 const clusteredUsersIcon = require('assets/icons/icon-clustered-users.png');
 const defaultUserAvatar = require('assets/icon-user-share-location-solid.png');
@@ -289,7 +291,6 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
   const tabBarHeight = useBottomTabBarHeight();
   const userId = storage.get('uid', StoreType.STRING) as string;
   const token = storage.get('token', StoreType.STRING) as string;
-  const cleanupTimeoutRef = useRef<any>(null);
 
   const [isConnected, setIsConnected] = useState<boolean>(true);
   const netInfo = useConnection();
@@ -576,17 +577,6 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
         refetchVisitedCountries();
         refetchVisitedDare();
       }
-
-      return () => {
-        if (cleanupTimeoutRef.current) {
-          clearTimeout(cleanupTimeoutRef.current);
-        }
-
-        cleanupTimeoutRef.current = setTimeout(() => {
-          setImages({});
-          processedImages.current.clear();
-        }, 1000);
-      };
     }, [navigation, token])
   );
 
@@ -1228,7 +1218,41 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
 
   const handleMarkerPress = async (event: any) => {
     const { features } = event;
+
     if (features?.length) {
+      if (features.length > 1) {
+        const markers = features
+          .map((f: any) => {
+            const markerCoordinates = f.geometry.coordinates;
+            if (!markerCoordinates) return null;
+
+            return {
+              coordinates: markerCoordinates,
+              name: f.properties.name,
+              icon: images[f.properties.series_id],
+              description: f.properties.description,
+              series_name: f.properties.series_name,
+              visited: seriesVisited.includes(f.properties.id) ? 1 : 0,
+              series_id: f.properties.series_id,
+              id: f.properties.id
+            };
+          })
+          .sort((a: any, b: any) => a.visited - b.visited);
+
+        SheetManager.show('multiple-series-modal', {
+          payload: {
+            markers,
+            token,
+            toggleSeries,
+            setSelectedMarker,
+            setIsWarningModalVisible
+          } as any
+        });
+
+        setSelectedUser(null);
+        return;
+      }
+
       const selectedFeature = features[0];
       const { coordinates } = selectedFeature.geometry;
       const visited = seriesVisited.includes(selectedFeature.properties.id) ? 1 : 0;
@@ -1997,6 +2021,7 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
         }}
         message="NomadMania app needs location permissions to function properly. Open settings?"
       />
+      <MultipleSeriesModal />
     </SafeAreaView>
   );
 };

+ 5 - 0
src/screens/InAppScreens/ProfileScreen/Profile/edit-personal-info.tsx

@@ -119,6 +119,11 @@ export const EditPersonalInfo = () => {
     storage.remove('currentUserData');
     storage.remove('showNomads');
     storage.remove('filterSettings');
+    storage.remove('visitedRegions');
+    storage.remove('visitedCountries');
+    storage.remove('visitedDares');
+    storage.remove('visitedSeries');
+
     updateNotificationStatus();
     updateUnreadMessagesCount();
     navigation.dispatch(