Skip to content

Commit

Permalink
Merge pull request #319 from rishabhm05/reactotpchallenge
Browse files Browse the repository at this point in the history
ReactOtp Challenge
  • Loading branch information
sadanandpai authored Nov 2, 2023
2 parents 753c800 + 05ba408 commit 99cf3fb
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 0 deletions.
11 changes: 11 additions & 0 deletions react/src/helpers/challenges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -434,4 +434,15 @@ export const challenges = new Map<string, Challenge>([
tags: [],
},
],
[
'otp',
{
title: 'OTP',
link: 'otp',
difficulty: 'medium',
developer: 'rishabhm05',
tags: [],
isNew: true,
},
],
]);
69 changes: 69 additions & 0 deletions react/src/machine-coding/otp/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React, { useState, useRef } from 'react';
import styles from './otp.module.css';
const App = () => {
let [otpfields, setOtpFields] = useState(Array(4).fill(''));
let otpinputref = useRef([]);
const handleOtp = (e, index) => {
const numericValue = e.target.value.replace(/[^0-9]/g, '');
const singleDigitValue = numericValue.slice(0, 1);
let copyotpfields = [...otpfields];
copyotpfields[index] = singleDigitValue;
if (index < otpfields.length - 1) {
otpinputref.current[index + 1].focus();
}
setOtpFields(copyotpfields);
};
const handleKeyDown = (e, index) => {
if (e.key === 'Backspace') {
e.preventDefault();
let copyotpfields = [...otpfields];
copyotpfields[index] = '';
setOtpFields(copyotpfields);
if (index > 0) {
otpinputref.current[index - 1].focus();
}
} else if (e.key === 'ArrowRight' && index < otpfields.length - 1) {
otpinputref.current[index + 1].focus();
} else if (e.key === 'ArrowLeft' && index > 0) {
otpinputref.current[index - 1].focus();
}
};
const handlePaste = (e) => {
e.preventDefault();
const pastedData = e.clipboardData.getData('text');
if (/^[0-9]*$/.test(pastedData)) {
const copyotpfields = [...otpfields];
for (let i = 0; i < copyotpfields.length; i++) {
if (i < pastedData.length) {
copyotpfields[i] = pastedData[i];
} else {
break;
}
}
setOtpFields(copyotpfields);
}
};
return (
<>
<div className={styles.otpFields}>
<div className={styles.otpinput}>
{otpfields.map((_, index) => {
return (
<input
key={index}
onKeyDown={(e) => handleKeyDown(e, index)}
onPaste={handlePaste}
ref={(el) => (otpinputref.current[index] = el)}
onChange={(e) => handleOtp(e, index)}
value={otpfields[index]}
type="number"
/>
);
})}
</div>
</div>
</>
);
};

export default App;
27 changes: 27 additions & 0 deletions react/src/machine-coding/otp/otp.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.otpFields {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;

margin: auto;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}

.otpinput {
display: flex;
gap: 1rem;
align-items: center;
justify-content: center;
}
.otpinput input {
width: 3rem;
height: 3rem;
text-align: center;

border: 1px solid rgba(0, 0, 0, 0.3);
}
2 changes: 2 additions & 0 deletions react/src/pages/Challenge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import YourSport from '@/machine-coding/your-sport';
import ModalPopup from '@/machine-coding/modal-popup/App';
import EmojiPicker from '@/machine-coding/emoji-picker/App';
import ProgrammingLanguageMultiverse from '@/machine-coding/programming-languages-multiverse';
import Otp from '@/machine-coding/otp/App';
import { challenges } from '@/helpers/challenges';
import { useParams } from 'react-router-dom';

Expand Down Expand Up @@ -83,6 +84,7 @@ const reactChallenges = {
'modal-popup':<ModalPopup/>,
'emoji-picker':<EmojiPicker/>,
'programming-languages-multiverse': <ProgrammingLanguageMultiverse />,
otp: <Otp />,
};

function Challenge() {
Expand Down

0 comments on commit 99cf3fb

Please sign in to comment.