"use client"; import { useAtom } from "jotai"; import { Eye, EyeOff } from "lucide-react"; import { AnimatePresence, motion } from "motion/react"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { useTranslations } from "next-intl"; import { useEffect, useState } from "react"; import { loginMutationAtom } from "@/atoms/auth/auth-mutation.atoms"; import { Spinner } from "@/components/ui/spinner"; import { getAuthErrorDetails, isNetworkError } from "@/lib/auth-errors"; import { AUTH_TYPE } from "@/lib/env-config"; import { ValidationError } from "@/lib/error"; import { trackLoginAttempt, trackLoginFailure, trackLoginSuccess } from "@/lib/posthog/events"; export function LocalLoginForm() { const t = useTranslations("auth"); const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const [showPassword, setShowPassword] = useState(false); const [error, setError] = useState<{ title: string | null; message: string | null; }>({ title: null, message: null, }); const [authType, setAuthType] = useState(null); const router = useRouter(); const [{ mutateAsync: login, isPending: isLoggingIn }] = useAtom(loginMutationAtom); useEffect(() => { // Get the auth type from centralized config setAuthType(AUTH_TYPE); }, []); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError({ title: null, message: null }); // Clear any previous errors // Track login attempt trackLoginAttempt("local"); try { const data = await login({ username, password, grant_type: "password", }); // Track successful login trackLoginSuccess("local"); // Set flag so TokenHandler knows local login was already tracked if (typeof window !== "undefined") { sessionStorage.setItem("login_success_tracked", "true"); } // Small delay to show success message setTimeout(() => { router.push(`/auth/callback?token=${data.access_token}`); }, 500); } catch (err) { if (err instanceof ValidationError) { trackLoginFailure("local", err.message); setError({ title: err.name, message: err.message }); return; } // Use auth-errors utility to get proper error details let errorCode = "UNKNOWN_ERROR"; if (err instanceof Error) { errorCode = err.message; } else if (isNetworkError(err)) { errorCode = "NETWORK_ERROR"; } // Track login failure trackLoginFailure("local", errorCode); // Get detailed error information from auth-errors utility const errorDetails = getAuthErrorDetails(errorCode); // Set persistent error display setError({ title: errorDetails.title, message: errorDetails.description, }); } }; return (
{/* Error Display */} {error?.title && (
Error Icon

{error.title}

{error.message}

)}
setUsername(e.target.value)} className={`mt-1 block w-full rounded-md border px-3 py-1.5 md:py-2 shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 dark:bg-gray-800 dark:text-white transition-all ${ error.title ? "border-red-300 focus:border-red-500 focus:ring-red-500 dark:border-red-700" : "border-gray-300 focus:border-blue-500 focus:ring-blue-500 dark:border-gray-700" }`} disabled={isLoggingIn} />
setPassword(e.target.value)} className={`mt-1 block w-full rounded-md border pr-10 px-3 py-1.5 md:py-2 shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 dark:bg-gray-800 dark:text-white transition-all ${ error.title ? "border-red-300 focus:border-red-500 focus:ring-red-500 dark:border-red-700" : "border-gray-300 focus:border-blue-500 focus:ring-blue-500 dark:border-gray-700" }`} disabled={isLoggingIn} />
{authType === "LOCAL" && (

{t("dont_have_account")}{" "} {t("sign_up")}

)}
); }