accountMainPageComponent.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. import { View, Text, ScrollView, Image, Switch, Pressable, Dimensions, Linking, Alert, AppState } from 'react-native';
  2. import { SafeAreaView } from 'react-native-safe-area-context';
  3. import { router, useFocusEffect } from 'expo-router';
  4. import { useAuth } from '../../context/AuthProvider';
  5. import * as Notifications from 'expo-notifications';
  6. import { useColorScheme } from 'nativewind';
  7. import Constants from 'expo-constants';
  8. import { useState, useEffect, useCallback } from 'react';
  9. import {
  10. AccountSettingIconSvg,
  11. ActivitySvg,
  12. MyCarSvg,
  13. DarkModeSvg,
  14. QuestionMarkIconSvg,
  15. SettingIconSvg,
  16. VipCodeIcoonSvg,
  17. WalletSvg,
  18. NotificationSvg
  19. } from '../global/SVG';
  20. import { usePushNotifications } from '../../app/hooks/usePushNotifications';
  21. import useUserInfoStore from '../../providers/userinfo_store';
  22. import { authenticationService } from '../../service/authService';
  23. const AccountMainPageComponent = () => {
  24. const { user, logout } = useAuth();
  25. const { colorScheme, toggleColorScheme } = useColorScheme();
  26. const screenWidth = Dimensions.get('window').width;
  27. const imageWidth = screenWidth * 0.9; // 90% of screen width
  28. const aspectRatio = 210 / 375;
  29. const [notificationsEnabled, setNotificationsEnabled] = useState(false);
  30. const { expoPushToken, notification } = usePushNotifications();
  31. // const notify_session_id = expoPushToken?.data || '';
  32. // Check initial notification permission status
  33. const { notifySessionID } = useUserInfoStore();
  34. //everytime i am on this screen, i check if permission is granted.
  35. useFocusEffect(
  36. useCallback(() => {
  37. const checkPermissionsAndToken = async () => {
  38. const { status } = await Notifications.getPermissionsAsync();
  39. setNotificationsEnabled(status === 'granted');
  40. if (status === 'granted') {
  41. //if status is granted, then i will fetch latest expo token to see if it is the same as notify_session_id
  42. const latestToken = await Notifications.getExpoPushTokenAsync({
  43. projectId: Constants.expoConfig?.extra?.eas?.projectId
  44. });
  45. console.log('latestToken.data', latestToken.data);
  46. console.log('notifySessionID', notifySessionID);
  47. //TODO: if latestToken = notify_session_id, do nothing
  48. if (latestToken.data === notifySessionID) {
  49. return;
  50. } else {
  51. const res = await authenticationService.changeNotifySessionID(latestToken.data);
  52. if (res) {
  53. console.log('Change notifySessionID Successfully!');
  54. } else {
  55. Alert.alert('更新通知權限失敗', '請稍後再試');
  56. }
  57. }
  58. //TODO: if latestToken != notify_session_id, update notify_session_id to latestToken
  59. }
  60. };
  61. checkPermissionsAndToken();
  62. const subscription = AppState.addEventListener('change', (nextAppState: string) => {
  63. if (nextAppState === 'active') {
  64. checkPermissionsAndToken();
  65. }
  66. });
  67. return () => {
  68. subscription.remove();
  69. };
  70. }, [expoPushToken]) // Add expoPushToken as a dependency
  71. );
  72. const toggleNotifications = async () => {
  73. Alert.alert('通知設定', '要更改通知設定,請前往手機的設定頁面,允許CrazyCharge通知。', [
  74. {
  75. text: '取消',
  76. style: 'cancel'
  77. },
  78. {
  79. text: '前往設定',
  80. onPress: () => Linking.openSettings()
  81. }
  82. ]);
  83. };
  84. return (
  85. <SafeAreaView className="flex-1 bg-white dark:bg-[#05181C]" edges={['top', 'left', 'right']}>
  86. <ScrollView className="flex-1 mx-[5%]" showsVerticalScrollIndicator={false}>
  87. <View style={{ marginTop: 25 }}>
  88. <Text style={{ fontSize: 48 }} className="text-black dark:text-white">
  89. {user?.nickname}
  90. </Text>
  91. </View>
  92. <View className="flex-row justify-between mt-4 ">
  93. <Pressable
  94. className="h-[114px] w-[30%] bg-[#e7f2f8] dark:bg-[#253336] items-center justify-center rounded-xl"
  95. onPress={() => router.push('/(account)/(wallet)/walletPage')}
  96. >
  97. <WalletSvg isDark={colorScheme == 'dark'} />
  98. <Text className="text-black dark:text-[#36DFFF]">錢包</Text>
  99. </Pressable>
  100. {/* <Pressable
  101. className="h-[114px] w-[30%] bg-[#e7f2f8] items-center justify-center rounded-xl"
  102. onPress={() => router.replace('myVehiclePage')}
  103. >
  104. <MyCarSvg />
  105. <Text>我的車輛</Text>
  106. </Pressable> */}
  107. <Pressable
  108. className="h-[114px] w-[30%] bg-[#e7f2f8] dark:bg-[#253336] items-center justify-center rounded-xl"
  109. onPress={() => router.replace('vipQrPage')}
  110. >
  111. <VipCodeIcoonSvg isDark={colorScheme == 'dark'} />
  112. <Text className="text-black dark:text-[#36DFFF]">VIP Code</Text>
  113. </Pressable>
  114. <Pressable
  115. className="h-[114px] w-[30%] bg-[#e7f2f8] dark:bg-[#253336] items-center justify-center rounded-xl"
  116. onPress={() => router.push('/activityRecordPage')}
  117. >
  118. <ActivitySvg isDark={colorScheme == 'dark'} />
  119. <Text className="text-black dark:text-[#36DFFF]">充電記錄</Text>
  120. </Pressable>
  121. </View>
  122. <View className="my-4 ">
  123. <Pressable onPress={() => router.push('uberVerificationPage')}>
  124. <Image
  125. resizeMode="contain"
  126. source={require('../../assets/uber20008.png')}
  127. style={{ width: imageWidth, height: imageWidth * aspectRatio, alignSelf: 'center' }}
  128. />
  129. </Pressable>
  130. </View>
  131. <View className="w-full h-1 bg-[#DBE4E8] dark:bg-[#253336]" />
  132. <View>
  133. <View className="py-4">
  134. <Pressable
  135. onPress={() => router.push('/accountSettingPage')}
  136. className="flex-row items-center"
  137. hitSlop={{
  138. top: 10,
  139. bottom: 10,
  140. left: 10,
  141. right: 10
  142. }}
  143. >
  144. <AccountSettingIconSvg isDark={colorScheme == 'dark'} />
  145. <Text className="text-lg pl-2 text-black dark:text-white">帳戶管理</Text>
  146. </Pressable>
  147. </View>
  148. <View className="h-0.5 bg-[#f4f4f4] dark:bg-[#5E6C70]" />
  149. <View className=" py-4 ">
  150. <Pressable
  151. onPress={() => router.push('/assistancePage')}
  152. className="flex-row items-center"
  153. hitSlop={{
  154. top: 10,
  155. bottom: 10,
  156. left: 10,
  157. right: 10
  158. }}
  159. >
  160. <QuestionMarkIconSvg isDark={colorScheme == 'dark'} />
  161. <Text className="text-lg pl-2 text-black dark:text-white">排除解難</Text>
  162. </Pressable>
  163. </View>
  164. <View className="h-0.5 bg-[#f4f4f4] dark:bg-[#5E6C70]" />
  165. <View className=" py-4 ">
  166. <Pressable
  167. // onPress={() => router.push('/assistancePage')}
  168. className="flex-row items-center"
  169. hitSlop={{
  170. top: 10,
  171. bottom: 10,
  172. left: 10,
  173. right: 10
  174. }}
  175. >
  176. <View className="flex flex-row justify-between w-full">
  177. <View className="flex flex-row items-center">
  178. <NotificationSvg isDark={colorScheme == 'dark'} />
  179. <Text className="text-lg pl-2 text-black dark:text-white">允許通知</Text>
  180. </View>
  181. <Switch value={notificationsEnabled} onChange={toggleNotifications} />
  182. </View>
  183. </Pressable>
  184. </View>
  185. {/* <View className="h-0.5 bg-[#f4f4f4] dark:bg-[#5E6C70]" />
  186. <View className=" py-4 ">
  187. <Pressable
  188. // onPress={() => router.push('/assistancePage')}
  189. className="flex-row items-center"
  190. hitSlop={{
  191. top: 10,
  192. bottom: 10,
  193. left: 10,
  194. right: 10
  195. }}
  196. >
  197. <View className="flex flex-row justify-between w-full">
  198. <View className="flex flex-row items-center">
  199. <DarkModeSvg isDark={colorScheme == 'dark'} />
  200. <Text className="text-lg pl-2 text-black dark:text-white">深色模式</Text>
  201. </View>
  202. <Switch value={colorScheme == 'dark'} onChange={toggleColorScheme} />
  203. </View>
  204. </Pressable>
  205. </View> */}
  206. <View className="h-0.5 bg-[#f4f4f4] dark:bg-[#5E6C70]" />
  207. <View className="py-4">
  208. <Pressable
  209. onPress={logout}
  210. className="flex-row items-center"
  211. hitSlop={{
  212. top: 10,
  213. bottom: 10,
  214. left: 10,
  215. right: 10
  216. }}
  217. >
  218. <SettingIconSvg isDark={colorScheme == 'dark'} />
  219. <Text className="text-lg pl-2 text-black dark:text-white">登出</Text>
  220. </Pressable>
  221. </View>
  222. <View className="h-0.5 bg-[#f4f4f4] dark:bg-[#5E6C70]" />
  223. </View>
  224. </ScrollView>
  225. </SafeAreaView>
  226. );
  227. };
  228. export default AccountMainPageComponent;