70 lines
2.0 KiB
TypeScript
70 lines
2.0 KiB
TypeScript
"use client";
|
|
import { useState } from "react";
|
|
import { createBrowserClient } from "@supabase/ssr";
|
|
import { Mail } from "lucide-react";
|
|
export function SignIn() {
|
|
const [email, setEmail] = useState(""),
|
|
[message, setMessage] = useState(""),
|
|
[error, setError] = useState(""),
|
|
[busy, setBusy] = useState(false);
|
|
async function submit(event: React.FormEvent) {
|
|
event.preventDefault();
|
|
setBusy(true);
|
|
setError("");
|
|
try {
|
|
const client = createBrowserClient(
|
|
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!,
|
|
);
|
|
const { error } = await client.auth.signInWithOtp({
|
|
email,
|
|
options: { emailRedirectTo: window.location.origin + "/auth/callback" },
|
|
});
|
|
if (error) throw error;
|
|
setMessage(
|
|
"Check your inbox for a sign-in link. You can return here after opening it.",
|
|
);
|
|
} catch (e) {
|
|
setError((e as Error).message);
|
|
} finally {
|
|
setBusy(false);
|
|
}
|
|
}
|
|
return (
|
|
<div className="auth-card">
|
|
<span className="eyebrow">YOUR CARTOGRAPHER ACCOUNT</span>
|
|
<h2>Welcome, explorer.</h2>
|
|
<p className="muted">
|
|
Sign in to share maps and keep your expeditions. No password needed.
|
|
</p>
|
|
<form onSubmit={submit}>
|
|
<label className="field">
|
|
Email address
|
|
<input
|
|
type="email"
|
|
autoComplete="email"
|
|
value={email}
|
|
onChange={(e) => setEmail(e.target.value)}
|
|
placeholder="you@example.com"
|
|
required
|
|
/>
|
|
</label>
|
|
<button className="button primary full" disabled={busy}>
|
|
<Mail size={16} />
|
|
{busy ? "Sending…" : "Send me a sign-in link"}
|
|
</button>
|
|
</form>
|
|
{message && (
|
|
<p role="status" className="success-message">
|
|
{message}
|
|
</p>
|
|
)}
|
|
{error && (
|
|
<p role="alert" className="error-message">
|
|
{error}
|
|
</p>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|