"use client"; import Image from "next/image"; import Script from "next/script"; import { signIn } from "next-auth/react"; import { useTranslations } from "next-intl"; import { useActionState, useEffect, useRef, useState } from "react"; import { type RegisterState, register } from "@/actions/register"; import Link from "@/components/link"; import { signInWithTransientRetry } from "@/lib/auth/sign-in-retry"; interface RegisterFormProps { hotelName: string; captcha: { provider: string; siteKey?: string }; error?: string; nonce?: string; } function passwordStrength(pw: string): { score: number; label: string; color: string; } { let score = 0; if (pw.length >= 8) score += 1; if (pw.length >= 12) score += 1; if (/[a-z]/.test(pw) && /[A-Z]/.test(pw)) score += 1; if (/\d/.test(pw)) score += 1; if (/[^a-zA-Z0-9]/.test(pw)) score += 1; if (score <= 1) return { score, label: "Weak", color: "#ef4444" }; if (score <= 2) return { score, label: "Fair", color: "#f59e0b" }; if (score <= 3) return { score, label: "Good", color: "#22c55e" }; return { score: 5, label: "Strong", color: "#16a34a" }; } export function RegisterForm({ hotelName, captcha, error, nonce, }: RegisterFormProps) { const t = useTranslations("pages.register"); const showCaptcha = captcha.provider !== "none" && !!captcha.siteKey; const [state, formAction, isPending] = useActionState< RegisterState, FormData >(register, { error: null, ok: false }); const [termsAccepted, setTermsAccepted] = useState(false); const [termsError, setTermsError] = useState(false); const termsRef = useRef(null); const [password, setPassword] = useState(""); const [showPassword, setShowPassword] = useState(false); const [showConfirm, setShowConfirm] = useState(false); const [signingIn, setSigningIn] = useState(false); const credentialsRef = useRef<{ username: string; password: string } | null>( null, ); const autoLoginStartedRef = useRef(false); const strength = passwordStrength(password); // Successful sign-up: sign in with the submitted credentials and go // straight to /me. If the automatic sign-in is refused (e.g. email // verification required), fall back to the regular login page. useEffect(() => { if (!state.ok || autoLoginStartedRef.current) return; autoLoginStartedRef.current = true; const creds = credentialsRef.current; if (!creds) { window.location.href = "/login?registered=1"; return; } let cancelled = false; setSigningIn(true); (async () => { try { const res = await signInWithTransientRetry(() => signIn("credentials", { ...creds, code: "", redirect: false }), ); if (!cancelled && res && !res.error) { window.location.href = "/me"; return; } } catch { /* fall through to fallback below */ } if (!cancelled) window.location.href = "/login?registered=1"; })(); return () => { cancelled = true; }; }, [state.ok]); return (
{showCaptcha && captcha.provider === "turnstile" ? (