Skip to content

Instantly share code, notes, and snippets.

@miracleonyenma
Created February 20, 2024 13:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save miracleonyenma/51115e9547dbd9fe1e65911935b21f8f to your computer and use it in GitHub Desktop.
Save miracleonyenma/51115e9547dbd9fe1e65911935b21f8f to your computer and use it in GitHub Desktop.
"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