accountMainPageComponent.tsx 11 KB

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