Created
February 20, 2024 13:15
-
-
Save miracleonyenma/51115e9547dbd9fe1e65911935b21f8f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use client"; | |
import React, { use, useEffect, useState } from "react"; | |
import { useFormik } from "formik"; | |
import * as Yup from "yup"; | |
import { useRouter, useSearchParams } from "next/navigation"; | |
interface OTPFieldProps { | |
value: string; | |
onChange: (value: string) => void; | |
} | |
export const OTPField: React.FC<OTPFieldProps> = ({ value, onChange }) => { | |
const [code, setCode] = useState<string[]>(new Array(4).fill("")); | |
const handleChange = (element: any, index: number) => { | |
if (isNaN(element.value)) return false; | |
setCode([...code.map((d, idx) => (idx === index ? element.value : d))]); | |
if (element.nextSibling && element.value !== "") { | |
element.nextSibling.focus(); | |
} | |
// go to previous input if value is empty or backspace is pressed | |
if (element.previousSibling) { | |
if (element.value === "" || element.value === " ") { | |
element.previousSibling.focus(); | |
} | |
} | |
}; | |
const handlePaste = (e: any) => { | |
e.preventDefault(); | |
const paste = e.clipboardData.getData("text"); | |
if (paste.length === 4) { | |
setCode([...paste]); | |
} | |
}; | |
useEffect(() => { | |
onChange(code.join("")); | |
}, [code]); | |
return ( | |
<div className="form-input"> | |
{code.map((data, index) => { | |
return ( | |
<input | |
key={index} | |
type="text" | |
name="otp" | |
className="form-input--otp form-input" | |
maxLength={1} | |
value={data} | |
onChange={(e) => handleChange(e.target, index)} | |
onFocus={(e) => e.target.select()} | |
onPaste={(e) => handlePaste(e)} | |
/> | |
); | |
})} | |
</div> | |
); | |
}; | |
const OTPForm = () => { | |
const router = useRouter(); | |
const searchParams = useSearchParams(); | |
const formik = useFormik({ | |
initialValues: { | |
otp: "", | |
}, | |
validationSchema: Yup.object({ | |
otp: Yup.string() | |
.min(4, "Must be 4 characters or more") | |
.required("Required"), | |
}), | |
onSubmit: (values) => { | |
console.log(JSON.stringify(values, null, 2)); | |
const from = searchParams.get("from"); | |
// route to /app | |
router.push(`/app/${from}`); | |
}, | |
}); | |
useEffect(() => { | |
console.log(formik.values.otp); | |
}, [formik.values.otp]); | |
return ( | |
<form onSubmit={formik.handleSubmit} className="site-form"> | |
<div className="wrapper"> | |
<div className="form-control form-control--otp"> | |
<OTPField | |
value={formik.values.otp} | |
onChange={(value) => formik.setFieldValue("otp", value)} | |
/> | |
{formik.touched.otp && formik.errors.otp ? ( | |
<div className="form-error">{formik.errors.otp}</div> | |
) : null} | |
</div> | |
</div> | |
<div className="action-cont"> | |
<button | |
type="submit" | |
className="btn btn--pill btn--fat btn--full btn--primary" | |
> | |
Verify | |
</button> | |
</div> | |
</form> | |
); | |
}; | |
export default OTPForm; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment