diff --git a/client/pages/ResetPassword.tsx b/client/pages/ResetPassword.tsx new file mode 100644 index 00000000..4061a64e --- /dev/null +++ b/client/pages/ResetPassword.tsx @@ -0,0 +1,114 @@ +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 navigate = useNavigate(); + const { updatePassword } = useAuth(); + const { error: toastError, success: toastSuccess } = useAethexToast(); + + useEffect(() => { + let mounted = true; + (async () => { + try { + // Ensure recovery session is established from URL parameters + try { + await supabase.auth.exchangeCodeForSession(window.location.href); + } catch {} + await supabase.auth.getSession(); + } 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 ( + + + + + + Set a new password + Enter and confirm your new password + + + + + New Password + setPassword(e.target.value)} + placeholder="Enter a new password" + minLength={6} + required + /> + + + Confirm Password + setConfirm(e.target.value)} + placeholder="Re-enter your new password" + minLength={6} + required + /> + + + {submitting ? "Updating..." : "Update Password"} + + + + + + + + ); +}