From 5470c1e75db0cf86a2cce8e4be839c50b6767667 Mon Sep 17 00:00:00 2001 From: harmanbatheja15 Date: Sat, 1 Feb 2025 20:33:35 +0530 Subject: [PATCH] updated OTP screen --- apps/mobile/src/components/OtpInput.tsx | 79 +++++++++++++++++++++++++ apps/mobile/src/screens/Otp.tsx | 27 ++++++++- 2 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 apps/mobile/src/components/OtpInput.tsx diff --git a/apps/mobile/src/components/OtpInput.tsx b/apps/mobile/src/components/OtpInput.tsx new file mode 100644 index 0000000..d42731b --- /dev/null +++ b/apps/mobile/src/components/OtpInput.tsx @@ -0,0 +1,79 @@ +import { useRef } from 'react'; +import { + View, + TextInput, + NativeSyntheticEvent, + TextInputKeyPressEventData, + Keyboard, +} from 'react-native'; + +type OtpInputProps = { + length: number; + value: Array; + disabled: boolean; + onChange: (value: Array) => void; +}; + +const OtpInput = ({ length, value, disabled, onChange }: OtpInputProps) => { + const inputRefs = useRef>([]); + + const onChangeValue = (text: string, index: number) => { + const newValue = value.map((item, valueIndex) => { + if (valueIndex === index) { + return text; + } + return item; + }); + onChange(newValue); + }; + + const handleChange = (text: string, index: number) => { + onChangeValue(text, index); + + if (text.length !== 0) { + if (index === length - 1) { + Keyboard.dismiss(); + } else { + inputRefs.current[index + 1]?.focus(); + } + } else { + inputRefs.current[index - 1]?.focus(); + } + }; + + const handleBackspace = ( + e: NativeSyntheticEvent, + index: number, + ) => { + const { nativeEvent } = e; + if (nativeEvent.key === 'Backspace') { + handleChange('', index); + } + }; + + return ( + + {[...new Array(length)].map((_, index) => ( + { + if (ref && !inputRefs.current.includes(ref)) { + inputRefs.current = [...inputRefs.current, ref]; + } + }} + keyboardType="decimal-pad" + key={index} + maxLength={1} + contextMenuHidden + selectTextOnFocus + editable={!disabled} + testID={`OTPInput-${index}`} + onChangeText={text => handleChange(text, index)} + className="w-16 h-14 bg-[#262626] border border-[#F8D48D40] focus:border-[#F8D48D] rounded-lg text-[#FFF] text-xl text-center font-medium" + onKeyPress={e => handleBackspace(e, index)} + /> + ))} + + ); +}; + +export default OtpInput; diff --git a/apps/mobile/src/screens/Otp.tsx b/apps/mobile/src/screens/Otp.tsx index 32748dd..e6764ce 100644 --- a/apps/mobile/src/screens/Otp.tsx +++ b/apps/mobile/src/screens/Otp.tsx @@ -1,14 +1,26 @@ -import { View, Text, TouchableOpacity, Image, TextInput } from 'react-native'; +import { useState } from 'react'; +import { View, Text, TouchableOpacity, Image } from 'react-native'; import Gradient from '../assets/gradient.png'; import OtpImage from '../assets/otp.png'; import { NativeStackScreenProps } from '@react-navigation/native-stack'; import { RootStackParamList } from '../navigation/navigator.types'; import IonIcon from 'react-native-vector-icons/Ionicons'; import { KeyboardAwareScrollView } from 'react-native-keyboard-controller'; +import OtpInput from '../components/OtpInput'; type OtpProps = NativeStackScreenProps; const Otp = ({ navigation }: OtpProps) => { + const [otpValue, setOtpValue] = useState>(['', '', '', '']); + const [isBtnDisabled, setIsBtnDisabled] = useState(true); + + const handleOtpChange = (value: Array) => { + setOtpValue(value); + + const allFilled = value.every(v => v.length > 0); + setIsBtnDisabled(!allFilled); + }; + return ( { RESEND? - */} + navigation.navigate('Name')} - className="bg-[#EDEAE2] rounded-lg py-3 mt-8" + className={`bg-[#EDEAE2] rounded-lg py-3 mt-8 ${ + isBtnDisabled ? 'opacity-60' : '' + }`} + disabled={isBtnDisabled} > Next