import React, { useEffect, useState } from "react"; import Layout from "@/components/Layout"; import { Card, CardContent, CardHeader, CardTitle, CardDescription, } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; import LoadingScreen from "@/components/LoadingScreen"; import { useAuth } from "@/contexts/AuthContext"; import { useNavigate } from "react-router-dom"; import { useAethexToast } from "@/hooks/use-aethex-toast"; import { supabase } from "@/lib/supabase"; export default function ResetPassword() { const [password, setPassword] = useState(""); const [confirm, setConfirm] = useState(""); const [isLoading, setIsLoading] = useState(true); const [submitting, setSubmitting] = useState(false); const [linkError, setLinkError] = useState(null); const [resetEmail, setResetEmail] = useState(""); const navigate = useNavigate(); const { updatePassword, requestPasswordReset } = useAuth(); const { error: toastError, success: toastSuccess, info: toastInfo, } = useAethexToast(); useEffect(() => { let mounted = true; (async () => { try { const hash = typeof window !== "undefined" ? window.location.hash.replace(/^#/, "") : ""; const params = new URLSearchParams(hash); const urlError = params.get("error"); const urlErrorDesc = params.get("error_description"); if (urlError) { setLinkError(urlErrorDesc || "Reset link is invalid or has expired."); return; } const access_token = params.get("access_token"); const refresh_token = params.get("refresh_token"); if (access_token && refresh_token) { const { error: setErr } = await supabase.auth.setSession({ access_token, refresh_token, }); if (setErr) { setLinkError("Reset link is invalid or has expired."); return; } } else { try { await supabase.auth.exchangeCodeForSession(window.location.href); } catch (e: any) { setLinkError("Reset link is invalid or has expired."); return; } } const { data } = await supabase.auth.getSession(); if (!data?.session) { setLinkError("Reset link is invalid or has expired."); return; } } finally { if (mounted) setIsLoading(false); } })(); return () => { mounted = false; }; }, []); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!password || password.length < 6) { toastError({ title: "Invalid password", description: "Minimum 6 characters.", }); return; } if (password !== confirm) { toastError({ title: "Passwords do not match", description: "Please re-enter matching passwords.", }); return; } setSubmitting(true); try { await updatePassword(password); toastSuccess({ title: "Password updated", description: "Please sign in with your new password.", }); navigate("/login", { replace: true }); } catch (err: any) { // Error already toasted in context; keep here for safety toastError({ title: "Update failed", description: err?.message || "Try again.", }); } finally { setSubmitting(false); } }; if (isLoading) { return ( ); } return (
{linkError ? ( Reset link expired {linkError || "The link is invalid or has expired. Request a new reset link."}
setResetEmail(e.target.value)} placeholder="you@example.com" />
) : ( Set a new password Enter and confirm your new password
setPassword(e.target.value)} placeholder="Enter a new password" minLength={6} required />
setConfirm(e.target.value)} placeholder="Re-enter your new password" minLength={6} required />
)}
); }