blob: 63b3af328ddf23215d61ad4b95f8f1702201e500 (
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("/mesh");
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("/mesh");
}
} 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>
);
}
|