accountMainPageComponent.tsx 12 KB

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