email de mudar senha
This commit is contained in:
54
src/App.jsx
54
src/App.jsx
@@ -12,7 +12,7 @@ import {
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
signInWithEmailAndPassword, createUserWithEmailAndPassword,
|
signInWithEmailAndPassword, createUserWithEmailAndPassword,
|
||||||
onAuthStateChanged, signOut, signInWithCustomToken
|
onAuthStateChanged, signOut, signInWithCustomToken, sendPasswordResetEmail
|
||||||
} from 'firebase/auth';
|
} from 'firebase/auth';
|
||||||
import {
|
import {
|
||||||
collection, doc, onSnapshot, addDoc, updateDoc,
|
collection, doc, onSnapshot, addDoc, updateDoc,
|
||||||
@@ -39,6 +39,8 @@ export default function App() {
|
|||||||
const [sidebarOpen, setSidebarOpen] = useState(true);
|
const [sidebarOpen, setSidebarOpen] = useState(true);
|
||||||
const [authMode, setAuthMode] = useState('login');
|
const [authMode, setAuthMode] = useState('login');
|
||||||
const [authError, setAuthError] = useState('');
|
const [authError, setAuthError] = useState('');
|
||||||
|
const [showForgotPasswordModal, setShowForgotPasswordModal] = useState(false);
|
||||||
|
const [forgotPasswordEmail, setForgotPasswordEmail] = useState('');
|
||||||
const [categoryFilter, setCategoryFilter] = useState('Todos');
|
const [categoryFilter, setCategoryFilter] = useState('Todos');
|
||||||
const [colorFilter, setColorFilter] = useState('');
|
const [colorFilter, setColorFilter] = useState('');
|
||||||
const [ageFilter, setAgeFilter] = useState('any');
|
const [ageFilter, setAgeFilter] = useState('any');
|
||||||
@@ -723,6 +725,30 @@ export default function App() {
|
|||||||
} finally { setLoading(false); }
|
} finally { setLoading(false); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleForgotPassword = () => {
|
||||||
|
setAuthError('');
|
||||||
|
setShowForgotPasswordModal(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleForgotPasswordSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const email = forgotPasswordEmail;
|
||||||
|
if (!email) return;
|
||||||
|
setLoading(true);
|
||||||
|
setAuthError('');
|
||||||
|
try {
|
||||||
|
await sendPasswordResetEmail(auth, email);
|
||||||
|
setShowForgotPasswordModal(false);
|
||||||
|
setForgotPasswordEmail('');
|
||||||
|
setToastMessage(t('passwordResetSent') || "E-mail de recuperação enviado! Verifique a sua caixa de entrada.");
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
setAuthError(err.message);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const emptyTrashPermanently = async () => {
|
const emptyTrashPermanently = async () => {
|
||||||
@@ -888,6 +914,13 @@ export default function App() {
|
|||||||
<form onSubmit={handleAuth} className="space-y-4">
|
<form onSubmit={handleAuth} className="space-y-4">
|
||||||
<input name="email" type="email" placeholder={t('emailPlaceholder')} required className="w-full p-5 rounded-2xl bg-gray-50 dark:bg-gray-800 border-none focus:ring-2 focus:ring-primary-500 outline-none font-bold" />
|
<input name="email" type="email" placeholder={t('emailPlaceholder')} required className="w-full p-5 rounded-2xl bg-gray-50 dark:bg-gray-800 border-none focus:ring-2 focus:ring-primary-500 outline-none font-bold" />
|
||||||
<input name="password" type="password" placeholder={t('passwordPlaceholder')} required className="w-full p-5 rounded-2xl bg-gray-50 dark:bg-gray-800 border-none focus:ring-2 focus:ring-primary-500 outline-none font-bold" />
|
<input name="password" type="password" placeholder={t('passwordPlaceholder')} required className="w-full p-5 rounded-2xl bg-gray-50 dark:bg-gray-800 border-none focus:ring-2 focus:ring-primary-500 outline-none font-bold" />
|
||||||
|
{authMode === 'login' && (
|
||||||
|
<div className="text-right">
|
||||||
|
<button type="button" onClick={handleForgotPassword} className="text-[10px] font-black text-primary-500 hover:text-primary-600 uppercase tracking-widest transition-colors">
|
||||||
|
{t('forgotPassword') || 'Esqueceu-se da palavra-passe?'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<button className="w-full py-5 bg-primary-600 text-white rounded-[2rem] font-black text-lg shadow-2xl hover:scale-[1.02] active:scale-95 transition-all">
|
<button className="w-full py-5 bg-primary-600 text-white rounded-[2rem] font-black text-lg shadow-2xl hover:scale-[1.02] active:scale-95 transition-all">
|
||||||
{authMode === 'login' ? t('loginBtn') : t('registerBtn')}
|
{authMode === 'login' ? t('loginBtn') : t('registerBtn')}
|
||||||
</button>
|
</button>
|
||||||
@@ -900,6 +933,25 @@ export default function App() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
{/* Modal de Forgot Password */}
|
||||||
|
{showForgotPasswordModal && (
|
||||||
|
<div className="fixed inset-0 z-[200] flex items-center justify-center bg-black/60 backdrop-blur-sm p-6" onClick={() => setShowForgotPasswordModal(false)}>
|
||||||
|
<Card className="w-full max-w-md p-8 animate-in zoom-in-95" darkMode={darkMode} onClick={e => e.stopPropagation()}>
|
||||||
|
<h3 className="text-2xl font-black mb-4 text-center text-inherit">{t('forgotPassword')}</h3>
|
||||||
|
<p className="text-center opacity-70 mb-8 text-sm text-inherit">{t('forgotPasswordPrompt')}</p>
|
||||||
|
<form onSubmit={handleForgotPasswordSubmit} className="space-y-4">
|
||||||
|
<input name="resetEmail" type="email" placeholder={t('emailPlaceholder')} required value={forgotPasswordEmail} onChange={e => setForgotPasswordEmail(e.target.value)} className="w-full p-5 rounded-2xl bg-gray-50 dark:bg-gray-800 border-none focus:ring-2 focus:ring-primary-500 outline-none font-bold text-inherit" />
|
||||||
|
<button type="submit" disabled={loading} className="w-full py-5 bg-primary-600 text-white rounded-[2rem] font-black text-lg shadow-2xl hover:scale-[1.02] active:scale-95 transition-all disabled:opacity-50">
|
||||||
|
{loading ? t('saving') : t('sendEmailBtn')}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<button type="button" onClick={() => setShowForgotPasswordModal(false)} className="w-full mt-6 py-4 uppercase font-black text-[10px] tracking-widest text-gray-500 hover:text-gray-900 dark:hover:text-white transition-colors">
|
||||||
|
{t('cancel')}
|
||||||
|
</button>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,13 @@ export const translations = {
|
|||||||
passwordPlaceholder: "Palavra-passe",
|
passwordPlaceholder: "Palavra-passe",
|
||||||
loginBtn: "ENTRAR",
|
loginBtn: "ENTRAR",
|
||||||
registerBtn: "REGISTAR",
|
registerBtn: "REGISTAR",
|
||||||
createAccount: "Criar Nova Conta",
|
createAccount: "Criar Conta",
|
||||||
haveAccount: "Já Tenho Conta",
|
haveAccount: "Já tenho conta",
|
||||||
authErrorDisabled: "O login por e-mail está desativado.",
|
authErrorDisabled: "Este método de login está desativado na base de dados.",
|
||||||
|
forgotPassword: "Esqueceu-se da palavra-passe?",
|
||||||
|
forgotPasswordPrompt: "Introduza o seu e-mail para recuperar a palavra-passe:",
|
||||||
|
passwordResetSent: "E-mail de recuperação enviado! Verifique a sua caixa de entrada.",
|
||||||
|
sendEmailBtn: "Enviar Email",
|
||||||
dashboard: "Painel",
|
dashboard: "Painel",
|
||||||
closet: "Armário",
|
closet: "Armário",
|
||||||
laundry: "Lavandaria",
|
laundry: "Lavandaria",
|
||||||
@@ -195,9 +199,13 @@ export const translations = {
|
|||||||
passwordPlaceholder: "Password",
|
passwordPlaceholder: "Password",
|
||||||
loginBtn: "LOGIN",
|
loginBtn: "LOGIN",
|
||||||
registerBtn: "REGISTER",
|
registerBtn: "REGISTER",
|
||||||
createAccount: "Create New Account",
|
createAccount: "Create Account",
|
||||||
haveAccount: "I Already Have an Account",
|
haveAccount: "I already have an account",
|
||||||
authErrorDisabled: "Email login is disabled.",
|
authErrorDisabled: "This login method is disabled in the database.",
|
||||||
|
forgotPassword: "Forgot password?",
|
||||||
|
forgotPasswordPrompt: "Enter your email to reset your password:",
|
||||||
|
passwordResetSent: "Password reset email sent! Check your inbox.",
|
||||||
|
sendEmailBtn: "Send Email",
|
||||||
dashboard: "Dashboard",
|
dashboard: "Dashboard",
|
||||||
closet: "Closet",
|
closet: "Closet",
|
||||||
laundry: "Laundry",
|
laundry: "Laundry",
|
||||||
@@ -385,9 +393,13 @@ export const translations = {
|
|||||||
passwordPlaceholder: "Contraseña",
|
passwordPlaceholder: "Contraseña",
|
||||||
loginBtn: "ENTRAR",
|
loginBtn: "ENTRAR",
|
||||||
registerBtn: "REGISTRAR",
|
registerBtn: "REGISTRAR",
|
||||||
createAccount: "Crear Nueva Cuenta",
|
createAccount: "Crear Cuenta",
|
||||||
haveAccount: "Ya Tengo Cuenta",
|
haveAccount: "Ya tengo cuenta",
|
||||||
authErrorDisabled: "El inicio de sesión por correo electrónico está desactivado.",
|
authErrorDisabled: "Este método de inicio de sesión está desactivado en la base de datos.",
|
||||||
|
forgotPassword: "¿Olvidaste tu contraseña?",
|
||||||
|
forgotPasswordPrompt: "Introduce tu correo electrónico para recuperar la contraseña:",
|
||||||
|
passwordResetSent: "¡Correo de recuperación enviado! Revisa tu bandeja de entrada.",
|
||||||
|
sendEmailBtn: "Enviar Correo",
|
||||||
dashboard: "Panel",
|
dashboard: "Panel",
|
||||||
closet: "Armario",
|
closet: "Armario",
|
||||||
laundry: "Lavandería",
|
laundry: "Lavandería",
|
||||||
@@ -575,9 +587,13 @@ export const translations = {
|
|||||||
passwordPlaceholder: "Mot de passe",
|
passwordPlaceholder: "Mot de passe",
|
||||||
loginBtn: "CONNEXION",
|
loginBtn: "CONNEXION",
|
||||||
registerBtn: "S'INSCRIRE",
|
registerBtn: "S'INSCRIRE",
|
||||||
createAccount: "Créer un Nouveau Compte",
|
createAccount: "Créer un Compte",
|
||||||
haveAccount: "J'ai Déjà un Compte",
|
haveAccount: "J'ai déjà un compte",
|
||||||
authErrorDisabled: "La connexion par e-mail est désactivée.",
|
authErrorDisabled: "Cette méthode de connexion est désactivée dans la base de données.",
|
||||||
|
forgotPassword: "Mot de passe oublié ?",
|
||||||
|
forgotPasswordPrompt: "Entrez votre e-mail pour réinitialiser votre mot de passe :",
|
||||||
|
passwordResetSent: "E-mail de réinitialisation envoyé ! Vérifiez votre boîte de réception.",
|
||||||
|
sendEmailBtn: "Envoyer l'E-mail",
|
||||||
dashboard: "Tableau de bord",
|
dashboard: "Tableau de bord",
|
||||||
closet: "Placard",
|
closet: "Placard",
|
||||||
laundry: "Blanchisserie",
|
laundry: "Blanchisserie",
|
||||||
@@ -765,9 +781,13 @@ export const translations = {
|
|||||||
passwordPlaceholder: "Passwort",
|
passwordPlaceholder: "Passwort",
|
||||||
loginBtn: "ANMELDEN",
|
loginBtn: "ANMELDEN",
|
||||||
registerBtn: "REGISTRIEREN",
|
registerBtn: "REGISTRIEREN",
|
||||||
createAccount: "Neues Konto erstellen",
|
createAccount: "Konto Erstellen",
|
||||||
haveAccount: "Ich habe bereits ein Konto",
|
haveAccount: "Ich habe bereits ein Konto",
|
||||||
authErrorDisabled: "E-Mail-Anmeldung ist deaktiviert.",
|
authErrorDisabled: "Diese Anmeldemethode ist in der Datenbank deaktiviert.",
|
||||||
|
forgotPassword: "Passwort vergessen?",
|
||||||
|
forgotPasswordPrompt: "Gib deine E-Mail-Adresse ein, um dein Passwort zurückzusetzen:",
|
||||||
|
passwordResetSent: "E-mail zum Zurücksetzen des Passworts gesendet! Überprüfe deinen Posteingang.",
|
||||||
|
sendEmailBtn: "E-Mail Senden",
|
||||||
dashboard: "Startseite",
|
dashboard: "Startseite",
|
||||||
closet: "Schrank",
|
closet: "Schrank",
|
||||||
laundry: "Wäsche",
|
laundry: "Wäsche",
|
||||||
|
|||||||
Reference in New Issue
Block a user