mediahub-fe/components/auth/registration-otp-form.tsx

193 lines
5.9 KiB
TypeScript
Raw Normal View History

"use client";
import React, { useState, useEffect } from "react";
import { Button } from "@/components/ui/button";
import { useTranslations } from "next-intl";
import {
InputOTP,
InputOTPGroup,
InputOTPSeparator,
InputOTPSlot,
} from "@/components/ui/input-otp";
import { RegistrationOTPFormProps, UserCategory } from "@/types/registration";
import { useOTP } from "@/hooks/use-registration";
export const RegistrationOTPForm: React.FC<RegistrationOTPFormProps> = ({
email,
category,
memberIdentity,
onSuccess,
onError,
onResend,
className,
}) => {
const t = useTranslations("LandingPage");
const { verifyOTP, resendOTP, loading, error, formattedTime, canResend } = useOTP();
const [otpValue, setOtpValue] = useState("");
const handleOTPChange = (value: string) => {
setOtpValue(value);
};
const handleVerifyOTP = async () => {
if (otpValue.length !== 6) {
onError?.("Please enter a complete 6-digit OTP");
return;
}
try {
const userData = await verifyOTP(email, otpValue, category, memberIdentity);
onSuccess?.(userData);
} catch (error: any) {
onError?.(error.message || "OTP verification failed");
}
};
const handleResendOTP = async () => {
if (!canResend) {
onError?.("Please wait before requesting a new OTP");
return;
}
try {
const success = await resendOTP(email, category, memberIdentity);
if (success) {
onResend?.();
}
} catch (error: any) {
onError?.(error.message || "Failed to resend OTP");
}
};
const handleTypeOTP = (event: React.KeyboardEvent<HTMLInputElement>) => {
const { key } = event;
const target = event.currentTarget;
if (key === "Enter") {
event.preventDefault();
handleVerifyOTP();
}
};
return (
<div className={className}>
<div className="space-y-6">
{/* OTP Instructions */}
{/* <div className="px-8 lg:px-20 mb-6">
<p className="text-black dark:text-white text-2xl px-0 lg:px-20 font-semibold">
{t("enterOTP", { defaultValue: "Masukkan kode OTP" })}
</p>
<p className="text-red-500 text-sm px-0 lg:px-20">
{t("checkInbox", { defaultValue: "Silahkan cek inbox atau kotak spam pada email Anda." })}
</p>
<p className="text-gray-600 text-sm px-0 lg:px-20 mt-2">
OTP sent to: <span className="font-medium">{email}</span>
</p>
</div> */}
{/* OTP Input */}
<div className="flex justify-center mb-6">
<InputOTP
maxLength={6}
value={otpValue}
onChange={handleOTPChange}
disabled={loading}
className="gap-2"
>
<InputOTPGroup>
<InputOTPSlot
index={0}
onKeyDown={handleTypeOTP}
className="w-12 h-12 text-lg"
/>
<InputOTPSlot
index={1}
onKeyDown={handleTypeOTP}
className="w-12 h-12 text-lg"
/>
</InputOTPGroup>
<InputOTPSeparator />
<InputOTPGroup>
<InputOTPSlot
index={2}
onKeyDown={handleTypeOTP}
className="w-12 h-12 text-lg"
/>
<InputOTPSlot
index={3}
onKeyDown={handleTypeOTP}
className="w-12 h-12 text-lg"
/>
</InputOTPGroup>
<InputOTPSeparator />
<InputOTPGroup>
<InputOTPSlot
index={4}
onKeyDown={handleTypeOTP}
className="w-12 h-12 text-lg"
/>
<InputOTPSlot
index={5}
onKeyDown={handleTypeOTP}
className="w-12 h-12 text-lg"
/>
</InputOTPGroup>
</InputOTP>
</div>
{/* Error Message */}
{error && (
<p className="text-red-500 text-center">
<b>{error}</b>
</p>
)}
{/* Action Buttons */}
<div className="flex flex-row px-0 lg:px-28 justify-between items-center my-4">
<Button
type="button"
variant="outline"
onClick={handleResendOTP}
disabled={!canResend || loading}
className="bg-slate-300 dark:bg-black text-center rounded-lg mr-1 w-[200px] py-2 text-base"
>
{canResend
? t("resend", { defaultValue: "Resend OTP" })
: `${t("resending", { defaultValue: "Resending" })} (${formattedTime})`
}
</Button>
<Button
type="button"
onClick={handleVerifyOTP}
disabled={otpValue.length !== 6 || loading}
className="bg-red-700 w-[200px] py-2 text-center text-white rounded-lg ml-1 hover:bg-red-800"
>
{loading ? (
<div className="flex items-center gap-2">
<div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
Verifying...
</div>
) : (
t("next", { defaultValue: "Next" })
)}
</Button>
</div>
{/* Help Text */}
<div className="text-center px-8">
<p className="text-sm text-gray-600">
{t("otpHelp", { defaultValue: "Didn't receive the code? Check your spam folder or" })}{" "}
<button
type="button"
onClick={handleResendOTP}
disabled={!canResend || loading}
className="text-blue-600 hover:text-blue-800 underline disabled:opacity-50 disabled:cursor-not-allowed"
>
{t("resendOTP", { defaultValue: "resend OTP" })}
</button>
</p>
</div>
</div>
</div>
);
};