Bläddra i källkod

drawer menu and region selector fix

Viktoriia 1 år sedan
förälder
incheckning
c52282b7f9

+ 19 - 1
Route.tsx

@@ -6,6 +6,7 @@ import * as Notifications from 'expo-notifications';
 
 import { createStackNavigator } from '@react-navigation/stack';
 import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
+import { createDrawerNavigator } from '@react-navigation/drawer';
 
 import WelcomeScreen from './src/screens/WelcomeScreen';
 import LoginScreen from './src/screens/LoginScreen';
@@ -53,6 +54,7 @@ import { openDatabases } from './src/db';
 import TabBarButton from './src/components/TabBarButton';
 import { ParamListBase, RouteProp } from '@react-navigation/native';
 import setupDatabaseAndSync from 'src/database';
+import { MenuDrawer } from 'src/components';
 
 const ScreenStack = createStackNavigator();
 const BottomTab = createBottomTabNavigator();
@@ -126,6 +128,22 @@ const Route = () => {
     cardStyle: { backgroundColor: 'white' }
   });
 
+  const MapDrawer = createDrawerNavigator();
+
+  function MapDrawerNavigator() {
+    return (
+      <MapDrawer.Navigator
+        drawerContent={(props) => <MenuDrawer {...props} />}
+      >
+        <MapDrawer.Screen
+          options={{ headerShown: false }}
+          name="MapDrawerScreen"
+          component={MapScreen}
+        />
+      </MapDrawer.Navigator>
+    );
+  }
+
   return (
     <ScreenStack.Navigator
       screenOptions={{ headerShown: false, cardStyle: { backgroundColor: 'white' }}}
@@ -143,7 +161,7 @@ const Route = () => {
       <ScreenStack.Screen name={NAVIGATION_PAGES.IN_APP}>
         {() => (
           <BottomTab.Navigator screenOptions={screenOptions}>
-            <BottomTab.Screen name={NAVIGATION_PAGES.MAP_TAB} component={MapScreen} />
+            <BottomTab.Screen name={NAVIGATION_PAGES.MAP_TAB} component={MapDrawerNavigator} />
             <BottomTab.Screen name={NAVIGATION_PAGES.IN_APP_TRAVELLERS_TAB}>
               {() => (
                 <ScreenStack.Navigator screenOptions={screenOptions}>

+ 3 - 0
babel.config.js

@@ -2,5 +2,8 @@ module.exports = function(api) {
   api.cache(true);
   return {
     presets: ['babel-preset-expo'],
+    plugins: [
+      'react-native-reanimated/plugin',
+    ],
   };
 };

+ 3 - 1
package.json

@@ -16,6 +16,7 @@
     "@react-native-community/masked-view": "^0.1.11",
     "@react-native-community/netinfo": "9.3.10",
     "@react-navigation/bottom-tabs": "^6.5.11",
+    "@react-navigation/drawer": "^6.6.15",
     "@react-navigation/material-top-tabs": "^6.6.5",
     "@react-navigation/native": "^6.1.9",
     "@react-navigation/native-stack": "^6.9.17",
@@ -61,7 +62,8 @@
     "react-native-svg": "13.9.0",
     "react-native-tab-view": "^3.5.2",
     "yup": "^1.3.3",
-    "zustand": "^4.4.7"
+    "zustand": "^4.4.7",
+    "react-native-reanimated": "~3.3.0"
   },
   "devDependencies": {
     "@babel/core": "^7.20.0",

+ 16 - 7
src/components/FlatList/index.tsx

@@ -6,6 +6,7 @@ import { Item, ItemData } from './item';
 import { useGetRegionsWithFlagQuery } from '@api/regions';
 import { useFocusEffect } from '@react-navigation/native';
 import { Loading } from '../Loading';
+import { FlashList } from '@shopify/flash-list';
 
 type Props = {
   itemObject: (object: any) => void;
@@ -79,14 +80,22 @@ export const FlatList: FC<Props> = ({ itemObject, initialData, date }) => {
   return (
     <SafeAreaView style={styles.container}>
       {!date && (
-        <Input
-          inputMode={'search'}
-          placeholder={'Search'}
-          onChange={(text) => searchFilter(text)}
-          value={search}
-        />
+        <View style={{ marginTop: 12 }}>
+          <Input
+            inputMode={'search'}
+            placeholder={'Search'}
+            onChange={(text) => searchFilter(text)}
+            value={search}
+          />
+        </View>
       )}
-      <List
+      <FlashList
+        viewabilityConfig={{
+          waitForInteraction: true,
+          itemVisiblePercentThreshold: 50,
+          minimumViewTime: 1000
+        }}
+        estimatedItemSize={50}
         data={filteredData as ItemData[]}
         renderItem={renderItem}
         keyExtractor={(item) => (date ? item.toString() : item.id.toString())}

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

@@ -0,0 +1,120 @@
+import React, { useState } from 'react';
+import { View, Image, Linking } from 'react-native';
+import { CommonActions, useNavigation } from '@react-navigation/native';
+
+import { WarningModal } from '../WarningModal';
+import { MenuButton } from '../MenuButton';
+import { styles } from './styles';
+import { StoreType, storage } from 'src/storage';
+import { useDeleteUserMutation } from '@api/app';
+import { Colors } from 'src/theme';
+import { NAVIGATION_PAGES } from 'src/types';
+
+import MailIcon from '../../../assets/icons/mail.svg';
+import DocumentIcon from '../../../assets/icons/document.svg';
+import ExitIcon from '../../../assets/icons/exit.svg';
+import UserXMark from '../../../assets/icons/user-xmark.svg';
+
+export const MenuDrawer = (props: any) => {
+  const { mutate: deleteUser } = useDeleteUserMutation();
+  const token = storage.get('token', StoreType.STRING) as string;
+  const navigation = useNavigation();
+  const [modalInfo, setModalInfo] = useState({
+    visible: false,
+    type: 'confirm',
+    message: '',
+    action: () => {}
+  });
+
+  const openModal = (type: string, message: string, action: any) => {
+    setModalInfo({
+      visible: true,
+      type,
+      message,
+      action
+    });
+  };
+
+  const closeModal = () => {
+    setModalInfo({ ...modalInfo, visible: false });
+  };
+
+  const handleLogout = () => {
+    storage.remove('token');
+    storage.remove('uid');
+    navigation.dispatch(
+      CommonActions.reset({
+        index: 1,
+        routes: [{ name: NAVIGATION_PAGES.WELCOME }]
+      })
+    );
+  };
+
+  const handleDeleteAccount = () => {
+    deleteUser({ token }, { onSuccess: handleLogout });
+  };
+
+  return (
+    <>
+      <View style={styles.container}>
+        <View style={{ flex: 1 }}>
+          <View style={styles.logoContainer}>
+            <Image source={require('../../../assets/logo-ua.png')} style={styles.logo} />
+          </View>
+          <View style={{ top: 12 }}>
+            <MenuButton
+              label="Contact Us"
+              icon={<MailIcon fill={Colors.DARK_BLUE} width={20} height={20} />}
+              red={false}
+              buttonFn={() => Linking.openURL('https://nomadmania.com/contact/')}
+            />
+            <MenuButton
+              label="Terms & Conditions"
+              icon={<DocumentIcon fill={Colors.DARK_BLUE} width={20} height={20} />}
+              red={false}
+              buttonFn={() => Linking.openURL('https://nomadmania.com/terms/')}
+            />
+          </View>
+        </View>
+
+        {token ? (
+          <View style={styles.bottomMenu}>
+            <MenuButton
+              label="Logout"
+              icon={<ExitIcon fill={Colors.RED} width={20} height={20} />}
+              red={true}
+              buttonFn={() =>
+                openModal('confirm', 'Are you sure you want to logout?', handleLogout)
+              }
+            />
+            <MenuButton
+              label="Delete account"
+              icon={<UserXMark fill={Colors.RED} width={20} height={20} />}
+              red={true}
+              buttonFn={() =>
+                openModal(
+                  'confirm',
+                  'Are you sure you want to delete your account?',
+                  handleDeleteAccount
+                )
+              }
+            />
+          </View>
+        ) : (
+          <View style={styles.bottomMenu} />
+        )}
+      </View>
+
+      <WarningModal
+        isVisible={modalInfo.visible}
+        onClose={closeModal}
+        type={modalInfo.type}
+        message={modalInfo.message}
+        action={() => {
+          modalInfo.action();
+          closeModal();
+        }}
+      />
+    </>
+  );
+};

+ 21 - 0
src/components/MenuDrawer/styles.tsx

@@ -0,0 +1,21 @@
+import { StyleSheet } from 'react-native';
+
+export const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    margin: '10%'
+  },
+  logoContainer: {
+    flex: 1,
+    justifyContent: 'center',
+    alignItems: 'center'
+  },
+  bottomMenu: {
+    flex: 1,
+    justifyContent: 'flex-end'
+  },
+  logo: {
+    width: 150,
+    height: 150
+  }
+});

+ 1 - 0
src/components/index.ts

@@ -16,3 +16,4 @@ export * from './Loading';
 export * from './WarningModal';
 export * from './HorizontalTabView';
 export * from './EditNmModal';
+export * from './MenuDrawer';

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

@@ -611,9 +611,9 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation }) => {
         </>
       ) : (
         <>
-          {/* <TouchableOpacity style={[styles.cornerButton, styles.topLeftButton]}>
+          <TouchableOpacity style={[styles.cornerButton, styles.topRightButton]} onPress={() => (navigation as any)?.openDrawer()}>
             <MenuIcon />
-          </TouchableOpacity> */}
+          </TouchableOpacity>
 
           {/* <TouchableOpacity style={[styles.cornerButton, styles.topRightButton]}>
             <SearchIcon fill={'#0F3F4F'} />

+ 1 - 1
src/screens/InAppScreens/MapScreen/style.tsx

@@ -43,7 +43,7 @@ export const styles = StyleSheet.create({
     right: 16,
   },
   bottomButton: {
-    bottom: Platform.OS == 'android' ? 80 : 100,
+    bottom: Platform.OS == 'android' ? 24 : 32,
     width: 42,
     height: 42,
     borderRadius: 21,

+ 1 - 1
src/screens/InAppScreens/ProfileScreen/index.tsx

@@ -110,7 +110,7 @@ const ProfileScreen: FC<Props> = ({ navigation, route }) => {
             {!isPublicView ? (
               <TouchableOpacity
                 style={styles.settings}
-                onPress={() => navigation.navigate(NAVIGATION_PAGES.SETTINGS)}
+                onPress={() => navigation.navigate(NAVIGATION_PAGES.EDIT_PERSONAL_INFO)}
               >
                 <GearIcon
                   width={20}