import React, { useState, useEffect } from "react"; import { Lock, Eye, EyeOff, CheckCircle } from "lucide-react"; import toast from "react-hot-toast"; import { useNavigate } from "react-router-dom"; import { authService } from "../services"; const ResetPassword: React.FC = () => { const [password, setPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); const [showPassword, setShowPassword] = useState(false); const [showConfirmPassword, setShowConfirmPassword] = useState(false); const [loading, setLoading] = useState(false); const [accessToken, setAccessToken] = useState(null); const navigate = useNavigate(); useEffect(() => { // Extrair access_token do hash da URL (#access_token=...) // OU do query string (?token=...&type=recovery) let token: string | null = null; let type: string | null = null; // Primeiro tenta no hash (formato padrão do Supabase após redirect) const hash = window.location.hash; console.log("[ResetPassword] Hash completo:", hash); if (hash) { const hashParams = new URLSearchParams(hash.substring(1)); token = hashParams.get("access_token"); type = hashParams.get("type"); console.log("[ResetPassword] Token do hash:", token ? token.substring(0, 20) + "..." : "null"); console.log("[ResetPassword] Type do hash:", type); } // Se não encontrou no hash, tenta no query string if (!token) { const search = window.location.search; console.log("[ResetPassword] Query string completo:", search); if (search) { const queryParams = new URLSearchParams(search); token = queryParams.get("token"); type = queryParams.get("type"); console.log("[ResetPassword] Token do query:", token ? token.substring(0, 20) + "..." : "null"); console.log("[ResetPassword] Type do query:", type); } } if (token) { setAccessToken(token); console.log("[ResetPassword] ✅ Token de recuperação detectado e armazenado"); console.log("[ResetPassword] Type:", type); } else { console.error("[ResetPassword] ❌ Token não encontrado no hash nem no query string"); console.log("[ResetPassword] URL completa:", window.location.href); toast.error("Link de recuperação inválido ou expirado"); setTimeout(() => navigate("/"), 3000); } }, [navigate]); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); // Validações if (!password.trim()) { toast.error("Digite a nova senha"); return; } if (password.length < 6) { toast.error("A senha deve ter pelo menos 6 caracteres"); return; } if (password !== confirmPassword) { toast.error("As senhas não coincidem"); return; } if (!accessToken) { toast.error("Token de recuperação não encontrado"); return; } setLoading(true); try { console.log("[ResetPassword] Atualizando senha..."); // Atualizar senha usando o token de recuperação await authService.updatePassword(accessToken, password); console.log("[ResetPassword] Senha atualizada com sucesso!"); toast.success("Senha atualizada com sucesso!"); // Limpar formulário setPassword(""); setConfirmPassword(""); // Redirecionar para login após 2 segundos setTimeout(() => { navigate("/"); }, 2000); } catch (error: unknown) { console.error("[ResetPassword] Erro ao atualizar senha:", error); const err = error as { response?: { data?: { error_description?: string; message?: string; msg?: string; error_code?: string; } }; message?: string; }; // Mensagem específica para senha igual if (err?.response?.data?.error_code === "same_password") { toast.error("A nova senha deve ser diferente da senha atual"); setLoading(false); return; } const errorMessage = err?.response?.data?.msg || err?.response?.data?.error_description || err?.response?.data?.message || err?.message || "Erro ao atualizar senha. Tente novamente."; toast.error(errorMessage); } finally { setLoading(false); } }; // Validações em tempo real const hasMinLength = password.length >= 6; const passwordsMatch = password === confirmPassword && confirmPassword !== ""; // Se não tiver token ainda, mostrar loading if (!accessToken) { return (

Verificando link de recuperação...

); } return (
{/* Header */}

Redefinir Senha

Digite sua nova senha abaixo

{/* Formulário */}
{/* Nova Senha */}
setPassword(e.target.value)} className="w-full pl-10 pr-12 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-gray-100" placeholder="Digite sua nova senha" required />
{/* Confirmar Senha */}
setConfirmPassword(e.target.value)} className="w-full pl-10 pr-12 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-gray-100" placeholder="Confirme sua nova senha" required />
{/* Indicadores de Validação */} {password && (
Mínimo de 6 caracteres
{confirmPassword && (
{passwordsMatch ? "As senhas coincidem" : "As senhas não coincidem"}
)}
)} {/* Botão Submit */}
{/* Link para voltar */}
); }; export default ResetPassword;