changePasswordPageComponent.tsx 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. import { View, Text, ScrollView, StyleSheet, Pressable } from 'react-native';
  2. import React, { useContext, useEffect, useState } from 'react';
  3. import { SafeAreaView } from 'react-native-safe-area-context';
  4. import { router } from 'expo-router';
  5. import { CrossLogoSvg } from '../global/SVG';
  6. import { AuthContext } from '../../context/AuthProvider';
  7. import NormalInput from '../global/normal_input';
  8. import NormalButton from '../global/normal_button';
  9. import * as SecureStore from 'expo-secure-store';
  10. import { authenticationService } from '../../service/authService';
  11. import { get } from 'react-native/Libraries/TurboModule/TurboModuleRegistry';
  12. import { walletService } from '../../service/walletService';
  13. const changePasswordPageComponent = () => {
  14. const { user, setUser } = useContext(AuthContext);
  15. const [token, setToken] = useState<string | null>(null);
  16. const [currentPassword, setCurrentPassword] = useState<string | null>(null);
  17. const [newPassword, setNewPassword] = useState<string | null>(null);
  18. const [newConfirmPassword, setNewConfirmPassword] = useState<string | null>(
  19. null
  20. );
  21. const [isPasswordVerified, setIsPasswordVerified] =
  22. useState<boolean>(false);
  23. const [error, setError] = useState<string | null>(null);
  24. const [isLoading, setIsLoading] = useState(false);
  25. const [isLoading2, setIsLoading2] = useState(false);
  26. useEffect(() => {
  27. const getToken = async () => {
  28. const storedToken = await SecureStore.getItemAsync('accessToken');
  29. setToken(storedToken);
  30. };
  31. getToken();
  32. }, []);
  33. const handleVerifyPassword = async (currentPassword: string) => {
  34. try {
  35. setIsLoading(true);
  36. if (!currentPassword) {
  37. setError('請輸入密碼');
  38. return;
  39. }
  40. if (!user || !user.email) {
  41. setError('無法驗證用戶,請重新登錄');
  42. return;
  43. }
  44. const success = await authenticationService.login(
  45. user.email,
  46. currentPassword
  47. );
  48. if (success) {
  49. setIsPasswordVerified(true);
  50. setError('');
  51. return true;
  52. } else {
  53. setError('密碼錯誤,請稍後再試');
  54. }
  55. } catch (error) {
  56. console.error('Error verifying password:', error);
  57. setError('密碼錯誤,請稍後再試');
  58. return false;
  59. } finally {
  60. setIsLoading(false);
  61. }
  62. };
  63. const handlePasswordChange = async () => {
  64. try {
  65. setIsLoading2(true);
  66. if (newPassword !== newConfirmPassword) {
  67. setError('新密碼不相符');
  68. return;
  69. }
  70. if (!newConfirmPassword || !token) {
  71. setError('請輸入新密碼');
  72. return;
  73. }
  74. const success = await authenticationService.changePassword(
  75. newConfirmPassword,
  76. token
  77. );
  78. if (success) {
  79. setError('');
  80. console.log('change password success');
  81. router.replace('accountMainPage');
  82. } else {
  83. setError('密碼更改失敗,請稍後再試');
  84. }
  85. } catch (error) {
  86. console.error('Error changing password:', error);
  87. setError('發生錯誤,請稍後再試');
  88. } finally {
  89. setIsLoading2(false);
  90. }
  91. };
  92. return (
  93. <SafeAreaView
  94. className="flex-1 bg-white"
  95. edges={['top', 'right', 'left']}
  96. >
  97. <ScrollView
  98. className="flex-1 mx-[5%]"
  99. showsVerticalScrollIndicator={false}
  100. >
  101. <View style={{ marginTop: 25 }}>
  102. <Pressable
  103. onPress={() => {
  104. if (router.canGoBack()) {
  105. router.back();
  106. } else {
  107. router.replace('/accountMainPage');
  108. }
  109. }}
  110. >
  111. <CrossLogoSvg />
  112. </Pressable>
  113. <Text style={{ fontSize: 45, marginVertical: 25 }}>
  114. 更改密碼
  115. </Text>
  116. <Text className="text-xl ">請輸入您現時的帳戶密碼</Text>
  117. <View className="py-2">
  118. <NormalInput
  119. placeholder="帳戶密碼"
  120. onChangeText={(t) => setCurrentPassword(t)}
  121. secureTextEntry={true}
  122. editable={!isPasswordVerified}
  123. />
  124. </View>
  125. <NormalButton
  126. title={
  127. <Text style={{ color: '#fff' }}>
  128. {isLoading
  129. ? '驗證中...'
  130. : isPasswordVerified
  131. ? '已驗證'
  132. : '下一步'}
  133. </Text>
  134. }
  135. onPress={() => {
  136. if (currentPassword) {
  137. handleVerifyPassword(currentPassword);
  138. }
  139. }}
  140. disabled={isPasswordVerified}
  141. extendedStyle={
  142. isPasswordVerified == true
  143. ? { backgroundColor: '#70787C' }
  144. : {}
  145. }
  146. />
  147. </View>
  148. {isPasswordVerified && (
  149. <View
  150. style={[
  151. styles.hiddenPasswordFields,
  152. isPasswordVerified
  153. ? styles.opacityFull
  154. : styles.opacityZero
  155. ]}
  156. >
  157. <NormalInput
  158. placeholder="新密碼"
  159. onChangeText={(t) => setNewPassword(t)}
  160. secureTextEntry={true}
  161. textContentType={'oneTimeCode'}
  162. />
  163. <NormalInput
  164. placeholder="確認密碼"
  165. onChangeText={(t) => setNewConfirmPassword(t)}
  166. secureTextEntry={true}
  167. textContentType={'oneTimeCode'}
  168. />
  169. <NormalButton
  170. title={
  171. <Text style={{ color: '#fff' }}>
  172. {isLoading2 ? '更改中...' : '確認'}
  173. </Text>
  174. }
  175. onPress={handlePasswordChange}
  176. />
  177. </View>
  178. )}
  179. {error && <Text style={styles.errorMessage}>{error}</Text>}
  180. </ScrollView>
  181. </SafeAreaView>
  182. );
  183. };
  184. const styles = StyleSheet.create({
  185. container: {
  186. flex: 1,
  187. marginHorizontal: 20
  188. },
  189. titleText: {
  190. fontSize: 24,
  191. fontWeight: '300'
  192. },
  193. bottomContainer: {
  194. flex: 3,
  195. paddingBottom: 100
  196. },
  197. breakline: {
  198. width: 24,
  199. height: 1,
  200. backgroundColor: '#000000',
  201. marginVertical: 17
  202. },
  203. text: {
  204. fontSize: 18,
  205. paddingBottom: 10
  206. },
  207. hiddenPasswordFields: {
  208. gap: 10,
  209. paddingTop: 10
  210. },
  211. opacityZero: {
  212. opacity: 0
  213. },
  214. opacityFull: {
  215. opacity: 1
  216. },
  217. errorMessage: {
  218. fontSize: 14,
  219. color: '#ff0033',
  220. fontWeight: '400',
  221. marginLeft: 10,
  222. marginTop: 10
  223. },
  224. footer: { color: '#02677D', fontSize: 16, paddingVertical: 10 }
  225. });
  226. export default changePasswordPageComponent;
  227. // <NormalButton
  228. // title={<Text className="text-white text-lg">確認</Text>}
  229. // onPress={() => {
  230. // // poSSIBLY ADD ERROR HANDLING AND LOADING
  231. // // authenticationService.changePassword(password, token);
  232. // router.replace('accountMainPage');
  233. // }}
  234. // />