changePasswordPageComponent.tsx 7.8 KB

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