# 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>
      );
    }
  }}
/>;
```
