97 lines
3.5 KiB
TypeScript
97 lines
3.5 KiB
TypeScript
"use client";
|
|
|
|
import { Suspense, useState } from "react";
|
|
import Link from "next/link";
|
|
import Header from "@/components/Header";
|
|
import Footer from "@/components/Footer";
|
|
import { createClient } from "@/lib/supabase/client";
|
|
|
|
function ForgotInner() {
|
|
const supabase = createClient();
|
|
const [email, setEmail] = useState("");
|
|
const [busy, setBusy] = useState(false);
|
|
const [msg, setMsg] = useState<string | null>(null);
|
|
const [err, setErr] = useState<string | null>(null);
|
|
|
|
async function submit(e: React.FormEvent) {
|
|
e.preventDefault();
|
|
setBusy(true); setMsg(null); setErr(null);
|
|
const { error } = await supabase.auth.resetPasswordForEmail(email.trim(), {
|
|
redirectTo: `${window.location.origin}/forum/reset-password`,
|
|
});
|
|
setBusy(false);
|
|
if (error) {
|
|
setErr(error.message);
|
|
} else {
|
|
setMsg("Check your inbox — we sent a password reset link. If you didn't have an account, no email is sent.");
|
|
}
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<Header />
|
|
<main className="min-h-screen bg-gradient-to-b from-[#0d0d0d] via-[#111111] to-[#0d0d0d]">
|
|
<div className="max-w-md mx-auto px-4 py-16">
|
|
<div className="text-center mb-6">
|
|
<div className="text-[10px] uppercase tracking-widest text-[#ffb800] font-mono mb-2">Account recovery</div>
|
|
<h1 className="text-3xl font-heading font-bold text-white">Reset your password</h1>
|
|
<p className="text-[#888] font-body text-sm mt-2">
|
|
Enter your email — we’ll send a link to set a new password.
|
|
</p>
|
|
</div>
|
|
<form
|
|
onSubmit={submit}
|
|
className="bg-[#1a1a1a] border border-[#252525] rounded-lg p-6 space-y-4 shadow-2xl"
|
|
>
|
|
{err && (
|
|
<div className="bg-[#2a0a0a] border border-[#d60701] text-[#ff8a8a] font-body text-sm px-3 py-2 rounded">
|
|
{err}
|
|
</div>
|
|
)}
|
|
{msg && (
|
|
<div className="bg-[#0a1f2a] border border-[#1e6c8c] text-[#7adbff] font-body text-sm px-3 py-2 rounded">
|
|
{msg}
|
|
</div>
|
|
)}
|
|
<div>
|
|
<label className="block text-xs font-body uppercase tracking-wider text-[#888] mb-1.5">
|
|
Email
|
|
</label>
|
|
<input
|
|
type="email"
|
|
value={email}
|
|
onChange={(e) => setEmail(e.target.value)}
|
|
autoComplete="email"
|
|
required
|
|
className="w-full bg-[#0d0d0d] border border-[#2a2a2a] rounded-lg px-3 py-2 text-white font-body text-sm focus:outline-none focus:border-[#ffb800]"
|
|
/>
|
|
</div>
|
|
<button
|
|
type="submit"
|
|
disabled={busy || !email.trim()}
|
|
className="w-full bg-[#ffb800] hover:bg-[#d99700] disabled:opacity-50 text-white font-body font-semibold text-sm px-5 py-3 rounded-lg transition-colors"
|
|
>
|
|
{busy ? "Sending…" : "Send reset link"}
|
|
</button>
|
|
<div className="text-center text-xs font-body text-[#888] pt-2 border-t border-[#252525]">
|
|
Remembered it?{" "}
|
|
<Link href="/forum/login" className="text-[#ffb800] hover:underline font-semibold">
|
|
Back to sign in
|
|
</Link>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</main>
|
|
<Footer />
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default function ForgotPasswordPage() {
|
|
return (
|
|
<Suspense fallback={null}>
|
|
<ForgotInner />
|
|
</Suspense>
|
|
);
|
|
}
|