Browse Source

fix: 修复bug优化页面

zengkunsen 4 months ago
parent
commit
c7086f94ac

+ 1 - 1
app/(auth)/(tabs)/(home)/notificationDetailPage.tsx

@@ -88,7 +88,7 @@ const NotificationDetailPage = () => {
                 setPromotionImage(promotionImage);
             } catch (e) {
             } finally {
-                setLoading(false);
+              setLoading(false);
             }
         };
         fetchPromotionImage();

+ 41 - 7
app/(auth)/(tabs)/(home)/notificationPage.tsx

@@ -13,16 +13,50 @@ import { SafeAreaView } from 'react-native-safe-area-context';
 import { router, useLocalSearchParams } from 'expo-router';
 import { CrossLogoSvg, PreviousPageBlackSvg } from '../../../../component/global/SVG';
 import { useEffect, useState } from 'react';
-
+import { chargeStationService } from '../../../../service/chargeStationService';
 import NotificationTabView from '../../../../component/global/notificationTabViewComponent';
 const NotificationPageComponent = () => {
-    const params = useLocalSearchParams();
     const screenHeight = Dimensions.get('window').height;
     const [loading, setLoading] = useState(false);
     const [loading1, setLoading1] = useState(false);
-    const { reservationAfter2025, passingThisPromotionToBell } = useLocalSearchParams();
-    const parsedReservationAfter2025 = JSON.parse(reservationAfter2025 as string);
-    const parsedPassingThisPromotionToBell = JSON.parse(passingThisPromotionToBell as string);
+    const [reservationAfter2025, setReservationAfter2025] = useState([]);
+    const [passingThisPromotionToBell, setPassingThisPromotionToBell] = useState([]);
+    const fetchData = async () => {
+      try {
+            const results = await Promise.allSettled([
+                chargeStationService.fetchReservationHistories(),
+                chargeStationService.getAdvertise()
+            ]);
+            console.log('results', results);
+            // Handle reservation data
+            if (results[0].status === 'fulfilled') {
+                const year2025 = new Date('2025-02-01T00:00:00.000Z');
+                const reservationAfter2025 = results[0].value.filter((r: any) => {
+                    const date = new Date(r.createdAt);
+                    return date > year2025;
+                });
+                setReservationAfter2025(reservationAfter2025);
+            } else if (results[0].status === 'rejected') {
+                Alert.alert('Error fetching reservations:', results[0].reason);
+            }
+
+            // Handle promotion data
+            if (results[1].status === 'fulfilled') {
+                const passingThisPromotionToBell = results[1].value.filter((p: any) => p.is_show);
+                setPassingThisPromotionToBell(passingThisPromotionToBell);
+            } else if (results[1].status === 'rejected') {
+                Alert.alert('Error fetching promotions:', results[1].reason);
+            }
+
+        } catch (error) {
+            Alert.alert('Error fetching data');
+        } finally {
+    
+        }
+    }
+    useEffect(() => {
+      fetchData()
+    }, [])
     return (
         <SafeAreaView className="flex-1 bg-white" edges={['top']}>
             <View style={{ minHeight: screenHeight, flex: 1 }} className="mx-[5%]">
@@ -44,8 +78,8 @@ const NotificationPageComponent = () => {
                 <View className="flex-1">
                     <NotificationTabView
                         titles={['充電資訊', '活動優惠']}
-                        reservationAfter2025={parsedReservationAfter2025}
-                        passingThisPromotionToBell={parsedPassingThisPromotionToBell}
+                        reservationAfter2025={reservationAfter2025}
+                        passingThisPromotionToBell={passingThisPromotionToBell}
                     />
                 </View>
             </View>

+ 2 - 0
app/_layout.tsx

@@ -1,5 +1,6 @@
 import "./global.css"
 import { Stack } from 'expo-router/stack';
+import { StatusBar } from 'expo-status-bar';
 import AuthProvider, { useAuth } from '../context/AuthProvider';
 import { EXPO_PUBLIC_NODE_ENV } from '@env';
 import { GestureHandlerRootView } from 'react-native-gesture-handler';
@@ -66,6 +67,7 @@ export default function RootLayout() {
                     )}
                 </Stack>
             </AuthProvider>
+            <StatusBar style="dark" backgroundColor="#fff" />
         </GestureHandlerRootView>
     );
 }

+ 2 - 2
app/hooks/usePushNotifications.ts

@@ -13,8 +13,8 @@ export const usePushNotifications = (): PushNotificationState => {
   const [expoPushToken, setExpoPushToken] = useState<Notifications.ExpoPushToken | undefined>();
   const [notification, setNotification] = useState<Notifications.Notification | undefined>();
 
-  const notificationListener = useRef<Notifications.EventSubscription>();
-  const responseListener = useRef<Notifications.EventSubscription>();
+  const notificationListener = useRef<Notifications.Subscription>();
+  const responseListener = useRef<Notifications.Subscription>();
 
   useEffect(() => {
     Notifications.setNotificationHandler({

+ 6 - 32
component/accountPages/changeCarPageComponent.tsx

@@ -9,6 +9,7 @@ import NormalButton from '../global/normal_button';
 import { authenticationService } from '../../service/authService';
 import * as SecureStore from 'expo-secure-store';
 import { chargeStationService } from '../../service/chargeStationService';
+import { User } from '../../types/user';
 
 const ChangeCarPageComponent = () => {
     const { user, setUser } = useContext(AuthContext);
@@ -72,6 +73,11 @@ const ChangeCarPageComponent = () => {
                         onPress: () => router.replace('accountMainPage')
                     }
                 ]);
+                const newUser = {...user}
+                newUser.car = car
+                setUser({
+                    ...newUser,
+                } as User);
             } else {
                 setError('無法保存車牌號碼');
                 Alert.alert('錯誤', '無法保存車牌號碼,請稍後再試');
@@ -82,38 +88,6 @@ const ChangeCarPageComponent = () => {
         }
     };
 
-    const handleChangeCar = async () => {
-        if (!name) {
-            setError('請輸入新的車牌號碼');
-            return;
-        }
-        if (!token) {
-            setError('未找到有效的登錄令牌,請重新登錄');
-            return;
-        }
-        setError(null);
-        setIsLoading(true);
-        try {
-            const success = await authenticationService.changeName(name, token);
-            if (success) {
-                if (user) {
-                    setUser({
-                        ...user,
-                        nickname: name
-                    });
-                }
-                router.replace('accountMainPage');
-            } else {
-                setError('更新暱稱失敗,請稍後再試');
-            }
-        } catch (error) {
-            console.error('Error changing name:', error);
-            setError('發生錯誤,請稍後再試');
-        } finally {
-            setIsLoading(false);
-        }
-    };
-
     return (
         <SafeAreaView className="flex-1 bg-white" edges={['top', 'right', 'left']}>
             <ScrollView className="flex-1 mx-[5%]">

+ 1 - 1
component/global/bookingTabViewComponent.tsx

@@ -141,7 +141,7 @@ const BookingTabViewComponentInner: React.FC<BookingTabViewComponentProps> = ({
     // 确保即使 data 为 undefined 也能安全处理
     const reservations = Array.isArray(data?.reservations) ? data.reservations : [];
     const stations = Array.isArray(data?.stations) ? data.stations : [];
-    console.log('iiii', data)
+  
     const tabItems = processReservations(reservations, stations, true);
     const completedReservationTabItems = processReservations(reservations, stations, false);
     return (

+ 9 - 6
component/global/notificationTabViewComponent.tsx

@@ -5,7 +5,7 @@ import { View, Text, useWindowDimensions, StyleSheet, ScrollView, ActivityIndica
 import { TabView, TabBar } from 'react-native-tab-view';
 
 import { formatToChineseDateTime } from '../../util/lib';
-import { useCallback, useEffect, useState } from 'react';
+import { useCallback, useMemo, useEffect, useState } from 'react';
 import { notificationStorage } from '../notificationStorage';
 import { router, useFocusEffect } from 'expo-router';
 
@@ -141,7 +141,7 @@ const FirstRoute = ({ loading, reservationAfter2025 }: { loading: boolean; reser
                             <ActivityIndicator />
                         </View>
                     ) : (
-                        <View className="">
+                        <View>
                             <View>
                                 {reservationAfter2025.length === 0 ? (
                                     <Text className="pl-4">暫時沒有充電資訊。</Text>
@@ -199,7 +199,7 @@ const SecondRoute = ({ promotions, loading }: { promotions: TabItem[]; loading:
                         <ActivityIndicator />
                     </View>
                 ) : (
-                    <View className="">
+                    <View>
                         <View>
                             {promotions.length === 0 ? (
                                 <Text className="pl-4">暫時沒有通知消息。</Text>
@@ -233,7 +233,7 @@ const NotificationTabView: React.FC<TabViewComponentProps> = ({
     passingThisPromotionToBell
 }) => {
     const layout = useWindowDimensions();
-    const [loading, setLoading] = useState(false);
+    const [loading, setLoading] = useState(true);
     const renderScene = useCallback(
         ({ route }: { route: any }) => {
             switch (route.key) {
@@ -245,9 +245,11 @@ const NotificationTabView: React.FC<TabViewComponentProps> = ({
                     return null;
             }
         },
-        [loading]
+        [reservationAfter2025, passingThisPromotionToBell]
     );
-
+    useEffect(() => {
+        setLoading(false)
+    }, [reservationAfter2025, passingThisPromotionToBell]);
     const [routes] = React.useState([
         { key: 'firstRoute', title: titles[0] },
         { key: 'secondRoute', title: titles[1] }
@@ -289,6 +291,7 @@ const NotificationTabView: React.FC<TabViewComponentProps> = ({
                     </Text>
                 )
             }}
+            lazy
         />
     );
 };

+ 4 - 38
component/homePage/homePage.tsx

@@ -52,8 +52,6 @@ const HomePage: React.FC<HomePageProps> = () => {
     const [isLoadingReservations, setIsLoadingReservations] = useState(true);
     const [unreadCount, setUnreadCount] = useState(0);
 
-    const [passingThisPromotionToBell, setPassingThisPromotionToBell] = useState<any>([]);
-
     useEffect(() => {
         const fetchIDandCheckLicensePlate = async () => {
             try {
@@ -143,14 +141,6 @@ const HomePage: React.FC<HomePageProps> = () => {
                         Alert.alert('Error fetching reservations:', results[0].reason);
                     }
 
-                    // Handle promotion data
-                    if (results[1].status === 'fulfilled') {
-                        const passingThisPromotionToBell = results[1].value.filter((p: any) => p.is_show);
-                        setPassingThisPromotionToBell(passingThisPromotionToBell);
-                    } else if (results[1].status === 'rejected') {
-                        Alert.alert('Error fetching promotions:', results[1].reason);
-                    }
-
                     // Get viewed notifications
                     const viewedNotifications = await notificationStorage.getViewedNotifications();
 
@@ -267,7 +257,6 @@ const HomePage: React.FC<HomePageProps> = () => {
                                     <NormalButton
                                         title={<Text className="text-white  text-sm lg:text-lg">確定</Text>}
                                         onPress={() => {
-                                            console.log('licensePlate', licensePlate);
                                             //here when users click confirm, i want to pop another modal that say you have entered "xxxxxx", click confirm to continue
                                             if (!licensePlate.trim()) {
                                                 Alert.alert('請輸入車牌號碼');
@@ -331,14 +320,7 @@ const HomePage: React.FC<HomePageProps> = () => {
                                 <View className="relative z-5">
                                     <Pressable
                                         onPress={() =>
-                                            router.push({
-                                                pathname: 'notificationPage',
-                                                params: {
-                                                    reservationAfter2025: JSON.stringify(reservationAfter2025),
-                                                    passingThisPromotionToBell:
-                                                        JSON.stringify(passingThisPromotionToBell)
-                                                }
-                                            })
+                                            router.push({pathname: 'notificationPage'})
                                         }
                                         disabled={isLoadingReservations}
                                         className="z-10 w-10 items-center justify-center"
@@ -414,23 +396,7 @@ const HomePage: React.FC<HomePageProps> = () => {
                                     padding: 24
                                 }}
                             />
-                        </View> */}                   
-                        <View className="flex-1">
-                            <NormalButton
-                                // onPress={() => console.log('掃瞄及充電')}
-                                onPress={() => router.push('vipQrPage')}
-                                title={
-                                    <View className="flex flex-row items-center space-x-2">
-                                        <VipCodeIconSvg />
-                                        <Text className="text-white font-bold text-lg ml-2">專屬會員二維碼</Text>
-                                    </View>
-                                }
-                                extendedStyle={{
-                                    alignItems: 'flex-start',
-                                    padding: 24
-                                }}
-                            />
-                        </View>
+                        </View> */}
                         <View className="flex-1">
                             <NormalButton
                                 onPress={() => router.push('/(account)/(wallet)/walletPage')}
@@ -447,7 +413,7 @@ const HomePage: React.FC<HomePageProps> = () => {
                             />
                         </View>
                     </View>
-                    {/* <View className="mt-4">
+                    <View className="mt-4">
                         <NormalButton
                             // onPress={() => console.log('掃瞄及充電')}
                             onPress={() => router.push('vipQrPage')}
@@ -462,7 +428,7 @@ const HomePage: React.FC<HomePageProps> = () => {
                                 padding: 24
                             }}
                         />
-                    </View> */}
+                    </View>
                 </View>
             </ScrollView>
         </SafeAreaView>

+ 0 - 30
context/AuthProvider.tsx

@@ -98,36 +98,6 @@ export default function AuthProvider({ children }: { children: ReactNode }) {
         }
     };
 
-    //this is urgent login, only for testing & debugging
-    // const login = async (username: string, password: string, isBinding: boolean) => {
-    //     try {
-    //         const loggedInUser = {
-    //             accessToken:
-    //                 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiY3VzdG9tZXIiLCJjcmVhdGVkQXQiOiIyMDI0LTA5LTAzVDA2OjM4OjU3LjI5NloiLCJ1cGRhdGVkQXQiOiIyMDI0LTEyLTAyVDE3OjUwOjQyLjI1MloiLCJpZCI6IjA2ZTRkNjU0LTliNDEtNDExMy1hZjBmLTE5OTIzYjc0YzEwZSIsImZpcnN0bmFtZSI6bnVsbCwibGFzdG5hbWUiOm51bGwsIm5pY2tuYW1lIjoiVGVzdCAyIiwiZW1haWwiOiJ0ZXN0MkBnbWFpbC5jb20iLCJwaG9uZSI6NjgxMDAxMTYsImljX2NhcmQiOiIwMDAwMDAwMDAwMDAxNDk2Iiwid2FsbGV0Ijo5NzYwLCJpY29uX3VybCI6bnVsbCwicmVtYXJrIjpudWxsLCJhZGRyZXNzIjpudWxsLCJzdGF0dXNfZmsiOiIxIiwiZ2VuZGVyIjoibWFuIiwiYmlydGhkYXkiOiIwNC8wNi8xMSIsImljX2Nhcl9pZCI6bnVsbCwiaWF0IjoxNzMzMTkyNjgzLCJleHAiOjE3MzMxOTk4ODN9.1VvQacR5SJ1JiRlnmy_m5rcrKN8wXsPTZ9_QLas8CEQ',
-    //             refreshToken:
-    //                 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiY3VzdG9tZXIiLCJjcmVhdGVkQXQiOiIyMDI0LTA5LTAzVDA2OjM4OjU3LjI5NloiLCJ1cGRhdGVkQXQiOiIyMDI0LTEyLTAyVDE3OjUwOjQyLjI1MloiLCJpZCI6IjA2ZTRkNjU0LTliNDEtNDExMy1hZjBmLTE5OTIzYjc0YzEwZSIsImZpcnN0bmFtZSI6bnVsbCwibGFzdG5hbWUiOm51bGwsIm5pY2tuYW1lIjoiVGVzdCAyIiwiZW1haWwiOiJ0ZXN0MkBnbWFpbC5jb20iLCJwaG9uZSI6NjgxMDAxMTYsImljX2NhcmQiOiIwMDAwMDAwMDAwMDAxNDk2Iiwid2FsbGV0Ijo5NzYwLCJpY29uX3VybCI6bnVsbCwicmVtYXJrIjpudWxsLCJhZGRyZXNzIjpudWxsLCJzdGF0dXNfZmsiOiIxIiwiZ2VuZGVyIjoibWFuIiwiYmlydGhkYXkiOiIwNC8wNi8xMSIsImljX2Nhcl9pZCI6bnVsbCwiaWF0IjoxNzMzMTkyMjY5LCJleHAiOjE3MzY2NDgyNjl9.OrZqQyLkHL0eojesrn3xqoxIYatanjCX-GyXTcmNoys'
-    //         };
-    //         if (loggedInUser) {
-    //             //this is only for urgent login, uncomment getItemAsync after
-    //             await SecureStore.setItemAsync('accessToken', loggedInUser.accessToken);
-    //             const token = await SecureStore.getItemAsync('accessToken');
-    //             if (token) {
-    //                 const userInfo = await getUserFromAccessToken();
-    //                 if (userInfo) {
-    //                     console.log('userInfouserInfouserInfouserInfouserInfouserInfo', userInfo);
-    //                     setUser(userInfo);
-    //                 }
-    //             }
-    //             return true;
-    //         } else {
-    //             return false;
-    //         }
-    //     } catch (error) {
-    //         console.error('Login error:', error);
-    //         return false;
-    //     }
-    // };
-
     const getUserFromAccessToken = async () => {
         const token = await SecureStore.getItemAsync('accessToken');
         try {

+ 4 - 4
ios/Podfile.lock

@@ -1704,7 +1704,7 @@ PODS:
     - React-Core
   - react-native-maps (1.20.1):
     - React-Core
-  - react-native-pager-view (6.7.1):
+  - react-native-pager-view (6.8.1):
     - DoubleConversion
     - glog
     - hermes-engine
@@ -2173,7 +2173,7 @@ PODS:
     - ReactCommon/turbomodule/bridging
     - ReactCommon/turbomodule/core
     - Yoga
-  - RNFlashList (1.7.6):
+  - RNFlashList (1.8.3):
     - DoubleConversion
     - glog
     - hermes-engine
@@ -2863,7 +2863,7 @@ SPEC CHECKSUMS:
   React-microtasksnativemodule: bda561d2648e1e52bd9e5a87f8889836bdbde2e2
   react-native-google-maps: c4f5c5b2dda17e7cb2cb2b37a81f140b039b3e7e
   react-native-maps: 9febd31278b35cd21e4fad2cf6fa708993be5dab
-  react-native-pager-view: f238ed7fb53458bd03366944a33686f067c83e9a
+  react-native-pager-view: 919534782a0489f7e2aeeb9a8b8959edfd3f067a
   react-native-safe-area-context: 562163222d999b79a51577eda2ea8ad2c32b4d06
   react-native-webview: 520bcb79c3f2af91e157cdd695732a34ab5f25c8
   React-NativeModulesApple: 1ecb83880dd11baf2228f8dd89d8419c387e03ad
@@ -2898,7 +2898,7 @@ SPEC CHECKSUMS:
   ReactCodegen: 6cb6e0d0b52471abc883541c76589d1c367c64c7
   ReactCommon: 1ab5451fc5da87c4cc4c3046e19a8054624ca763
   RNCAsyncStorage: 39c42c1e478e1f5166d1db52b5055e090e85ad66
-  RNFlashList: 7ad51f0d0d51a3b7b1d1bb07947b927cb352afc4
+  RNFlashList: b3f60e72e738e46e53bb05663c80e14af5328990
   RNGestureHandler: 7d0931a61d7ba0259f32db0ba7d0963c3ed15d2b
   RNReanimated: 2313402fe27fecb7237619e9c6fcee3177f08a65
   RNScreens: 482e9707f9826230810c92e765751af53826d509

+ 1 - 2
service/chargeStationService.tsx

@@ -362,7 +362,6 @@ class ChargeStationService {
                     Authorization: `Bearer ${await SecureStore.getItemAsync('accessToken')}`
                 }
             });
-
             if (response.status === 200 || response.status === 201) {
                 return response.data.data;
             } else {
@@ -488,8 +487,8 @@ class ChargeStationService {
                     Authorization: `Bearer ${await SecureStore.getItemAsync('accessToken')}`
                 }
             });
+            console.log('Fetching all charge stations:', response.data);
             if (response.status === 200 || response.status === 201) {
-                // console.log(response.data);
                 return response.data;
             } else {
                 console.log('invalid response');

+ 1 - 0
service/walletService.tsx

@@ -25,6 +25,7 @@ class WalletService {
                 return false;
             }
         } catch (error) {
+            console.log('dqqqqqq',SecureStore.getItemAsync('accessToken'));
             console.error('Error in getCouponForSpecificUser:', error);
             throw error;
         }

+ 2 - 1
types/user.d.ts

@@ -1,8 +1,9 @@
 export interface User {
     address: string;
     birthday: string;
-    license_plate?: string;
+    license_plate?: string | null;
     email: string;
+    car: string | null;
     // firstname?: string | null;
     gender: string;
     nickname: string;

+ 1 - 1
util/index.ts

@@ -1,7 +1,7 @@
 import { Linking, Alert } from 'react-native';
 
 export const handleGoWhatsApp = async () => {
-  const phoneWithCountryCode = '8613365413560'; // 不带 "+",如 +60 改成 60(马来西亚)
+  const phoneWithCountryCode = '8528691382139'; // 不带 "+",如 +60 改成 60(马来西亚)
   const message = 'Hello!';
 
   const url = `whatsapp://send?phone=${phoneWithCountryCode}&text=${encodeURIComponent(message)}`;