changePasswordPageComponent.tsx 7.7 KB

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