Viktoriia vor 10 Monaten
Ursprung
Commit
40e42f04ff

+ 16 - 0
Route.tsx

@@ -376,6 +376,22 @@ const Route = () => {
               options={regionViewScreenOptions}
             />
             <ScreenStack.Screen name={NAVIGATION_PAGES.MY_FRIENDS} component={MyFriendsScreen} />
+            <ScreenStack.Screen
+              name={NAVIGATION_PAGES.REGION_PREVIEW}
+              component={RegionViewScreen}
+              options={regionViewScreenOptions}
+            />
+            <ScreenStack.Screen
+              name={NAVIGATION_PAGES.USERS_LIST}
+              component={UsersListScreen}
+              options={regionViewScreenOptions}
+            />
+            <ScreenStack.Screen
+              name={NAVIGATION_PAGES.COUNTRY_PREVIEW}
+              component={CountryViewScreen}
+              options={regionViewScreenOptions}
+            />
+            <ScreenStack.Screen name={NAVIGATION_PAGES.ADD_PHOTO} component={AddPhotoScreen} />
           </ScreenStack.Navigator>
         )}
       </BottomTab.Screen>

+ 1 - 1
src/components/Input/index.tsx

@@ -60,7 +60,7 @@ export const Input: FC<Props> = ({
         style={[
           [styles.wrapper, formikError ? styles.inputError : null, { backgroundColor }],
           { flexDirection: 'row', alignItems: 'center' },
-          multiline ? { height: height ?? 100 } : { height: height ?? 44 }
+          multiline ? { minHeight: height ?? 100, height: 'auto' } : { height: height ?? 44 }
         ]}
       >
         {icon ? (

+ 5 - 2
src/contexts/NotificationContext.tsx

@@ -19,8 +19,11 @@ export const NotificationProvider = ({ children }: { children: React.ReactNode }
       try {
         const data = await fetchFriendsNotification(token as string);
         const isActive = data && data.active;
-        setIsNotificationActive(isActive as boolean);
-        storage.set('friendsNotification', isActive as boolean);
+        
+        if (typeof isActive === 'boolean') {
+          setIsNotificationActive(isActive);
+          storage.set('friendsNotification', isActive);
+        }
       } catch (error) {
         console.error('Failed to fetch notifications', error);
       }

+ 4 - 1
src/screens/InAppScreens/MapScreen/CountryViewScreen/index.tsx

@@ -95,6 +95,9 @@ const CountryViewScreen: FC<Props> = ({ navigation, route }) => {
 
         setSeries(data?.data?.series || []);
         setRoutes(staticGroups);
+        if (regionData?.id !== countryId) {
+          setRegionData(data?.data || {});
+        }
         setIsLoading(false);
       };
 
@@ -245,7 +248,7 @@ const CountryViewScreen: FC<Props> = ({ navigation, route }) => {
         )}
         <TouchableOpacity
           onPress={() => {
-            route.params?.isTravelsScreen
+            route.params?.isTravelsScreen || route.params?.isProfileScreen
               ? navigation.dispatch(
                   CommonActions.reset({
                     index: 1,

+ 4 - 1
src/screens/InAppScreens/MapScreen/RegionViewScreen/index.tsx

@@ -127,6 +127,9 @@ const RegionViewScreen: FC<Props> = ({ navigation, route }) => {
         setName([regionName, subname]);
         setSeries(data?.data?.series || []);
         setRoutes(staticGroups);
+        if (regionData?.id !== regionId) {
+          setRegionData(data?.data || {});
+        }
         setIsLoading(false);
       };
 
@@ -372,7 +375,7 @@ const RegionViewScreen: FC<Props> = ({ navigation, route }) => {
 
         <TouchableOpacity
           onPress={() => {
-            route.params?.isTravelsScreen
+            route.params?.isTravelsScreen || route.params?.isProfileScreen
               ? navigation.dispatch(
                   CommonActions.reset({
                     index: 1,

+ 6 - 6
src/screens/InAppScreens/MapScreen/index.tsx

@@ -470,7 +470,7 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
               { id: +countryId, token },
               {
                 onSuccess: (data) => {
-                  setUserData({ type: 'countries', ...data.data });
+                  setUserData({ type: 'countries', id: +countryId, ...data.data });
                   const bounds = turf.bbox(data.data.bbox);
                   const center = data.data.center;
                   const region = calculateMapCountry(bounds, center);
@@ -530,7 +530,7 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
             { region_id: +id, token: String(token) },
             {
               onSuccess: (data) => {
-                setUserData({ type: 'nm', ...data });
+                setUserData({ type: 'nm', id: +id, ...data });
               }
             }
           ));
@@ -552,7 +552,7 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
             { dare_id: +id, token: String(token) },
             {
               onSuccess: (data) => {
-                setUserData({ type: 'dare', ...data });
+                setUserData({ type: 'dare', id: +id, ...data });
               }
             }
           ));
@@ -591,7 +591,7 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
           { id: +id, token },
           {
             onSuccess: (data) => {
-              setUserData({ type: 'countries', ...data.data });
+              setUserData({ type: 'countries', id: +id, ...data.data });
               const bounds = turf.bbox(data.data.bbox);
               const center = data.data.center;
               const region = calculateMapCountry(bounds, center);
@@ -643,7 +643,7 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
             { region_id: +id, token: String(token) },
             {
               onSuccess: (data) => {
-                setUserData({ type: 'nm', ...data });
+                setUserData({ type: 'nm', id: +id, ...data });
               }
             }
           ));
@@ -666,7 +666,7 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
             { dare_id: +id, token: String(token) },
             {
               onSuccess: (data) => {
-                setUserData({ type: 'dare', ...data });
+                setUserData({ type: 'dare', id: +id, ...data });
               }
             }
           ));

+ 138 - 32
src/screens/InAppScreens/ProfileScreen/RegionsRenderer/index.tsx

@@ -1,5 +1,5 @@
-import React, { useCallback } from 'react';
-import { View, Text, Image, TouchableOpacity, ScrollView, Dimensions } from 'react-native';
+import React, { useCallback, useEffect, useState } from 'react';
+import { View, Text, Image, TouchableOpacity, ScrollView, Dimensions, Switch } from 'react-native';
 import { Colors } from 'src/theme';
 import { styles } from './styles';
 import { Loading } from 'src/components';
@@ -8,6 +8,8 @@ import CheckSvg from 'assets/icons/mark.svg';
 import CloseSVG from 'assets/icons/close.svg';
 import { API_HOST } from 'src/constants';
 import { FlashList } from '@shopify/flash-list';
+import { useNavigation } from '@react-navigation/native';
+import { NAVIGATION_PAGES } from 'src/types';
 
 interface Mega {
   id: number;
@@ -20,6 +22,7 @@ interface Mega {
   }[];
   transits: number[];
   visits: number[];
+  total?: number;
 }
 
 interface Region {
@@ -39,12 +42,69 @@ const RegionsRenderer = ({
   regions: any;
   setIsModalVisible: (value: boolean) => void;
 }) => {
+  const navigation = useNavigation();
   const flashlistConfig = {
     waitForInteraction: true,
     itemVisiblePercentThreshold: 50,
     minimumViewTime: 1000
   };
   const isSmallWidth = Dimensions.get('window').width < 383;
+  const [showAll, setShowAll] = useState(true);
+  const [filteredRegions, setFilteredRegions] = useState<any[]>([]);
+  const [filteredMegaregions, setFilteredMegaregions] = useState<any[]>([]);
+  const disabled =
+    type === 'whs' || type === 'tcc' || type === 'un' || type === 'unp' ? true : false;
+
+  useEffect(() => {
+    if (!regions?.data) return;
+
+    if (showAll) {
+      switch (type) {
+        case 'nm':
+        case 'mqp':
+          setFilteredMegaregions(regions.data.megaregions);
+          break;
+        case 'un':
+        case 'unp':
+        case 'slow':
+        case 'yes':
+        case 'tcc':
+          setFilteredRegions(regions.data[0]);
+          break;
+        case 'whs':
+          setFilteredRegions(regions.data);
+          break;
+      }
+    } else {
+      switch (type) {
+        case 'nm':
+        case 'mqp':
+          const filteredMegaregions = regions.data?.megaregions
+            ?.map((item: Mega) => ({
+              ...item,
+              regions: item.regions.filter((region) => item.visits.includes(region.id)),
+              total: item.regions.length
+            }))
+            ?.filter((item: Mega) => item.regions.length > 0);
+
+          setFilteredMegaregions(filteredMegaregions);
+          break;
+        case 'un':
+        case 'unp':
+        case 'tcc':
+          setFilteredRegions(
+            regions.data[0].filter((item: Region) => regions.data[1].includes(item.name))
+          );
+          break;
+        case 'slow':
+          setFilteredRegions(regions.data[0].filter((item: any) => item.visited === 1));
+          break;
+        case 'whs':
+          setFilteredRegions(regions.data.filter((item: any) => item.visited));
+          break;
+      }
+    }
+  }, [showAll, regions]);
 
   const getOpacity = useCallback(
     (item: any, mega?: Mega) => {
@@ -67,10 +127,49 @@ const RegionsRenderer = ({
     [type, regions?.data]
   );
 
+  const handlePress = (item: any) => {
+    switch (type) {
+      case 'nm':
+      case 'mqp':
+        setIsModalVisible(false);
+        navigation.navigate(
+          ...([
+            NAVIGATION_PAGES.REGION_PREVIEW,
+            {
+              regionId: item.id,
+              type: type === 'nm' ? 'nm' : 'dare',
+              disabled: false,
+              isProfileScreen: true
+            }
+          ] as never)
+        );
+        break;
+      case 'slow':
+      case 'yes':
+        setIsModalVisible(false);
+        navigation.navigate(
+          ...([
+            NAVIGATION_PAGES.COUNTRY_PREVIEW,
+            {
+              regionId: type === 'slow' ? item.country_id : item.id,
+              type: 'country',
+              disabled: false,
+              isProfileScreen: true
+            }
+          ] as never)
+        );
+        break;
+    }
+  };
+
   const renderRegion = useCallback(
     (item: any, mega?: Mega) => {
       return (
-        <View style={[styles.regionRow, { opacity: getOpacity(item, mega) }]}>
+        <TouchableOpacity
+          style={[styles.regionRow, { opacity: getOpacity(item, mega) }]}
+          onPress={() => handlePress(item)}
+          disabled={disabled}
+        >
           <View
             style={[
               styles.flags,
@@ -164,7 +263,7 @@ const RegionsRenderer = ({
               </View>
             </View>
           )}
-        </View>
+        </TouchableOpacity>
       );
     },
     [getOpacity, regions?.data, type]
@@ -180,8 +279,8 @@ const RegionsRenderer = ({
               {item.name}
               <Text style={{ fontWeight: '600' }}>
                 {' '}
-                - {item.visits.length}/{item.regions.length} (
-                {((item.visits.length * 100) / item.regions.length).toFixed(2)}%)
+                - {item.visits.length}/{item?.total ?? item.regions.length} (
+                {((item.visits.length * 100) / (item?.total ?? item.regions.length)).toFixed(2)}%)
               </Text>
             </Text>
             {type === 'nm' && (
@@ -231,8 +330,27 @@ const RegionsRenderer = ({
   );
 
   const renderContent = () => {
-    const renderHeader = (headerText: string) => (
-      <RegionsModalHeader textHeader={headerText} onRequestClose={() => setIsModalVisible(false)} />
+    const renderHeader = (headerText: string, rightElement: boolean) => (
+      <RegionsModalHeader
+        textHeader={headerText}
+        onRequestClose={() => setIsModalVisible(false)}
+        rightElement={
+          rightElement ? (
+            <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
+              <Text style={{ color: Colors.DARK_BLUE, fontSize: 12, fontWeight: '600' }}>
+                Show/Hide All
+              </Text>
+              <Switch
+                trackColor={{ false: Colors.LIGHT_GRAY, true: Colors.DARK_BLUE }}
+                thumbColor={Colors.WHITE}
+                onValueChange={() => setShowAll(!showAll)}
+                value={showAll}
+                style={{ transform: 'scale(0.8)' }}
+              />
+            </View>
+          ) : null
+        }
+      />
     );
 
     switch (type) {
@@ -240,11 +358,11 @@ const RegionsRenderer = ({
       case 'mqp':
         return (
           <>
-            {renderHeader(type === 'nm' ? 'NM' : 'DARE')}
+            {renderHeader(type === 'nm' ? 'NM' : 'DARE', true)}
             <FlashList
               viewabilityConfig={flashlistConfig}
               estimatedItemSize={4000}
-              data={regions.data.megaregions}
+              data={filteredMegaregions}
               renderItem={renderMegaregion}
               keyExtractor={(megaregion) => megaregion?.id?.toString()}
               showsVerticalScrollIndicator={false}
@@ -258,11 +376,11 @@ const RegionsRenderer = ({
       case 'tcc':
         return (
           <>
-            {renderHeader(type === 'un' ? 'UN' : type === 'unp' ? 'UN+' : 'TCC')}
+            {renderHeader(type === 'un' ? 'UN' : type === 'unp' ? 'UN+' : 'TCC', true)}
             <FlashList
               viewabilityConfig={flashlistConfig}
               estimatedItemSize={50}
-              data={regions.data[0]}
+              data={filteredRegions}
               renderItem={(region) => renderRegion(region.item)}
               keyExtractor={(region: Region) => region.name}
               showsVerticalScrollIndicator={false}
@@ -285,11 +403,11 @@ const RegionsRenderer = ({
       case 'slow':
         return (
           <>
-            {renderHeader('SLOW')}
+            {renderHeader('SLOW', true)}
             <FlashList
               viewabilityConfig={flashlistConfig}
               estimatedItemSize={50}
-              data={regions.data[0]}
+              data={filteredRegions}
               renderItem={(region) => renderRegion(region.item)}
               keyExtractor={(region: Region) => region.country_id.toString()}
               showsVerticalScrollIndicator={false}
@@ -301,29 +419,17 @@ const RegionsRenderer = ({
                     <View style={{ flexDirection: 'row', flex: 1 }}>
                       <View style={styles.slow}>
                         <Text style={styles.alignCenter}>
-                          <Text
-                            style={[styles.megaregionTitle, { fontSize: 12 }]}
-                          >
-                            11+
-                          </Text>
+                          <Text style={[styles.megaregionTitle, { fontSize: 12 }]}>11+</Text>
                         </Text>
                       </View>
                       <View style={styles.slow}>
                         <Text style={styles.alignCenter}>
-                          <Text
-                            style={[styles.megaregionTitle, { fontSize: 12 }]}
-                          >
-                            31+
-                          </Text>
+                          <Text style={[styles.megaregionTitle, { fontSize: 12 }]}>31+</Text>
                         </Text>
                       </View>
                       <View style={styles.slow}>
                         <Text style={styles.alignCenter}>
-                          <Text
-                            style={[styles.megaregionTitle, { fontSize: 12 }]}
-                          >
-                            101+
-                          </Text>
+                          <Text style={[styles.megaregionTitle, { fontSize: 12 }]}>101+</Text>
                         </Text>
                       </View>
                     </View>
@@ -348,7 +454,7 @@ const RegionsRenderer = ({
         };
         return (
           <>
-            {renderHeader('YES')}
+            {renderHeader('YES', false)}
             <FlashList
               viewabilityConfig={flashlistConfig}
               estimatedItemSize={50}
@@ -390,11 +496,11 @@ const RegionsRenderer = ({
       case 'whs':
         return (
           <>
-            {renderHeader('WHS')}
+            {renderHeader('WHS', true)}
             <FlashList
               viewabilityConfig={flashlistConfig}
               estimatedItemSize={50}
-              data={regions.data}
+              data={filteredRegions}
               renderItem={(region) => renderRegion(region.item)}
               keyExtractor={(region: Region) => region.name}
               showsVerticalScrollIndicator={false}

+ 0 - 1
src/screens/InAppScreens/TravelsScreen/AddNewFixerScreen/index.tsx

@@ -305,7 +305,6 @@ const AddNewFixerScreen = ({ route }: { route: any }) => {
                 onBlur={handleBlur('comment')}
                 value={values.comment}
                 header="Comment"
-                height={64}
                 multiline={true}
                 formikError={touched.comment && errors.comment}
               />

+ 1 - 0
src/screens/InAppScreens/TravelsScreen/Components/CountryItem/index.tsx

@@ -37,6 +37,7 @@ const CountryItem = React.memo(
         onPress={() => {
           setUserData({
             type: 'countries',
+            id: item.country_id,
             visited: Boolean(item.visited),
             slow11: item.slow11,
             slow31: item.slow31,

+ 1 - 0
src/screens/InAppScreens/TravelsScreen/DareScreen/index.tsx

@@ -92,6 +92,7 @@ const DareScreen = () => {
       onPress={() => {
         setUserData({
           type: 'dare',
+          id: item.id,
           region_flag: item.flag1,
           region_name: item.name,
           visited: +item.visited > 0

+ 1 - 0
src/screens/InAppScreens/TravelsScreen/RegionsScreen/index.tsx

@@ -154,6 +154,7 @@ const RegionsScreen = () => {
       onPress={() => {
         setUserData({
           type: 'nm',
+          id: item.id,
           region_flag: item.flag_1,
           region_name: item.region_name,
           best_visit_quality: item.quality,