import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { getErrorMessage, useIsAuthEnabledQuery, useLoginMutation } from "@/lib/store/apis"; import { BooksIcon, DiscordLogoIcon, GithubLogoIcon } from "@phosphor-icons/react"; import { useNavigate } from "@tanstack/react-router"; import { Eye, EyeOff } from "lucide-react"; import { useTheme } from "next-themes"; import { useEffect, useState } from "react"; const externalLinks = [ { title: "Discord Server", url: "https://discord.gg/exN5KAydbU", icon: DiscordLogoIcon, }, { title: "GitHub Repository", url: "https://github.com/maximhq/bifrost", icon: GithubLogoIcon, }, { title: "Full Documentation", url: "https://docs.getbifrost.ai", icon: BooksIcon, strokeWidth: 1, }, ]; export default function LoginView() { const { resolvedTheme } = useTheme(); const [mounted, setMounted] = useState(false); const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const [showPassword, setShowPassword] = useState(false); const [errorMessage, setErrorMessage] = useState(""); const [isCheckingAuth, setIsCheckingAuth] = useState(true); const navigate = useNavigate(); const [isLoading, setIsLoading] = useState(false); const { data: isAuthEnabledData, isLoading: isLoadingIsAuthEnabled, error: isAuthEnabledError } = useIsAuthEnabledQuery(); const isAuthEnabled = isAuthEnabledData?.is_auth_enabled || false; const hasValidToken = isAuthEnabledData?.has_valid_token || false; const [login, { isLoading: isLoggingIn }] = useLoginMutation(); useEffect(() => { setMounted(true); }, []); // Check auth status on component mount useEffect(() => { if (isLoadingIsAuthEnabled) { return; } if (isAuthEnabledError) { setErrorMessage("Unable to verify authentication status. Please retry."); return; } if (!isAuthEnabled || hasValidToken) { navigate({ to: "/workspace" }); return; } // Auth is enabled but user is not logged in, show login form setIsCheckingAuth(false); }, [isLoadingIsAuthEnabled]); const handleSubmit = async (e: React.FormEvent) => { setIsLoading(true); e.preventDefault(); setErrorMessage(""); try { await login({ username, password }).unwrap(); // Cookie is set automatically by the server response — just navigate navigate({ to: "/workspace" }); } catch (error) { const message = getErrorMessage(error); setErrorMessage(message); } finally { setIsLoading(false); } }; // Use light logo for SSR to avoid hydration mismatch const logoSrc = mounted && resolvedTheme === "dark" ? "/bifrost-logo-dark.webp" : "/bifrost-logo.webp"; // Show loading state while checking auth if (isCheckingAuth || isLoadingIsAuthEnabled) { return (
Bifrost
Checking authentication...
); } return (
{/* Logo */}
Bifrost

Welcome back

Sign in to your account to continue

{errorMessage &&
{errorMessage}
}
setUsername(e.target.value)} required className="text-sm" autoComplete="username" />
setPassword(e.target.value)} required className="pr-10 text-sm" autoComplete="current-password" />
{/* Social Links */}
{externalLinks.map((item, index) => ( ))}
); }