frontend/app/components/input-otp.tsx
2025-07-29 11:05:49 +02:00

82 lines
2.3 KiB
TypeScript

import { AlertCircleIcon, LoaderIcon } from "lucide-react";
import { useState } from "react";
import { Alert, AlertDescription } from "./ui/alert";
import { InputOTP, InputOTPGroup, InputOTPSlot } from "./ui/input-otp";
import { verifyOtp } from "~/lib/api";
import { useNavigate } from "react-router";
export default function OtpInput({
email,
setOtpError,
otpError,
}: {
email: string;
setOtpError: (error: string | null) => void;
otpError: string | null;
}) {
const navigate = useNavigate();
const [isVerifying, setIsVerifying] = useState(false);
// Handle OTP verification
const handleVerifyOtp = (otpCode: string) => {
setIsVerifying(true);
setOtpError(null);
verifyOtp({ otpCode, email })
.then((data) => {
setIsVerifying(false);
// Check if user is registered
if (data.token) {
navigate(`/register?email=${data.email}&token=${data.token}`, {
replace: true,
});
} else {
navigate("/", {
replace: true,
})
}
})
.catch((error) => {
setOtpError(
error instanceof Error
? error.message
: "Code de vérification invalide"
)
setIsVerifying(false)
});
};
return (
<div className="space-y-4">
<div className="flex-1 flex items-center justify-center">
<InputOTP
maxLength={6}
onComplete={(value) => handleVerifyOtp(value)}
disabled={isVerifying}
>
<InputOTPGroup>
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
<InputOTPSlot index={2} />
<InputOTPSlot index={3} />
<InputOTPSlot index={4} />
<InputOTPSlot index={5} />
</InputOTPGroup>
</InputOTP>
</div>
{isVerifying && (
<div className="flex justify-center items-center py-2">
<LoaderIcon className="h-5 w-5 animate-spin text-primary mr-2" />
<span className="text-sm">Vérification en cours...</span>
</div>
)}
{otpError && (
<Alert variant="destructive" className="mt-2 pb-2">
<AlertCircleIcon className="h-4 w-4" />
<AlertDescription>{otpError}</AlertDescription>
</Alert>
)}
</div>
);
}