@@ -12,7 +12,7 @@ import {
1212import { useNavigation } from '@react-navigation/native' ;
1313import { NativeStackNavigationProp } from '@react-navigation/native-stack' ;
1414import { Container } from '@components/common' ;
15- import { ChevronLeft , ChevronDown , CircleCheck } from 'lucide-react-native' ;
15+ import { ChevronLeft , ChevronDown , CircleCheck , CircleAlert } from 'lucide-react-native' ;
1616import { useGetMe , usePutMe , postPhoneSend , postPhoneResend , postPhoneVerify } from '@apis' ;
1717import { MenuStackParamList } from '@navigation/student/MenuNavigator' ;
1818import { SafeAreaView } from 'react-native-safe-area-context' ;
@@ -29,8 +29,9 @@ const EditPhoneNumberScreen = () => {
2929 const [ phoneNumber , setPhoneNumber ] = useState ( data ?. phoneNumber || '' ) ;
3030 const [ carrier , setCarrier ] = useState < CarrierValue | null > ( null ) ;
3131 const [ verificationCode , setVerificationCode ] = useState ( '' ) ;
32+ const [ verifyFeedbackMessage , setVerifyFeedbackMessage ] = useState < string | null > ( null ) ;
3233 const [ isCodeSent , setIsCodeSent ] = useState ( false ) ;
33- const [ carrierModalVisible , setCarrierModalVisible ] = useState ( false ) ;
34+ // const [carrierModalVisible, setCarrierModalVisible] = useState(false);
3435 const [ timer , setTimer ] = useState ( 120 ) ; // 2분 = 120초
3536
3637 useEffect ( ( ) => {
@@ -43,6 +44,14 @@ const EditPhoneNumberScreen = () => {
4344 } , [ isCodeSent , timer ] ) ;
4445
4546 const handleSendCode = async ( ) => {
47+ if ( phoneNumber . length >= 2 && ! phoneNumber . startsWith ( '01' ) ) {
48+ showToast ( 'error' , '01로 시작하는 숫자를 입력해 주세요.' ) ;
49+ return ;
50+ }
51+ if ( phoneNumber . length !== 11 ) {
52+ showToast ( 'error' , '휴대폰 번호는 11자를 입력해 주세요.' ) ;
53+ return ;
54+ }
4655 try {
4756 const response = await postPhoneSend ( phoneNumber ) ;
4857 if ( response . data ?. success ) {
@@ -74,22 +83,22 @@ const EditPhoneNumberScreen = () => {
7483 }
7584 } ;
7685
77- const handleVerify = async ( ) => {
78- if ( ! verificationCode || verificationCode . length !== 6 ) {
79- showToast ( 'error' , '인증번호 6자리를 입력해주세요.' ) ;
80- return ;
86+ const handleVerifyCodeChange = ( text : string ) => {
87+ if ( / ^ [ 0 - 9 ] * $ / . test ( text ) && text . length <= 6 ) {
88+ setVerificationCode ( text ) ;
8189 }
90+ } ;
8291
92+ const handleVerify = async ( ) => {
8393 try {
8494 const response = await postPhoneVerify ( phoneNumber , verificationCode ) ;
8595 if ( response . data ?. success ) {
86- const verifyMessage = response . data . message || '인증이 완료되었습니다.' ;
8796 // 인증 성공 시 휴대폰 번호 업데이트
8897 putMeMutate (
8998 { phoneNumber } ,
9099 {
91100 onSuccess : ( ) => {
92- showToast ( 'success' , verifyMessage ) ;
101+ showToast ( 'success' , '휴대폰 번호 변경이 완료되었습니다.' ) ;
93102 navigation . goBack ( ) ;
94103 } ,
95104 onError : ( ) => {
@@ -98,11 +107,11 @@ const EditPhoneNumberScreen = () => {
98107 }
99108 ) ;
100109 } else {
101- showToast ( 'error' , response . data ?. message || '인증에 실패했습니다 .' ) ;
110+ setVerifyFeedbackMessage ( response . data ?. message || '인증번호를 다시 확인해주세요 .' ) ;
102111 }
103112 } catch ( error ) {
104113 console . error ( 'Failed to verify verification code:' , error ) ;
105- showToast ( 'error' , '인증에 실패했습니다.' ) ;
114+ showToast ( 'error' , ( error as Error ) . message || '인증에 실패했습니다.' ) ;
106115 }
107116 } ;
108117
@@ -117,6 +126,18 @@ const EditPhoneNumberScreen = () => {
117126 return `${ minutes } :${ secs . toString ( ) . padStart ( 2 , '0' ) } ` ;
118127 } ;
119128
129+ const isValidPhone = / ^ 0 1 \d { 9 } $ / . test ( phoneNumber ) ;
130+
131+ const getPhoneFeedbackMessage = ( ) : string | null => {
132+ if ( phoneNumber . length >= 2 && ! phoneNumber . startsWith ( '01' ) ) {
133+ return '01로 시작하는 숫자를 입력해 주세요.' ;
134+ }
135+ if ( phoneNumber . length > 0 && phoneNumber . length !== 11 ) {
136+ return '휴대폰 번호는 11자를 입력해 주세요.' ;
137+ }
138+ return null ;
139+ } ;
140+
120141 const handlePhoneNumberChange = ( text : string ) => {
121142 const phoneRegex = / ^ [ 0 - 9 ] * $ / ;
122143 if ( phoneRegex . test ( text ) && text . length <= 11 ) {
@@ -159,19 +180,29 @@ const EditPhoneNumberScreen = () => {
159180 />
160181 { isCodeSent && (
161182 < Pressable
183+ disabled = { timer > 0 }
162184 className = 'bg-primary-500 items-center justify-center rounded-[8px]'
163- style = { { width : 100 , height : 48 } }
185+ style = { { width : 100 , height : 48 , opacity : timer > 0 ? 0.5 : 1 } }
164186 onPress = { handleResendCode } >
165187 < Text className = 'text-16m text-white' > 재전송</ Text >
166188 </ Pressable >
167189 ) }
168190 </ View >
169- { isCodeSent && (
170- < View className = 'flex-row items-center gap-2' >
171- < CircleCheck color = { colors [ 'blue-500' ] } size = { 14 } />
172- < Text className = 'text-12r text-blue-500' > 문자로 인증번호를 전송했어요</ Text >
173- </ View >
174- ) }
191+ < View className = 'flex-row items-center gap-2' >
192+ { isCodeSent ? (
193+ < >
194+ < CircleCheck color = { colors [ 'blue-500' ] } size = { 14 } />
195+ < Text className = 'text-12r text-blue-500' > 문자로 인증번호를 전송했어요</ Text >
196+ </ >
197+ ) : (
198+ < >
199+ { getPhoneFeedbackMessage ( ) && (
200+ < CircleAlert size = { 14 } color = { colors [ 'red-500' ] } />
201+ ) }
202+ < Text className = 'text-12r text-red-500' > { getPhoneFeedbackMessage ( ) } </ Text >
203+ </ >
204+ ) }
205+ </ View >
175206 </ View >
176207 { /* <View className='gap-[10px]'>
177208 <View className='gap-[6px]'>
@@ -197,7 +228,7 @@ const EditPhoneNumberScreen = () => {
197228 < View className = 'w-full' style = { { position : 'relative' } } >
198229 < TextInput
199230 value = { verificationCode }
200- onChangeText = { setVerificationCode }
231+ onChangeText = { handleVerifyCodeChange }
201232 placeholder = '인증번호 6자리'
202233 keyboardType = 'number-pad'
203234 maxLength = { 6 }
@@ -215,6 +246,12 @@ const EditPhoneNumberScreen = () => {
215246 < Text className = 'text-14m text-primary-500' > { formatTime ( timer ) } </ Text >
216247 </ View >
217248 </ View >
249+ { verifyFeedbackMessage && (
250+ < View className = 'flex-row items-center gap-2' >
251+ < CircleAlert size = { 14 } color = { colors [ 'red-500' ] } />
252+ < Text className = 'text-12r text-red-500' > { verifyFeedbackMessage } </ Text >
253+ </ View >
254+ ) }
218255 </ View >
219256 ) }
220257 </ View >
@@ -224,8 +261,8 @@ const EditPhoneNumberScreen = () => {
224261 { ! isCodeSent || timer == 0 ? (
225262 < Pressable
226263 onPress = { handleSendCode }
227- disabled = { phoneNumber . length !== 11 }
228- className = { `bg-primary-500 items-center rounded-[8px] px-[12px] py-[10px] ${ phoneNumber . length !== 11 ? 'opacity-50' : '' } ` } >
264+ disabled = { ! isValidPhone }
265+ className = { `bg-primary-500 items-center rounded-[8px] px-[12px] py-[10px] ${ ! isValidPhone ? 'opacity-50' : '' } ` } >
229266 < Text className = 'text-16m text-white' > 인증번호 받기</ Text >
230267 </ Pressable >
231268 ) : (
0 commit comments