Skip to content

Commit 3d5bbdf

Browse files
updated OTP screen
1 parent 294dac5 commit 3d5bbdf

File tree

2 files changed

+103
-3
lines changed

2 files changed

+103
-3
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { useRef } from 'react';
2+
import {
3+
View,
4+
TextInput,
5+
NativeSyntheticEvent,
6+
TextInputKeyPressEventData,
7+
Keyboard,
8+
} from 'react-native';
9+
10+
type OtpInputProps = {
11+
length: number;
12+
value: Array<string>;
13+
disabled: boolean;
14+
onChange: (value: Array<string>) => void;
15+
};
16+
17+
const OtpInput = ({ length, value, disabled, onChange }: OtpInputProps) => {
18+
const inputRefs = useRef<Array<TextInput | null>>([]);
19+
20+
const onChangeValue = (text: string, index: number) => {
21+
const newValue = value.map((item, valueIndex) => {
22+
if (valueIndex === index) {
23+
return text;
24+
}
25+
return item;
26+
});
27+
onChange(newValue);
28+
};
29+
30+
const handleChange = (text: string, index: number) => {
31+
onChangeValue(text, index);
32+
33+
if (text.length !== 0) {
34+
if (index === length - 1) {
35+
Keyboard.dismiss();
36+
} else {
37+
inputRefs.current[index + 1]?.focus();
38+
}
39+
} else {
40+
inputRefs.current[index - 1]?.focus();
41+
}
42+
};
43+
44+
const handleBackspace = (
45+
e: NativeSyntheticEvent<TextInputKeyPressEventData>,
46+
index: number,
47+
) => {
48+
const { nativeEvent } = e;
49+
if (nativeEvent.key === 'Backspace') {
50+
handleChange('', index);
51+
}
52+
};
53+
54+
return (
55+
<View className="w-full flex flex-row justify-between items-center">
56+
{[...new Array(length)].map((_, index) => (
57+
<TextInput
58+
ref={ref => {
59+
if (ref && !inputRefs.current.includes(ref)) {
60+
inputRefs.current = [...inputRefs.current, ref];
61+
}
62+
}}
63+
keyboardType="decimal-pad"
64+
key={index}
65+
maxLength={1}
66+
contextMenuHidden
67+
selectTextOnFocus
68+
editable={!disabled}
69+
testID={`OTPInput-${index}`}
70+
onChangeText={text => handleChange(text, index)}
71+
className="w-16 h-14 bg-[#262626] border border-[#F8D48D40] focus:border-[#F8D48D] rounded-lg text-[#FFF] text-xl text-center font-medium"
72+
onKeyPress={e => handleBackspace(e, index)}
73+
/>
74+
))}
75+
</View>
76+
);
77+
};
78+
79+
export default OtpInput;

apps/mobile/src/screens/Otp.tsx

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
1-
import { View, Text, TouchableOpacity, Image, TextInput } from 'react-native';
1+
import { useState } from 'react';
2+
import { View, Text, TouchableOpacity, Image } from 'react-native';
23
import Gradient from '../assets/gradient.png';
34
import OtpImage from '../assets/otp.png';
45
import { NativeStackScreenProps } from '@react-navigation/native-stack';
56
import { RootStackParamList } from '../navigation/navigator.types';
67
import IonIcon from 'react-native-vector-icons/Ionicons';
78
import { KeyboardAwareScrollView } from 'react-native-keyboard-controller';
9+
import OtpInput from '../components/OtpInput';
810

911
type OtpProps = NativeStackScreenProps<RootStackParamList, 'Otp'>;
1012

1113
const Otp = ({ navigation }: OtpProps) => {
14+
const [otpValue, setOtpValue] = useState<Array<string>>(['', '', '', '']);
15+
const [isBtnDisabled, setIsBtnDisabled] = useState(true);
16+
17+
const handleOtpChange = (value: Array<string>) => {
18+
setOtpValue(value);
19+
20+
const allFilled = value.every(v => v.length > 0);
21+
setIsBtnDisabled(!allFilled);
22+
};
23+
1224
return (
1325
<KeyboardAwareScrollView
1426
bottomOffset={100}
@@ -36,17 +48,26 @@ const Otp = ({ navigation }: OtpProps) => {
3648
<Text className="text-[#A3A3A3] text-center text-2xl font-medium mb-6 underline">
3749
RESEND?
3850
</Text>
39-
<TextInput
51+
{/* <TextInput
4052
keyboardType="numeric"
4153
placeholder="OTP"
4254
placeholderTextColor={'#fff'}
4355
// autoFocus={true}
4456
className="w-full bg-[#262626] p-3 border border-[#F8D48D40] focus:border-[#F8D48D] rounded-lg text-[#FFF] text-base"
57+
/> */}
58+
<OtpInput
59+
length={4}
60+
value={otpValue}
61+
disabled={false}
62+
onChange={handleOtpChange}
4563
/>
4664
<TouchableOpacity
4765
activeOpacity={0.8}
4866
onPress={() => navigation.navigate('Name')}
49-
className="bg-[#EDEAE2] rounded-lg py-3 mt-8"
67+
className={`bg-[#EDEAE2] rounded-lg py-3 mt-8 ${
68+
isBtnDisabled ? 'opacity-60' : ''
69+
}`}
70+
disabled={isBtnDisabled}
5071
>
5172
<Text className="text-center text-[#0A0A0A] font-semibold text-base">
5273
Next

0 commit comments

Comments
 (0)