changePasswordPageComponent.tsx 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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. import { useTranslation } from '../../util/hooks/useTranslation';
  12. const changePasswordPageComponent = () => {
  13. const { user, setUser } = useContext(AuthContext);
  14. const [token, setToken] = useState<string | null>(null);
  15. const [currentPassword, setCurrentPassword] = useState<string | null>(null);
  16. const [newPassword, setNewPassword] = useState<string | null>(null);
  17. const [newConfirmPassword, setNewConfirmPassword] = useState<string | null>(null);
  18. const [isPasswordVerified, setIsPasswordVerified] = useState<boolean>(false);
  19. const [error, setError] = useState<string | null>(null);
  20. const [isLoading, setIsLoading] = useState(false);
  21. const [isLoading2, setIsLoading2] = useState(false);
  22. const { t } = useTranslation();
  23. useEffect(() => {
  24. const getToken = async () => {
  25. const storedToken = await SecureStore.getItemAsync('accessToken');
  26. setToken(storedToken);
  27. };
  28. getToken();
  29. }, []);
  30. const handleVerifyPassword = async (currentPassword: string) => {
  31. try {
  32. setIsLoading(true);
  33. if (!currentPassword) {
  34. setError(t('accountSettings.change_password.enter_password_error'));
  35. return;
  36. }
  37. if (!user || !user.email) {
  38. setError(t('accountSettings.change_password.user_verification_error'));
  39. return;
  40. }
  41. const success = await authenticationService.phoneLogin(user.phone, currentPassword);
  42. if (success) {
  43. setIsPasswordVerified(true);
  44. setError('');
  45. return true;
  46. } else {
  47. setError(t('accountSettings.change_password.incorrect_password'));
  48. }
  49. } catch (error) {
  50. console.error('Error verifying password:', error);
  51. setError(t('accountSettings.change_password.incorrect_password'));
  52. return false;
  53. } finally {
  54. setIsLoading(false);
  55. }
  56. };
  57. const handlePasswordChange = async () => {
  58. try {
  59. setIsLoading2(true);
  60. if (newPassword !== newConfirmPassword) {
  61. setError(t('accountSettings.change_password.password_mismatch'));
  62. return;
  63. }
  64. if (!newConfirmPassword || !token) {
  65. setError(t('accountSettings.change_password.enter_new_password'));
  66. return;
  67. }
  68. const success = await authenticationService.changePassword(newConfirmPassword, token);
  69. if (success) {
  70. setError('');
  71. router.replace('accountMainPage');
  72. } else {
  73. setError(t('accountSettings.change_password.change_password_failed'));
  74. }
  75. } catch (error) {
  76. console.error('Error changing password:', error);
  77. setError(t('accountSettings.change_password.general_error'));
  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 }}>{t('accountSettings.change_password.change_password_title')}</Text>
  98. <Text className="text-xl ">{t('accountSettings.change_password.enter_current_password')}</Text>
  99. <View className="py-2">
  100. <NormalInput
  101. placeholder={t('accountSettings.change_password.account_password')}
  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 ? t('accountSettings.change_password.verifying') : isPasswordVerified ? t('accountSettings.change_password.verified') : t('common.next')}
  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={t('accountSettings.change_password.new_password')}
  131. onChangeText={(t) => setNewPassword(t)}
  132. secureTextEntry={true}
  133. textContentType={'oneTimeCode'}
  134. />
  135. <NormalInput
  136. placeholder={t('accountSettings.change_password.confirm_password')}
  137. onChangeText={(t) => setNewConfirmPassword(t)}
  138. secureTextEntry={true}
  139. textContentType={'oneTimeCode'}
  140. />
  141. <NormalButton
  142. title={<Text style={{ color: '#fff' }}>{isLoading2 ? t('accountSettings.change_password.changing') : t('common.confirm')}</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;