pequenas mudanças no perfil e no suporte

This commit is contained in:
Jessica_Faro 2025-11-20 11:27:31 -03:00
parent 6ccb0992c3
commit 5d1751b7f9
2 changed files with 127 additions and 42 deletions

View File

@ -487,4 +487,15 @@
width: calc(100vw - 20px);
max-width: none;
}
}
}
/* permite que cliques "passem" através do header (exceto para os elementos interativos) */
.header-container {
pointer-events: none; /* header não captura cliques */
}
/* mas permite que os controles no canto (telefone e profile) continuem clicáveis */
.phone-icon-container,
.profile-section {
pointer-events: auto;
}

View File

@ -1,8 +1,11 @@
// src/components/Header/Header.jsx
import React, { useState, useRef, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { createPortal } from 'react-dom';
import { useNavigate, useLocation } from 'react-router-dom';
import './Header.css';
const Header = () => {
// --- Hooks (sempre chamados na mesma ordem) ---
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const [isSuporteCardOpen, setIsSuporteCardOpen] = useState(false);
const [isChatOpen, setIsChatOpen] = useState(false);
@ -11,9 +14,11 @@ const Header = () => {
const [showLogoutModal, setShowLogoutModal] = useState(false);
const [avatarUrl, setAvatarUrl] = useState(null);
const navigate = useNavigate();
const location = useLocation();
const chatInputRef = useRef(null);
const mensagensContainerRef = useRef(null);
// --- Efeitos ---
useEffect(() => {
const loadAvatar = () => {
const localAvatar = localStorage.getItem('user_avatar');
@ -44,7 +49,18 @@ const Header = () => {
}
}, [mensagens]);
// --- Logout ---
// Fecha modal com ESC (útil para logout)
useEffect(() => {
const onKey = (e) => {
if (e.key === 'Escape' && showLogoutModal) {
setShowLogoutModal(false);
}
};
window.addEventListener('keydown', onKey);
return () => window.removeEventListener('keydown', onKey);
}, [showLogoutModal]);
// --- Lógica e handlers ---
const handleLogoutClick = () => {
setShowLogoutModal(true);
setIsDropdownOpen(false);
@ -65,26 +81,21 @@ const Header = () => {
sessionStorage.getItem("authToken");
if (token) {
const response = await fetch(
"https://mock.apidog.com/m1/1053378-0-default/auth/v1/logout",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
}
);
if (response.status === 204) console.log("Logout realizado com sucesso");
else if (response.status === 401) console.log("Token inválido ou expirado");
else {
try {
const errorData = await response.json();
console.error("Erro no logout:", errorData);
} catch {
console.error("Erro no logout - status:", response.status);
}
// tentativa de logout no backend (se houver)
try {
await fetch(
"https://mock.apidog.com/m1/1053378-0-default/auth/v1/logout",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
}
);
} catch (err) {
// não interrompe o fluxo se a API falhar prosseguimos para limpar local
console.warn('Erro ao chamar endpoint de logout (ignorado):', err);
}
}
@ -105,12 +116,13 @@ const Header = () => {
sessionStorage.removeItem(key);
});
// tenta limpar caches relacionados se existirem
if (window.caches) {
caches.keys().then(names => {
names.forEach(name => {
if (name.includes("auth") || name.includes("api")) caches.delete(name);
});
});
}).catch(()=>{ /* ignore */ });
}
};
@ -157,7 +169,6 @@ const Header = () => {
e.preventDefault();
if (mensagem.trim() === '') return;
// Mensagem do usuário
const novaMensagemUsuario = {
id: Date.now(),
texto: mensagem,
@ -177,7 +188,6 @@ const Header = () => {
const data = await response.json();
// Resposta da IA
const respostaSuporte = {
id: Date.now() + 1,
texto: data.resposta || data.reply || "Desculpe, não consegui processar sua pergunta no momento 😅",
@ -198,6 +208,7 @@ const Header = () => {
}
};
// --- Subcomponentes ---
const SuporteCard = () => (
<div className="suporte-card">
<h2 className="suporte-titulo">Suporte</h2>
@ -257,6 +268,82 @@ const Header = () => {
</div>
);
// --- Modal de logout renderizado via Portal (garante top-most e clique) ---
const LogoutModalPortal = ({ onCancel, onConfirm }) => {
const modalContent = (
<div
className="logout-modal-overlay"
// inline style reforçando z-index e pointer events caso algum CSS global esteja atrapalhando
style={{
position: 'fixed',
top: 0, left: 0, right: 0, bottom: 0,
backgroundColor: 'rgba(0,0,0,0.5)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
zIndex: 99999,
padding: '1rem'
}}
role="dialog"
aria-modal="true"
>
<div
className="logout-modal-content"
style={{
backgroundColor: 'white',
padding: '1.6rem',
borderRadius: '12px',
boxShadow: '0 8px 24px rgba(0,0,0,0.2)',
maxWidth: '480px',
width: '100%',
textAlign: 'center'
}}
onClick={(e) => e.stopPropagation()}
>
<h3 style={{ marginTop: 0 }}>Confirmar Logout</h3>
<p>Tem certeza que deseja encerrar a sessão?</p>
<div style={{ display: 'flex', gap: '1rem', justifyContent: 'center', marginTop: '1rem' }}>
<button
onClick={onCancel}
style={{
padding: '10px 18px',
borderRadius: '8px',
border: '1px solid #ccc',
background: 'white',
cursor: 'pointer'
}}
>
Cancelar
</button>
<button
onClick={onConfirm}
style={{
padding: '10px 18px',
borderRadius: '8px',
border: 'none',
background: '#dc3545',
color: 'white',
cursor: 'pointer'
}}
>
Sair
</button>
</div>
</div>
</div>
);
// garante que exista document antes de criar portal (SSRed apps podem não ter)
if (typeof document === 'undefined') return null;
return createPortal(modalContent, document.body);
};
// --- Agora sim: condicional de render baseado na rota ---
if (location.pathname === '/login') {
return null;
}
// --- JSX principal ---
return (
<div className="header-container">
<div className="right-corner-elements">
@ -282,22 +369,9 @@ const Header = () => {
</div>
</div>
{/* Modal de Logout */}
{/* Modal de Logout via portal */}
{showLogoutModal && (
<div className="logout-modal-overlay">
<div className="logout-modal-content">
<h3>Confirmar Logout</h3>
<p>Tem certeza que deseja encerrar a sessão?</p>
<div className="logout-modal-buttons">
<button onClick={handleLogoutCancel} className="logout-cancel-button">
Cancelar
</button>
<button onClick={handleLogoutConfirm} className="logout-confirm-button">
Sair
</button>
</div>
</div>
</div>
<LogoutModalPortal onCancel={handleLogoutCancel} onConfirm={handleLogoutConfirm} />
)}
{isSuporteCardOpen && (
@ -319,4 +393,4 @@ const Header = () => {
);
};
export default Header;
export default Header;