Prechádzať zdrojové kódy

Shift drawer page/create tabs
https://dev.wormwood.com.sg/zentao/task-view-13.html
Remove the word Error
https://dev.wormwood.com.sg/zentao/task-view-17.html

vbea 2 rokov pred
rodič
commit
4bbb13a4f6

+ 1 - 0
Strides-APP/app.json

@@ -28,6 +28,7 @@
   },
   "company": "Strides YTL Pte. Ltd.",
   "v3": {
+    "drawer": true,
     "summary": true,
     "anzPayment": false,
     "vehicleModel": false,

+ 11 - 4
Strides-APP/app/components/Toolbar.js

@@ -2,20 +2,27 @@ import React from 'react';
 import { Image, Pressable, StyleSheet, View } from 'react-native';
 import TopChargeBackground from '../icons/TopChargeBackground';
 
-export const BackButton = ({color=pageTitleTint}) => {
+export const BackButton = ({style=Styles.backIcon, color=pageTitleTint, children, onPress}) => {
   return (
     <Pressable
       style={({pressed }) => [
         (pressed && isIOS) && {
           opacity: 0.5
         },
-        Styles.backIcon
+        style
       ]}
       android_ripple = {rippleLessIcon}
       onPress={() => {
-        goBack();
+        if (onPress) {
+          onPress();
+        } else {
+          goBack();
+        }
       }}>
-      <BackIcon color={color}/>
+      { children
+      ? children
+      : <BackIcon color={color}/>
+      }
     </Pressable>
   )
 }

+ 1 - 1
Strides-APP/app/i18n/locales/en.js

@@ -63,7 +63,7 @@ export default {
     paynow: "PAYNOW",
     payPerUse: "Pay Per Use",
     privacyPolicy: "Privacy Policy",
-    profileSettings: "Profile Settings",
+    profileSettings: "My Account",
     publicRegister: "Public Registration",
     qrScan: "QR Scan",
     rating: "Your Rating",

BIN
Strides-APP/app/images/site/error-A1.jpg


BIN
Strides-APP/app/images/site/error-A4.jpg


BIN
Strides-APP/app/images/site/error-A5.jpg


BIN
Strides-APP/app/images/site/error-A9.jpg


+ 1 - 1
Strides-APP/app/pages/Router.js

@@ -17,7 +17,7 @@ import RegisterV3 from './sign/RegisterV3';
 import RegisterV4 from './sign/RegisterV4';
 import RegisterPublic from './sign/RegisterPublic';
 import RegisterDriver from './sign/RegisterDriver';
-import Home from './home/Drawer';
+import Home from './home/Index';
 import Search from './search/SearchV2';
 import ChargeDetails from './charge/Details';
 import QRScan from './charge/QRScan';

+ 10 - 152
Strides-APP/app/pages/home/Drawer.js

@@ -1,164 +1,22 @@
 /**
- * 首页抽屉菜单
- * @邠心vbe on 2021/03/23
+ * 新版首页
+ * @邠心vbe on 2024/02/01
  */
-import React, { Component } from 'react';
+import React from 'react';
 import {View, Text, StyleSheet, Image} from 'react-native';
-import { createDrawerNavigator, DrawerContentScrollView } from '@react-navigation/drawer';
-import { Styles } from '../../components/Toolbar';
 import app from '../../../app.json';
-import Maps from './Home';
 import { PageList } from '../Router';
-import Dialog from '../../components/Dialog';
-import { setAccessToken } from '../../api/http';
-import { getStorageJsonSync, setStorage, setStorageJson } from '../../utils/storage';
 import Button from '../../components/Button';
-import { AutoLogin } from '../sign/Login';
+import { Styles } from '../../components/Toolbar';
+import TextView from '../../components/TextView';
 import apiCharge from '../../api/apiCharge';
 import { TouchableWithoutFeedback } from 'react-native-gesture-handler';
 import { toTopupPage } from '../payment/PaymentConfig';
 import utils from '../../utils/utils';
-import apiNotification from '../../api/apiNotification';
-import TextView from '../../components/TextView';
-
-const Drawer = createDrawerNavigator();
 
 const DEBUG = app.debug && !app.product;
 
-export default class Home extends Component {
-  constructor(props) {
-    super(props);
-    this.state = {
-      isLogin: false,
-      userInfo: {},
-      notificationCount: 0
-    }
-  }
-
-  componentDidMount() {
-    AutoLogin(() => {
-      this.setState({
-        userInfo: userInfo
-      });
-    });
-    this.props.navigation.addListener('focus', () => {
-      //console.log('drawer focus');
-      getUserInfo(info => {
-        this.setState({
-          userInfo: info
-        });
-      }, true);
-      if (app.modules.notifications && this.state.isLogin) {
-        this.getNotificationTotal();
-      }
-    });
-    /*BackHandler.addEventListener('hardwareBackPress', (e) => {
-      if (global.dialogId !== 0) {
-        Dialog.dismissLoading();
-        return true;
-      }
-      return false;
-    })*/
-  }
-
-  componentDidUpdate() {
-    const status = isLogin();
-    if (this.state.isLogin != status) {
-      this.setState({
-        isLogin: status
-      }, () => {
-        getUserInfo(info => {
-          this.setState({
-            userInfo: info
-          });
-          if (info.firebaseToken) {
-            let token = isIOS ? info.firebaseToken?.ios : info.firebaseToken?.android
-            if (notifyToken.token) {
-              utils.registerFirebaseToken(token ?? "");
-            }
-          }
-        }, true);
-        if (app.modules.notifications) {
-          this.getNotificationTotal();
-        }
-      });
-    }
-  }
-
-  async requestLogout() {
-    const data = await getStorageJsonSync('loginData');
-    if (data && data.email) {
-      delete data.password
-      setStorageJson('loginData', data);
-      setStorage('RegisterTokenDate', "");
-    }
-    global.userInfo = {}
-    this.setState({
-      isLogin: false,
-      userInfo: {}
-    });
-    setAccessToken('');
-    Dialog.dismissLoading();
-  }
-
-  getNotificationTotal() {
-    apiNotification.getUnreadTotal().then(res => {
-      if (res.data) {
-        this.setState({
-          notificationCount: res.data?.toBeReadCount ?? 0
-        })
-      } else {
-        this.setState({
-          notificationCount: 0
-        })
-      }
-    }).catch(err => {
-      this.setState({
-        notificationCount: 0
-      })
-    })
-  }
-
-  render () {
-    return (
-      <Drawer.Navigator
-        initialRouteName='maps'
-        drawerContent={props => 
-          <CustomerDrawerContent 
-            {...props}
-            isLogin={this.state.isLogin}
-            userInfo={this.state.userInfo}
-            onLogout={() => this.requestLogout()}
-            notificationCount={this.state.notificationCount}
-          />
-        }
-        drawerType={
-          global.$width >= 768 ? 'back' : 'front'
-        }
-        drawerStyle={{
-          width: $vw(75) > 320 ? 320 : $vw(75),
-          backgroundColor: colorLight
-        }}
-        screenOptions={{
-          headerShown: false
-        }}>
-        <Drawer.Screen name="maps" component={Maps} />
-      </Drawer.Navigator>
-    );
-  }
-};
-
-const CustomerDrawerContent = (props) => {
-  return (
-    <DrawerContentScrollView 
-      {...props}
-      canCancelContentTouches={true}>
-      <DrawerContent {...props}/>
-    </DrawerContentScrollView>
-  );
-}
-
-const DrawerContent = ({isLogin, userInfo, onLogout, notificationCount=0, navigation}) => {
+export default DrawerView = ({isLogin=false, userInfo, onLogout, notificationCount=0, navigation}) => {
   const getCharging = () => {
     Dialog.showProgressDialog();
     apiCharge.getUserCharging().then(res => {
@@ -181,13 +39,13 @@ const DrawerContent = ({isLogin, userInfo, onLogout, notificationCount=0, naviga
 
   const logout = () => {
     Dialog.showDialog({
-      title: 'Sign out',
-      message: 'Are you sure you want to sign out?',
+      title: $t('profile.signOut'),
+      message: $t('profile.tipSignOut'),
       callback: btn => {
-        if (btn == 'ok') {
+        if (btn == Dialog.BUTTON_OK) {
           Dialog.showProgressDialog();
           setTimeout(() => {
-            onLogout();
+            if (onLogout) onLogout();
           }, 500);
         }
       }

+ 433 - 0
Strides-APP/app/pages/home/DrawerV2.js

@@ -0,0 +1,433 @@
+/**
+ * 新版首页抽屉菜单
+ * @邠心vbe on 2024/02/01
+ */
+import React from 'react';
+import {View, Text, StyleSheet, Image} from 'react-native';
+import app from '../../../app.json';
+import { PageList } from '../Router';
+import Button from '../../components/Button';
+import { BackButton, Styles } from '../../components/Toolbar';
+import TextView from '../../components/TextView';
+import apiCharge from '../../api/apiCharge';
+import { TouchableWithoutFeedback } from 'react-native-gesture-handler';
+import { toTopupPage } from '../payment/PaymentConfig';
+import utils from '../../utils/utils';
+import Dialog from '../../components/Dialog';
+import { Path, Svg } from 'react-native-svg';
+
+const DEBUG = app.debug && !app.product;
+
+export default DrawerV2 = ({isLogin=false, userInfo, onLogout, sideCountInfo={}, navigation}) => {
+  const getCharging = () => {
+    Dialog.showProgressDialog();
+    apiCharge.getUserCharging().then(res => {
+      Dialog.dismissLoading();
+      if (res.data.sitePk) {
+        startPage(PageList.chargeDetailPage, {stationInfo: {id: res.data.sitePk}, action: 'view', from: PageList.home});
+        //startPage(PageList.chargeDetail, { stationInfo: {id: res.data.sitePk}, action: 'view'});
+      } else if (res.msg) {
+        toastShort(res.msg);
+      } else {
+        toastShort($t("drawer.noChargingSession"));
+      }
+    }).catch((err) => {
+      if (app.debug)
+        console.log(err);
+      Dialog.dismissLoading();
+      toastShort($t("drawer.noChargingSession"));
+    })
+  }
+
+  const logout = () => {
+    Dialog.showDialog({
+      title: $t('profile.signOut'),
+      message: $t('profile.tipSignOut'),
+      callback: btn => {
+        if (btn == Dialog.BUTTON_OK) {
+          Dialog.showProgressDialog();
+          setTimeout(() => {
+            if (onLogout) onLogout();
+          }, 500);
+        }
+      }
+    })
+  }
+
+  return (
+    <View style={styles.drawerView}>
+      <View style={styles.loginView}>
+        <View style={ui.flexcw}>
+          { (isLogin && userInfo.photoUrl)
+          ? <TouchableWithoutFeedback>
+              <Image
+                style={styles.avatar}
+                source={{uri: utils.getImageUrl(userInfo.photoUrl)}}/>
+            </TouchableWithoutFeedback>
+          : <TouchableWithoutFeedback>
+              <Image
+                style={styles.avatar}
+                source={require('../../images/user/ic-avatar-default.png')}/>
+            </TouchableWithoutFeedback>
+          }
+          <BackButton
+            style={styles.closeMenu}
+            onPress={() => navigation?.toggleDrawer()}>
+            <MaterialIcons
+              name="menu-open"
+              size={28}
+              color={pageTitleTint}/>
+          </BackButton>
+        </View>
+        { isLogin
+        ? <View
+            style={styles.nickViewStyle}>
+            <View style={ui.flex1}>
+              <TextView
+                style={styles.nickname}
+                ellipsizeMode='tail'
+                numberOfLines={1}>
+                { userInfo.nickName 
+                ? userInfo.nickName
+                : $t('drawer.logging')
+                }
+              </TextView>
+              <TextView
+                style={styles.emailText}
+                ellipsizeMode='tail'
+                numberOfLines={1}>{userInfo.email}</TextView>
+            </View>
+            <BackButton
+              onPress={logout}>
+              <MaterialIcons
+                size={26}
+                color={textPrimary}
+                name='exit-to-app'/>
+            </BackButton>
+          </View>
+        : <Button
+            style={styles.nickView}
+            viewStyle={styles.nickViewStyle}
+            onClick={() => startPage(PageList.login)}>
+            <TextView
+              style={styles.loginText}
+              ellipsizeMode='tail'
+              numberOfLines={1}>
+              {$t('drawer.sign')}
+            </TextView>
+            <FontAwesome
+              size={24}
+              color='#999'
+              name='angle-right'/>
+          </Button>
+        }
+      </View>
+      <View style={styles.divideLogin}></View>
+      { isLogin && <>
+        <Button
+          style={styles.itemButton}
+          viewStyle={styles.itemView}
+          onClick={() => startPage(PageList.profile)}>
+          <MaterialCommunityIcons
+            style={styles.icon}
+            name="account"
+            color={textPrimary}
+            size={24}/>
+          <TextView style={styles.label}>{$t('route.profileSettings')}</TextView>
+        </Button>
+        <Button
+          style={styles.itemButton}
+          viewStyle={styles.itemView}
+          onClick={() => getCharging()}>
+          <MaterialIcons
+            style={styles.icon}
+            name="ev-station"
+            color={textPrimary}
+            size={24}/>
+          <TextView style={styles.label}>{$t('drawer.charging')}</TextView>
+        </Button>
+        <Button
+          style={styles.itemButton}
+          viewStyle={styles.itemView}
+          onClick={() => {
+            startPage(PageList.wallet);
+          }}>
+          <MaterialCommunityIcons
+            style={styles.icon}
+            name="finance"
+            color={textPrimary}
+            size={24}/>
+          <TextView style={styles.label}>{$t('drawer.wallet')}</TextView>
+        </Button>
+        <Button
+          style={styles.itemButton}
+          viewStyle={styles.itemView}
+          onClick={() => toTopupPage()}>
+          <MaterialCommunityIcons
+            style={styles.icon}
+            name="wallet-plus"
+            color={textPrimary}
+            size={24}/>
+          <TextView style={styles.label}>{$t('drawer.topup')}</TextView>
+          <Text style={styles.balanceText2}>{userInfo.creditStr}</Text>
+        </Button></>
+      }
+
+      { (app.modules.notifications && isLogin) &&
+        <Button
+          style={styles.itemButton}
+          viewStyle={styles.itemView}
+          onClick={() => {
+            startPage(PageList.notification);
+          }}>
+          <MaterialCommunityIcons
+            style={styles.icon}
+            name="bell-badge"
+            color={textPrimary}
+            size={24}/>
+          <TextView style={styles.label}>{$t('route.notifications')}</TextView>
+          <TextView
+            style={styles.balanceText}
+            fixedAlign={false}>
+            <Text style={styles.balanceText2}>{sideCountInfo?.toBeReadCount || 0}</Text>  Unread
+          </TextView>
+        </Button>
+      }
+      { (app.modules.bookmarks && isLogin) &&
+        <Button
+          style={styles.itemButton}
+          viewStyle={styles.itemView}
+          onClick={() => {
+            startPage(PageList.bookmarks);
+          }}>
+          <MaterialCommunityIcons
+            style={styles.icon}
+            name="bookmark-check"
+            color={textPrimary}
+            size={24}/>
+          <TextView style={styles.label}>{$t('route.bookmarks')}</TextView>
+          <TextView
+            style={styles.balanceText}
+            fixedAlign={false}>
+            <Text style={styles.balanceText2}>{sideCountInfo?.bookMarkCount || 0}</Text>  Saved
+          </TextView>
+        </Button>
+      }
+      {/*附加功能-结束*/}
+      { (app.modules.membership && isLogin) &&
+        <Button
+          style={styles.itemButton}
+          viewStyle={styles.itemView}
+          onClick={() => {
+            startPage(PageList.membersList);
+          }}>
+          <Svg 
+            style={styles.icon}
+            width={24}
+            height={24}
+            viewBox='0 0 24 24'>
+            <Path
+              fill={textPrimary}
+              d="M7 4C4.8 4 3 5.8 3 8C3 10.2 4.8 12 7 12C9.2 12 11 10.2 11 8C11 5.8 9.2 4 7 4ZM7 10C5.9 10 5 9.1 5 8C5 6.9 5.9 6 7 6C8.1 6 9 6.9 9 8C9 9.1 8.1 10 7 10ZM0 18C0 15.8 3.1 14 7 14C8.5 14 9.9 14.3 11 14.7V17C10.2 16.5 8.8 16 7 16C3.8 16 2 17.4 2 18H11V20H0V18ZM22 4H15C13.9 4 13 4.9 13 6V18C13 19.1 13.9 20 15 20H22C23.1 20 24 19.1 24 18V6C24 4.9 23.1 4 22 4ZM22 18H15V6H22V18Z"/>
+          </Svg>
+          <TextView style={styles.label}>{$t('drawer.members')}</TextView>
+          <TextView
+            style={styles.balanceText}
+            fixedAlign={false}>
+            <Text style={styles.balanceText2}>{sideCountInfo?.membershipCount || 0}</Text>  Active
+          </TextView>
+        </Button>
+      }
+      {/* <Button
+        style={styles.itemButton}
+        viewStyle={styles.itemView}
+        onClick={() => {
+          startPage(PageList.feedback);
+        }}>
+        <MaterialCommunityIcons
+          style={styles.icon}
+          name="message-alert-outline"
+          color="#222"
+          size={24}/>
+        <TextView style={styles.label}>{$t('drawer.feedback')}</TextView>
+      </Button> */}
+      {/* <Button
+        style={styles.itemButton}
+        viewStyle={styles.itemView}
+        onClick={() => {
+          startPage(PageList.settings);
+        }}>
+        <MaterialIcons
+          style={styles.icon}
+          name="settings"
+          color="#222"
+          size={25}
+        />
+        <TextView style={styles.label}>{$t('drawer.settings')}</TextView>
+      </Button> */}
+      { app.modules.support &&
+        <Button
+          style={styles.itemButton}
+          viewStyle={styles.itemView}
+          onClick={() => {
+            startPage(PageList.supportContact);
+          }}>
+          <MaterialCommunityIcons
+            style={styles.icon}
+            name="face-agent"
+            color="#333"
+            size={26}
+          />
+          <TextView style={styles.label}>{$t('drawer.contactSupport')}</TextView>
+        </Button>
+      }
+      {/* <Button
+        style={styles.itemButton}
+        viewStyle={styles.itemView}
+        onClick={() => {
+          startPage(PageList.about);
+        }}>
+        <MaterialCommunityIcons
+          style={styles.icon}
+          name="information-outline"
+          color="#333"
+          size={26}
+        />
+        <TextView style={styles.label}>{$t('drawer.about')}</TextView>
+      </Button> */}
+    </View>
+  );
+}
+
+const styles = StyleSheet.create({
+  drawerView: {
+    paddingTop: 8,
+    paddingBottom: 8,
+  },
+  loginView: {
+    paddingTop: 16,
+    paddingBottom: 0
+  },
+  avatar: {
+    width: 66,
+    height: 66,
+    marginLeft: 24,
+    borderWidth: 2,
+    borderRadius: 80,
+    borderColor: colorLight,
+  },
+  closeMenu: {
+    width: 46,
+    height: 46,
+    marginRight: 16,
+    borderRadius: 46,
+    alignItems: 'center',
+    justifyContent: 'center',
+    backgroundColor: colorPrimary
+  },
+  nickView: {
+    borderRadius: 0,
+    backgroundColor: colorLight
+  },
+  nickViewStyle: {
+    flex: 1,
+    alignItems: 'center',
+    flexDirection: 'row',
+    ...$padding(12, 16)
+  },
+  nickname: {
+    flex: 1,
+    color: textPrimary,
+    fontSize: 20,
+    fontWeight: 'bold',
+    paddingLeft: 16,
+  },
+  emailText: {
+    color: textPrimary,
+    fontSize: 11,
+    marginTop: -5,
+    paddingLeft: 16,
+    paddingBottom: 4
+  },
+  loginText: {
+    flex: 1,
+    color: textPrimary,
+    fontSize: 20,
+    fontWeight: 'bold',
+    marginTop: 4,
+    paddingTop: 4,
+    paddingLeft: 16,
+    paddingBottom: 4
+  },
+  divideLogin: {
+    height: 4,
+    marginTop: 2,
+    marginRight: 0,
+    marginBottom: 8,
+    backgroundColor: colorPrimary
+  },
+  itemButton: {
+    borderRadius: 0,
+    backgroundColor: colorLight
+  },
+  itemView: {
+    flex: 1,
+    height: 48,
+    paddingLeft: 16,
+    marginBottom: 0,
+    alignItems: 'center',
+    flexDirection: 'row'
+  },
+  icon: {
+    width: 24,
+    height: 24,
+    marginRight: 16
+  },
+  label: {
+    flex: 1,
+    color: textPrimary,
+    fontSize: 14,
+  },
+  divided: {
+    height: 1,
+    marginTop: 24,
+    marginLeft: 16,
+    backgroundColor: colorAccent
+  },
+  balanceText: {
+    color: textPrimary,
+    fontSize: 14,
+    marginRight: 20
+  },
+  balanceText2: {
+    color: colorPrimary,
+    fontSize: 14,
+    marginRight: 20
+  },
+  bridgeText: {
+    width: 20,
+    height: 20,
+    color: textLight,
+    fontSize: 12,
+    marginRight: 16,
+    borderRadius: 30,
+    fontWeight: 'bold',
+    alignItems: 'center',
+    flexDirection: 'row',
+    justifyContent: 'center',
+    backgroundColor: "#FF3B30"
+  },
+  bridgeText2: {
+    width: 22,
+    height: 22,
+    color: textLight,
+    fontSize: 10,
+    marginRight: 16,
+    borderRadius: 30,
+    fontWeight: 'bold',
+    alignItems: 'center',
+    flexDirection: 'row',
+    justifyContent: 'center',
+    backgroundColor: "#FF3B30"
+  }
+});

+ 167 - 0
Strides-APP/app/pages/home/Index.js

@@ -0,0 +1,167 @@
+/**
+ * 首页抽屉菜单
+ * @邠心vbe on 2021/03/23
+ */
+import React, { Component } from 'react';
+import {View, Text, StyleSheet, Image} from 'react-native';
+import { createDrawerNavigator, DrawerContentScrollView } from '@react-navigation/drawer';
+import app from '../../../app.json';
+import Maps from './Home';
+import Dialog from '../../components/Dialog';
+import { setAccessToken } from '../../api/http';
+import { getStorageJsonSync, setStorage, setStorageJson } from '../../utils/storage';
+import { AutoLogin } from '../sign/Login';
+import utils from '../../utils/utils';
+import apiNotification from '../../api/apiNotification';
+import DrawerView from './Drawer.js';
+import DrawerViewV2 from './DrawerV2.js';
+
+const Drawer = createDrawerNavigator();
+
+export default class Home extends Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      isLogin: false,
+      userInfo: {},
+      notificationCount: 0,
+      sideCountInfo: {}
+    }
+  }
+
+  componentDidMount() {
+    AutoLogin(() => {
+      this.setState({
+        userInfo: userInfo
+      });
+    });
+    this.props.navigation.addListener('focus', () => {
+      //console.log('drawer focus');
+      getUserInfo(info => {
+        this.setState({
+          userInfo: info
+        });
+      }, true);
+      if (app.modules.notifications && this.state.isLogin) {
+        this.getNotificationTotal();
+      }
+    });
+    /*BackHandler.addEventListener('hardwareBackPress', (e) => {
+      if (global.dialogId !== 0) {
+        Dialog.dismissLoading();
+        return true;
+      }
+      return false;
+    })*/
+  }
+
+  componentDidUpdate() {
+    const status = isLogin();
+    if (this.state.isLogin != status) {
+      this.setState({
+        isLogin: status
+      }, () => {
+        getUserInfo(info => {
+          this.setState({
+            userInfo: info
+          });
+          if (info.firebaseToken) {
+            let token = isIOS ? info.firebaseToken?.ios : info.firebaseToken?.android
+            if (notifyToken.token) {
+              utils.registerFirebaseToken(token ?? "");
+            }
+          }
+        }, true);
+        if (app.modules.notifications) {
+          this.getNotificationTotal();
+        }
+      });
+    }
+  }
+
+  async requestLogout() {
+    const data = await getStorageJsonSync('loginData');
+    if (data && data.email) {
+      delete data.password
+      setStorageJson('loginData', data);
+      setStorage('RegisterTokenDate', "");
+    }
+    global.userInfo = {}
+    this.setState({
+      isLogin: false,
+      userInfo: {}
+    });
+    setAccessToken('');
+    Dialog.dismissLoading();
+  }
+
+  getNotificationTotal() {
+    apiNotification.getUnreadTotal().then(res => {
+      if (res.data) {
+        this.setState({
+          sideCountInfo: res.data,
+          notificationCount: res.data?.toBeReadCount ?? 0
+        })
+      } else {
+        this.setState({
+          sideCountInfo: {},
+          notificationCount: 0
+        })
+      }
+    }).catch(err => {
+      this.setState({
+        sideCountInfo: {},
+        notificationCount: 0
+      })
+    })
+  }
+
+  render () {
+    return (
+      <Drawer.Navigator
+        initialRouteName='maps'
+        drawerContent={props => 
+          <CustomerDrawerContent 
+            {...props}
+            isLogin={this.state.isLogin}
+            userInfo={this.state.userInfo}
+            onLogout={() => this.requestLogout()}
+            sideCountInfo={this.state.sideCountInfo}
+            notificationCount={this.state.notificationCount}
+          />
+        }
+        screenOptions={{
+          headerShown: false,
+          drawerType: global.$width >= 768 ? 'back' : 'front',
+          drawerStyle: {
+            width: app.v3.drawer ? $vw(100) : ($vw(75) > 320 ? 320 : $vw(75)),
+            backgroundColor: app.v3.drawer ? 'rgba(0,0,0,0.1)' : colorLight
+          },
+          swipeEnabled: !app.v3.drawer, //启用侧滑打开抽屉
+        }}>
+        <Drawer.Screen name="maps" component={Maps} />
+      </Drawer.Navigator>
+    );
+  }
+};
+
+const CustomerDrawerContent = (props) => {
+  return (
+    <DrawerContentScrollView 
+      {...props}
+      canCancelContentTouches={true}
+      style={app.v3.drawer ? styles.contentV2 : {}}>
+      { app.v3.drawer
+      ? <DrawerViewV2 {...props}/>
+      : <DrawerView {...props}/>
+      }
+    </DrawerContentScrollView>
+  );
+}
+
+const styles = StyleSheet.create({
+  contentV2: {
+    width: $vw(75) > 320 ? 320 : $vw(75),
+    backgroundColor: colorLight
+  }
+})

+ 73 - 15
Strides-APP/app/pages/my/ProfileV2.js

@@ -227,21 +227,23 @@ export default class ProfileV2 extends Component {
             name='angle-right'/>
         </Button>
         {/* Notifications */}
-        <Button
-          style={styles.cardView}
-          viewStyle={styles.profileItem}
-          onClick={() => startPage(PageList.settings)}>
-          <Image
-            style={styles.cardIcon}
-            source={require('../../images/user/card-notification.png')}/>
-          <View style={styles.cardInfo}>
-            <TextView style={styles.cardLabel}>{$t('profile.notificationSettings')}</TextView>
-          </View>
-          <FontAwesome
-            size={28}
-            color={textCancel}
-            name='angle-right'/>
-        </Button>
+        { !app.v3.drawer &&
+          <Button
+            style={styles.cardView}
+            viewStyle={styles.profileItem}
+            onClick={() => startPage(PageList.settings)}>
+            <Image
+              style={styles.cardIcon}
+              source={require('../../images/user/card-notification.png')}/>
+            <View style={styles.cardInfo}>
+              <TextView style={styles.cardLabel}>{$t('profile.notificationSettings')}</TextView>
+            </View>
+            <FontAwesome
+              size={28}
+              color={textCancel}
+              name='angle-right'/>
+          </Button>
+        }
         { (app.modules.apply_phv && this.state.userInfo.userType.toLowerCase() == "public") &&
           <Button
             style={styles.cardView}
@@ -278,6 +280,62 @@ export default class ProfileV2 extends Component {
             color={textCancel}
             name='angle-right'/>
         </Button>
+        { app.v3.drawer && <>
+          <Button
+            style={styles.cardView}
+            viewStyle={styles.profileItem}
+            onClick={() => startPage(PageList.feedback)}>
+            <MaterialCommunityIcons
+              style={styles.cardIcon}
+              name="message-alert-outline"
+              color="#00638C"
+              size={32}
+            />
+            <View style={styles.cardInfo}>
+              <TextView style={styles.cardLabel}>{$t('drawer.feedback')}</TextView>
+            </View>
+            <FontAwesome
+              size={28}
+              color={textCancel}
+              name='angle-right'/>
+          </Button>
+          <Button
+            style={styles.cardView}
+            viewStyle={styles.profileItem}
+            onClick={() => startPage(PageList.settings)}>
+            <MaterialIcons
+              style={styles.cardIcon}
+              name="settings"
+              color="#00638C"
+              size={32}
+            />
+            <View style={styles.cardInfo}>
+              <TextView style={styles.cardLabel}>{$t('drawer.settings')}</TextView>
+            </View>
+            <FontAwesome
+              size={28}
+              color={textCancel}
+              name='angle-right'/>
+          </Button>
+          <Button
+            style={styles.cardView}
+            viewStyle={styles.profileItem}
+            onClick={() => startPage(PageList.about)}>
+            <MaterialCommunityIcons
+              style={styles.cardIcon}
+              name="information-outline"
+              color="#00638C"
+              size={32}
+            />
+            <View style={styles.cardInfo}>
+              <TextView style={styles.cardLabel}>{$t('drawer.about')}</TextView>
+            </View>
+            <FontAwesome
+              size={28}
+              color={textCancel}
+              name='angle-right'/>
+          </Button>
+        </>}
         {/* <Button
           style={styles.deleteButton}
           text="DELETE MY ACCOUNT"

+ 2 - 0
Strides-APP/app/pages/wallet/TopupNew.js

@@ -95,6 +95,8 @@ export default class TopupNew extends Component {
       if (app.v3.anzPayment) {
         if (res.data.qr) {
           startPage(PageList.paynow, { info: res.data.qr, type: 'Topup' });
+        } else if (res.data.webPaymentUrl) {
+          startPage(PageList.paymentWeb, { amount: params.payAmount, url: res.data.webPaymentUrl, type: 'Topup' });
         } else {
           toastShort('Error 01')
         }