# OTP

The `Otp` component allows you to implement a One-Time Password (OTP) verification UI. With the `customUIRender` prop, you can fully customize the look and behavior of the OTP interface to match your project's needs.

## <mark style="color:red;">Installation Method</mark>

You can use the following command to install the extension with the latest plugins:

```bash
npx @akinon/projectzero@latest --plugins
```

### <mark style="color:red;">**Props**</mark>

<table><thead><tr><th width="148.53125">Prop</th><th width="188.6796875">Type</th><th width="102.2265625">Required</th><th>Description</th></tr></thead><tbody><tr><td>customUIRender</td><td>React.ReactNode</td><td>Optional</td><td>A render function to override the default OTP interface. Provides access to UI and control handlers</td></tr><tr><td>submitAction</td><td>SubmitHandler&#x3C;{ [key: string]: any }></td><td>Yes</td><td>A submit handler function triggered when OTP form is submitted.</td></tr><tr><td>data</td><td>{ [key: string]: any }</td><td>Yes</td><td>Data object containing required fields like phone number. OTP code will be appended here before submission</td></tr></tbody></table>

### <mark style="color:red;">**CustomUIRender Parameters**</mark>

<table><thead><tr><th width="147.28125">Parameter</th><th width="188.10546875">Type</th><th>Description</th></tr></thead><tbody><tr><td>closeHandler</td><td>() => void</td><td>Closes the popup manually.</td></tr><tr><td>resendHandler</td><td>() => void</td><td>Triggers OTP resend functionality.</td></tr><tr><td>onSubmit</td><td>(event: FormEvent&#x3C;HTMLFormElement>) => Promise&#x3C;void></td><td>Form submit function that wraps validation and calls submitAction.</td></tr><tr><td>otp</td><td>string</td><td>Current OTP value in the input field.</td></tr><tr><td>setOtp</td><td>(otp: string) => void</td><td>Updates the OTP input value.</td></tr><tr><td>hasError</td><td>boolean</td><td>Whether the current OTP input has a validation error.</td></tr><tr><td>error</td><td>string</td><td>Error message for invalid OTP attempts.</td></tr><tr><td>canResend</td><td>boolean</td><td>Indicates whether the resend option is enabled.</td></tr><tr><td>time</td><td>number</td><td>Countdown in seconds for the resend option.</td></tr><tr><td>codeLength</td><td>number</td><td>Expected number of digits in the OTP input.</td></tr><tr><td>setHasError</td><td>(hasError: boolean) => void</td><td>Allows toggling of error state manually.</td></tr></tbody></table>

## <mark style="color:red;">**Usage Example**</mark>

### <mark style="color:red;">**Default Usage**</mark>

```javascript
import PluginModule, { Component } from '@akinon/next/components/plugin-module';

<PluginModule
   component={Component.Otp}
   props={{
     data: getValues(),
     submitAction: registerHandler
   }}

 />
```

### <mark style="color:red;">Customizing OTP</mark>

```javascript
import PluginModule, { Component } from '@akinon/next/components/plugin-module';

<PluginModule
  component={Component.Otp}
  props={{
    data: getValues(),
    submitAction: registerHandler,
    customUIRender: ({
      closeHandler,
      resendHandler,
      onSubmit,
      otp,
      setOtp,
      hasError,
      error,
      canResend,
      time,
      codeLength,
      setHasError
    }) => {
      return (
        <div className="fixed left-0 top-0 z-50 flex h-screen w-screen items-end md:items-center md:justify-center md:bg-black/10">
          <div className="h-[calc(100vh-48px)] w-screen flex md:h-auto md:max-w-lg flex-col items-center rounded-sm bg-white p-8 shadow-xl">
            <div className="w-full flex items-center justify-end">
              <div className="cursor-pointer" onClick={closeHandler}>
                <svg
                  width="14"
                  height="14"
                  viewBox="0 0 14 14"
                  xmlns="http://www.w3.org/2000/svg"
                >
                  <g fill="#000" fillRule="nonzero">
                    <path d="M.684 14A.684.684 0 0 1 .2 12.833L12.833.2a.684.684 0 1 1 .967.967L1.167 13.8a.682.682 0 0 1-.483.2z" />
                    <path d="M13.316 14a.682.682 0 0 1-.483-.2L.2 1.167A.684.684 0 0 1 1.167.2L13.8 12.833A.684.684 0 0 1 13.316 14z" />
                  </g>
                </svg>
              </div>
            </div>
            <div className="flex flex-col items-center px-14 mt-5">
              <div className="text-2xl font-medium">OTP Verification</div>
              <div className="mt-2.5 text-center text-gray-700">
                {`Please enter the ${codeLength}-digit sms code sent to your registered number and email address`}
              </div>
            </div>
            <form
              onSubmit={onSubmit}
              className="flex flex-col items-center w-full"
            >
              <OtpInput
                value={otp}
                onChange={(otp) => {
                  setOtp(otp);
                  setHasError(false);
                }}
                numInputs={codeLength}
                containerStyle="mt-12 gap-2 flex-wrap"
                inputStyle={`h-12 w-8 md:h-16 md:w-12 rounded-md border border-gray-600 text-center text-lg ${hasError ? 'border-error' : ''}`}
                renderInput={(props) => <input {...props} />}
                skipDefaultStyles={true}
              />
              {error && <p className="text-xs text-error mt-2">{error}</p>}
              <Button
                type="submit"
                className="mt-5 h-auto w-full py-4 text-lg font-medium uppercase"
              >
                Verify
              </Button>
            </form>
            <div className="mt-6 flex flex-col items-center">
              <span className="text-gray-700">I didn’t receive a code</span>
              <div
                className={`font-medium underline cursor-pointer ${!canResend ? 'cursor-not-allowed text-gray-700' : ''}`}
                onClick={resendHandler}
              >
                RESEND
              </div>
            </div>
          </div>
        </div>
      );
    }
  }}
/>;
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.akinon.com/technical-guides/project-zero/next.js/plugins/otp.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
