"use client"; import { updatePasswordAction } from "@/app/(dashboard)/ajustes/actions"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { cn } from "@/lib/utils/ui"; import { RiEyeLine, RiEyeOffLine, RiCheckLine, RiCloseLine, RiAlertLine } from "@remixicon/react"; import { useState, useTransition, useMemo } from "react"; import { toast } from "sonner"; interface PasswordValidation { hasLowercase: boolean; hasUppercase: boolean; hasNumber: boolean; hasSpecial: boolean; hasMinLength: boolean; hasMaxLength: boolean; isValid: boolean; } function validatePassword(password: string): PasswordValidation { const hasLowercase = /[a-z]/.test(password); const hasUppercase = /[A-Z]/.test(password); const hasNumber = /\d/.test(password); const hasSpecial = /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?`~]/.test(password); const hasMinLength = password.length >= 7; const hasMaxLength = password.length <= 23; return { hasLowercase, hasUppercase, hasNumber, hasSpecial, hasMinLength, hasMaxLength, isValid: hasLowercase && hasUppercase && hasNumber && hasSpecial && hasMinLength && hasMaxLength, }; } function PasswordRequirement({ met, label, }: { met: boolean; label: string; }) { return (
{met ? ( ) : ( )} {label}
); } type UpdatePasswordFormProps = { authProvider?: string; // 'google' | 'credential' | undefined }; export function UpdatePasswordForm({ authProvider }: UpdatePasswordFormProps) { const [isPending, startTransition] = useTransition(); const [currentPassword, setCurrentPassword] = useState(""); const [newPassword, setNewPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); const [showCurrentPassword, setShowCurrentPassword] = useState(false); const [showNewPassword, setShowNewPassword] = useState(false); const [showConfirmPassword, setShowConfirmPassword] = useState(false); // Verificar se o usuário usa login via Google const isGoogleAuth = authProvider === "google"; // Validação em tempo real: senhas coincidem const passwordsMatch = useMemo(() => { if (!confirmPassword) return null; // Não mostrar erro se campo vazio return newPassword === confirmPassword; }, [newPassword, confirmPassword]); // Validação de requisitos da senha const passwordValidation = useMemo( () => validatePassword(newPassword), [newPassword] ); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); // Validação frontend antes de enviar if (!passwordValidation.isValid) { toast.error("A senha não atende aos requisitos de segurança"); return; } if (newPassword !== confirmPassword) { toast.error("As senhas não coincidem"); return; } startTransition(async () => { const result = await updatePasswordAction({ currentPassword, newPassword, confirmPassword, }); if (result.success) { toast.success(result.message); setCurrentPassword(""); setNewPassword(""); setConfirmPassword(""); } else { toast.error(result.error); } }); }; // Se o usuário usa Google OAuth, mostrar aviso if (isGoogleAuth) { return (

Alteração de senha não disponível

Você fez login usando sua conta do Google. A senha é gerenciada diretamente pelo Google e não pode ser alterada aqui. Para modificar sua senha, acesse as configurações de segurança da sua conta Google.

); } return (
{/* Senha atual */}
setCurrentPassword(e.target.value)} disabled={isPending} placeholder="Digite sua senha atual" required aria-required="true" aria-describedby="current-password-help" />

Por segurança, confirme sua senha atual antes de alterá-la

{/* Nova senha */}
setNewPassword(e.target.value)} disabled={isPending} placeholder="Crie uma senha forte" required minLength={7} maxLength={23} aria-required="true" aria-describedby="new-password-help" aria-invalid={newPassword.length > 0 && !passwordValidation.isValid} />
{/* Indicadores de requisitos da senha */} {newPassword.length > 0 && (
)}
{/* Confirmar nova senha */}
setConfirmPassword(e.target.value)} disabled={isPending} placeholder="Repita a senha" required minLength={6} aria-required="true" aria-describedby="confirm-password-help" aria-invalid={passwordsMatch === false} className={ passwordsMatch === false ? "border-red-500 focus-visible:ring-red-500" : passwordsMatch === true ? "border-green-500 focus-visible:ring-green-500" : "" } /> {/* Indicador visual de match */} {passwordsMatch !== null && (
{passwordsMatch ? ( ) : ( )}
)}
{/* Mensagem de erro em tempo real */} {passwordsMatch === false && ( )} {passwordsMatch === true && (

As senhas coincidem

)}
); }