verification.tsx 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. import { View, Text, StyleSheet, TextInput, Pressable } from 'react-native';
  2. import { useEffect, useState } from 'react';
  3. import PhoneInput from '../../../global/phone_input';
  4. import NumberInput from '../../../global/number_input';
  5. import NormalButton from '../../../global/normal_button';
  6. import useSignUpStore from '../../../../providers/signup_form_store';
  7. import NormalInput from '../../../global/normal_input';
  8. import { authenticationService } from '../../../../service/authService';
  9. import { usePushNotifications } from '../../../../app/hooks/usePushNotifications';
  10. type VerificationProps = {
  11. setScreen: React.Dispatch<React.SetStateAction<number>>;
  12. };
  13. const Verification: React.FC<VerificationProps> = ({ setScreen }) => {
  14. const { signUpFormData, setSignUpFormData } = useSignUpStore();
  15. const [error, setError] = useState('');
  16. const [otp, setOtp] = useState('');
  17. const [canSendOtp, setCanSendOtp] = useState(true);
  18. const [lockPhoneInput, setLockPhoneInput] = useState(false);
  19. const [countdown, setCountdown] = useState(0);
  20. const [loading, setLoading] = useState(false);
  21. const { expoPushToken } = usePushNotifications();
  22. const notify_session_id = expoPushToken?.data || '';
  23. const handleVerification = async () => {
  24. setLoading(true);
  25. if (signUpFormData.phone === '' || otp === '') {
  26. setError('請確保所有資料都已填寫。');
  27. } else {
  28. setError('');
  29. console.log('signUpFormData.phone', signUpFormData.phone);
  30. console.log('otp', otp);
  31. console.log('notifysession id in handleVerification', expoPushToken?.data);
  32. try {
  33. const result = await authenticationService.verifyPhoneOtp(
  34. signUpFormData.phone,
  35. otp,
  36. expoPushToken?.data
  37. );
  38. if (result.status === 200) {
  39. setScreen(2);
  40. } else {
  41. setError('OTP驗證失敗,請重新輸入');
  42. }
  43. } catch (error) {
  44. console.log('error', error);
  45. setError('OTP驗證失敗,請重新輸入');
  46. } finally {
  47. setLoading(false);
  48. }
  49. }
  50. };
  51. useEffect(() => {
  52. let timer: NodeJS.Timeout;
  53. if (countdown > 0) {
  54. timer = setInterval(() => {
  55. setCountdown((prev) => prev - 1);
  56. }, 1000);
  57. } else {
  58. setLockPhoneInput(false); // Add this line to unlock input when countdown reaches 0
  59. }
  60. return () => {
  61. if (timer) clearInterval(timer);
  62. };
  63. }, [countdown]);
  64. const handleSubmitOtp = () => {
  65. if (signUpFormData.phone) {
  66. if (canSendOtp) {
  67. setCanSendOtp(false);
  68. setLockPhoneInput(true);
  69. setCountdown(60);
  70. authenticationService.sendOtpToSignUpPhone(signUpFormData.phone);
  71. setTimeout(() => {
  72. setCanSendOtp(true);
  73. setLockPhoneInput(false);
  74. }, 60000);
  75. setError('');
  76. } else {
  77. setError('請等待一分鐘後再重新發送。');
  78. }
  79. } else {
  80. setError('請確保所有資料都已填寫。');
  81. }
  82. };
  83. const handleChangePhoneNumber = () => {
  84. setLockPhoneInput(false);
  85. };
  86. const otpButtonText = lockPhoneInput ? (
  87. <Text style={{ color: '#fff' }}>已發送 ({countdown}s)</Text>
  88. ) : (
  89. <Text style={{ color: '#fff' }}>發送</Text>
  90. );
  91. return (
  92. <>
  93. <View style={styles.container}>
  94. <Text style={styles.text}>請驗證您的手機號碼</Text>
  95. <PhoneInput
  96. value={signUpFormData?.phone || ''}
  97. onChangeText={(phone: any) =>
  98. setSignUpFormData({
  99. ...signUpFormData,
  100. phone: phone
  101. })
  102. }
  103. placeholder="請輸入手機號碼"
  104. editable={!lockPhoneInput}
  105. extendedStyle={{ opacity: !lockPhoneInput ? 1 : 0.5 }}
  106. />
  107. {/* <NormalInput
  108. placeholder="請填寫您的手機號碼"
  109. onChangeText={(phone) =>
  110. setSignUpFormData({
  111. ...signUpFormData,
  112. phone: phone
  113. })
  114. }
  115. editable={!lockPhoneInput}
  116. extendedStyle={{ opacity: !lockPhoneInput ? 1 : 0.5 }}
  117. autoCapitalize="none"
  118. /> */}
  119. <View
  120. style={{
  121. display: 'flex',
  122. flexDirection: 'row',
  123. paddingVertical: 10,
  124. gap: 10
  125. }}
  126. >
  127. <NumberInput placeholder="OTP驗證碼" onChangeText={setOtp} extendedStyle={{ flex: 1 }} />
  128. <NormalButton
  129. title={otpButtonText}
  130. onPress={handleSubmitOtp}
  131. extendedStyle={{ flex: 1 / 2, opacity: !lockPhoneInput ? 1 : 0.5 }}
  132. />
  133. </View>
  134. <NormalButton
  135. title={<Text style={{ color: '#fff' }}>{loading ? '驗證中...' : '驗證'}</Text>}
  136. onPress={() => {
  137. handleVerification();
  138. }}
  139. extendedStyle={{}}
  140. />
  141. {error && <Text style={styles.errorMessage}>{error}</Text>}
  142. {/* <Pressable onPress={handleChangePhoneNumber}>
  143. <Text style={[styles.footer, { opacity: lockPhoneInput ? 1 : 0 }]}>修改手機號碼</Text>
  144. </Pressable> */}
  145. </View>
  146. </>
  147. );
  148. };
  149. const styles = StyleSheet.create({
  150. container: {
  151. flex: 1,
  152. marginHorizontal: 20
  153. },
  154. text: {
  155. fontSize: 20,
  156. paddingBottom: 10
  157. },
  158. errorMessage: {
  159. fontSize: 16,
  160. color: '#ff0033',
  161. fontWeight: '400',
  162. paddingVertical: 10
  163. },
  164. footer: { color: '#02677D', fontSize: 16, paddingVertical: 10 }
  165. });
  166. export default Verification;