changePasswordPageComponent.tsx 8.2 KB

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