summaryrefslogblamecommitdiff
path: root/makima/frontend/src/routes/login.tsx
blob: 0725a2d921c3c38fb0f3fc82a4e3d4a164c722c0 (plain) (tree)



















                                                                          
                      














                                                        
                            
















































































































                                                                                                                                                              
import { useState, type FormEvent } from "react";
import { useNavigate } from "react-router";
import { useAuth } from "../contexts/AuthContext";
import { Masthead } from "../components/Masthead";

type AuthMode = "signin" | "signup";

export default function LoginPage() {
  const navigate = useNavigate();
  const { signIn, signUp, isAuthConfigured, isAuthenticated } = useAuth();

  const [mode, setMode] = useState<AuthMode>("signin");
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);
  const [message, setMessage] = useState<string | null>(null);

  // Redirect if already authenticated
  if (isAuthenticated && isAuthConfigured) {
    navigate("/exec");
    return null;
  }

  const handleEmailAuth = async (e: FormEvent) => {
    e.preventDefault();
    setError(null);
    setMessage(null);
    setLoading(true);

    try {
      if (mode === "signin") {
        const { error } = await signIn(email, password);
        if (error) {
          setError(error.message);
        } else {
          navigate("/exec");
        }
      } else if (mode === "signup") {
        const { error } = await signUp(email, password);
        if (error) {
          setError(error.message);
        } else {
          setMessage("Check your email for a confirmation link.");
        }
      }
    } finally {
      setLoading(false);
    }
  };

  // If auth is not configured, show a message
  if (!isAuthConfigured) {
    return (
      <div className="relative z-10 min-h-screen flex flex-col">
        <Masthead />
        <main className="flex-1 flex items-center justify-center p-4">
          <div className="w-full max-w-md text-center">
            <h1 className="text-2xl font-bold mb-4">Authentication Required</h1>
            <p className="text-zinc-400 mb-4">
              Authentication is not configured. Please configure Supabase authentication to use this application.
            </p>
            <p className="text-zinc-500 text-sm">
              For API access, use an API key in request headers instead.
            </p>
          </div>
        </main>
      </div>
    );
  }

  return (
    <div className="relative z-10 min-h-screen flex flex-col">
      <Masthead />
      <main className="flex-1 flex items-center justify-center p-4">
        <div className="w-full max-w-md">
          <div className="text-center mb-8">
            <h1 className="text-2xl font-bold mb-2">Sign In</h1>
            <p className="text-zinc-400">
              {mode === "signin" && "Sign in to your account"}
              {mode === "signup" && "Create a new account"}
            </p>
          </div>

        {/* Mode switcher */}
        <div className="flex border-b border-zinc-800 mb-6">
          <button
            onClick={() => setMode("signin")}
            className={`flex-1 py-2 text-sm transition-colors ${
              mode === "signin"
                ? "text-white border-b-2 border-white"
                : "text-zinc-500 hover:text-zinc-300"
            }`}
          >
            Sign In
          </button>
          <button
            onClick={() => setMode("signup")}
            className={`flex-1 py-2 text-sm transition-colors ${
              mode === "signup"
                ? "text-white border-b-2 border-white"
                : "text-zinc-500 hover:text-zinc-300"
            }`}
          >
            Sign Up
          </button>
        </div>

        {/* Email/password form */}
        <form onSubmit={handleEmailAuth} className="space-y-4">
          <div>
            <label className="block text-sm text-zinc-400 mb-1">Email</label>
            <input
              type="email"
              value={email}
              onChange={(e) => setEmail(e.target.value)}
              placeholder="you@example.com"
              className="w-full px-3 py-2 bg-zinc-900 border border-zinc-800 rounded text-white placeholder-zinc-600 focus:outline-none focus:border-zinc-600"
              required
            />
          </div>
          <div>
            <label className="block text-sm text-zinc-400 mb-1">Password</label>
            <input
              type="password"
              value={password}
              onChange={(e) => setPassword(e.target.value)}
              placeholder="********"
              className="w-full px-3 py-2 bg-zinc-900 border border-zinc-800 rounded text-white placeholder-zinc-600 focus:outline-none focus:border-zinc-600"
              required
              minLength={6}
            />
          </div>

          {error && <div className="text-red-400 text-sm">{error}</div>}
          {message && <div className="text-green-400 text-sm">{message}</div>}

          <button
            type="submit"
            disabled={loading}
            className="w-full py-2 bg-white text-black rounded font-medium hover:bg-zinc-200 transition-colors disabled:opacity-50"
          >
            {loading ? "Loading..." : mode === "signin" ? "Sign In" : "Sign Up"}
          </button>
        </form>
        </div>
      </main>
    </div>
  );
}