implementacao do sistema de logout com modal e API
This commit is contained in:
parent
fe455a256a
commit
efa723dbe3
@ -1,138 +1,271 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
import menuItems from "../data/sidebar-items-medico.json"; // Use "sidebar-items-secretaria.json" para secretaria e "sidebar-items-adm.json" para ADM
|
import menuItems from "../data/sidebar-items-medico.json";
|
||||||
import TrocardePerfis from "./TrocardePerfis";
|
import TrocardePerfis from "./TrocardePerfis";
|
||||||
|
|
||||||
|
function Sidebar({ menuItems }) {
|
||||||
|
const [isActive, setIsActive] = useState(true);
|
||||||
|
const [openSubmenu, setOpenSubmenu] = useState(null);
|
||||||
|
const [showLogoutModal, setShowLogoutModal] = useState(false);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
// 1. Recebe 'menuItems' e 'onLogout' como props
|
const toggleSidebar = () => {
|
||||||
function Sidebar({ menuItems, onLogout }) {
|
setIsActive(!isActive);
|
||||||
const [isActive, setIsActive] = useState(true);
|
};
|
||||||
const [openSubmenu, setOpenSubmenu] = useState(null);
|
|
||||||
|
|
||||||
const toggleSidebar = () => {
|
const handleSubmenuClick = (submenuName) => {
|
||||||
setIsActive(!isActive);
|
setOpenSubmenu(openSubmenu === submenuName ? null : submenuName);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmenuClick = (submenuName) => {
|
const handleLogoutClick = () => {
|
||||||
setOpenSubmenu(openSubmenu === submenuName ? null : submenuName);
|
setShowLogoutModal(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderLink = (item) => {
|
const handleLogoutConfirm = async () => {
|
||||||
// Links internos (rotas do React Router)
|
try {
|
||||||
if (item.url && item.url.startsWith("/")) {
|
const token = localStorage.getItem('token') ||
|
||||||
return (
|
localStorage.getItem('authToken') ||
|
||||||
<Link to={item.url} className="sidebar-link">
|
localStorage.getItem('userToken') ||
|
||||||
{item.icon && <i className={`bi bi-${item.icon}`}></i>}
|
localStorage.getItem('access_token') ||
|
||||||
<span>{item.name}</span>
|
sessionStorage.getItem('token') ||
|
||||||
</Link>
|
sessionStorage.getItem('authToken');
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Links externos
|
if (token) {
|
||||||
return (
|
const response = await fetch('https://mock.apidog.com/m1/1053378-0-default/auth/v1/logout', {
|
||||||
<a
|
method: 'POST',
|
||||||
href={item.url}
|
headers: {
|
||||||
className="sidebar-link"
|
'Content-Type': 'application/json',
|
||||||
target="_blank"
|
'Authorization': `Bearer ${token}`
|
||||||
rel="noreferrer"
|
}
|
||||||
>
|
});
|
||||||
{item.icon && <i className={`bi bi-${item.icon}`}></i>}
|
|
||||||
<span>{item.name}</span>
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
if (response.status === 204) {
|
||||||
<div id="sidebar" className={isActive ? "active" : ""}>
|
console.log('Logout realizado com sucesso');
|
||||||
<div className="sidebar-wrapper active">
|
} else if (response.status === 401) {
|
||||||
<div className="sidebar-header">
|
console.log('Token inválido ou expirado');
|
||||||
{/* ... Header... */}
|
} else {
|
||||||
<div className="d-flex justify-content-between">
|
try {
|
||||||
<div className="logo">
|
const errorData = await response.json();
|
||||||
<Link to="/">
|
console.error('Erro no logout:', errorData);
|
||||||
<h1>MediConnect</h1>
|
} catch {
|
||||||
</Link>
|
console.error('Erro no logout - status:', response.status);
|
||||||
</div>
|
}
|
||||||
<div className="toggler">
|
}
|
||||||
<button
|
}
|
||||||
type="button"
|
|
||||||
className="sidebar-hide d-xl-none d-block btn"
|
clearAuthData();
|
||||||
onClick={toggleSidebar}
|
navigate('/login');
|
||||||
>
|
|
||||||
<i className="bi bi-x bi-middle"></i>
|
} catch (error) {
|
||||||
</button>
|
console.error('Erro durante logout:', error);
|
||||||
</div>
|
clearAuthData();
|
||||||
</div>
|
navigate('/login');
|
||||||
</div>
|
} finally {
|
||||||
|
setShowLogoutModal(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearAuthData = () => {
|
||||||
|
localStorage.removeItem('token');
|
||||||
|
localStorage.removeItem('authToken');
|
||||||
|
localStorage.removeItem('userToken');
|
||||||
|
localStorage.removeItem('access_token');
|
||||||
|
localStorage.removeItem('user');
|
||||||
|
localStorage.removeItem('auth');
|
||||||
|
localStorage.removeItem('userData');
|
||||||
|
|
||||||
|
sessionStorage.removeItem('token');
|
||||||
|
sessionStorage.removeItem('authToken');
|
||||||
|
sessionStorage.removeItem('userToken');
|
||||||
|
sessionStorage.removeItem('access_token');
|
||||||
|
sessionStorage.removeItem('user');
|
||||||
|
sessionStorage.removeItem('auth');
|
||||||
|
sessionStorage.removeItem('userData');
|
||||||
|
|
||||||
|
if (window.caches) {
|
||||||
|
caches.keys().then(names => {
|
||||||
|
names.forEach(name => {
|
||||||
|
if (name.includes('auth') || name.includes('api')) {
|
||||||
|
caches.delete(name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLogoutCancel = () => {
|
||||||
|
setShowLogoutModal(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderLink = (item) => {
|
||||||
|
if (item.url && item.url.startsWith("/")) {
|
||||||
|
return (
|
||||||
|
<Link to={item.url} className="sidebar-link">
|
||||||
|
{item.icon && <i className={`bi bi-${item.icon}`}></i>}
|
||||||
|
<span>{item.name}</span>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
<div className="sidebar-menu">
|
|
||||||
<ul className="menu">
|
|
||||||
{menuItems && menuItems.map((item, index) => {
|
|
||||||
if (item.isTitle) {
|
|
||||||
return (
|
return (
|
||||||
<li key={index} className="sidebar-title">
|
<a
|
||||||
{item.name}
|
href={item.url}
|
||||||
</li>
|
className="sidebar-link"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
{item.icon && <i className={`bi bi-${item.icon}`}></i>}
|
||||||
|
<span>{item.name}</span>
|
||||||
|
</a>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
if (item.submenu) {
|
return (
|
||||||
return (
|
<>
|
||||||
<li
|
{showLogoutModal && (
|
||||||
key={index}
|
<div className="modal-overlay" style={{
|
||||||
className={`sidebar-item has-sub ${
|
position: 'fixed',
|
||||||
openSubmenu === item.key ? "active" : ""
|
top: 0,
|
||||||
}`}
|
left: 0,
|
||||||
>
|
right: 0,
|
||||||
{/* ... Lógica de Submenu ... */}
|
bottom: 0,
|
||||||
<button
|
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||||
type="button"
|
display: 'flex',
|
||||||
className="sidebar-link btn"
|
justifyContent: 'center',
|
||||||
onClick={() => handleSubmenuClick(item.key)}
|
alignItems: 'center',
|
||||||
>
|
zIndex: 9999
|
||||||
<i className={`bi bi-${item.icon}`}></i>
|
}}>
|
||||||
<span>{item.name}</span>
|
<div className="modal-content" style={{
|
||||||
</button>
|
backgroundColor: 'white',
|
||||||
<ul
|
padding: '2rem',
|
||||||
className={`submenu ${
|
borderRadius: '8px',
|
||||||
openSubmenu === item.key ? "active" : ""
|
boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
|
||||||
}`}
|
maxWidth: '400px',
|
||||||
>
|
width: '90%'
|
||||||
{item.submenu.map((subItem, subIndex) => (
|
}}>
|
||||||
<li key={subIndex} className="submenu-item">
|
<h3 style={{ marginBottom: '1rem' }}>Confirmar Logout</h3>
|
||||||
{renderLink(subItem)}
|
<p style={{ marginBottom: '2rem' }}>Tem certeza que deseja encerrar a sessão?</p>
|
||||||
</li>
|
<div style={{ display: 'flex', gap: '1rem', justifyContent: 'flex-end' }}>
|
||||||
))}
|
<button
|
||||||
</ul>
|
onClick={handleLogoutCancel}
|
||||||
</li>
|
style={{
|
||||||
);
|
padding: '0.5rem 1rem',
|
||||||
}
|
border: '1px solid #ccc',
|
||||||
|
borderRadius: '4px',
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
cursor: 'pointer'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Cancelar
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={handleLogoutConfirm}
|
||||||
|
style={{
|
||||||
|
padding: '0.5rem 1rem',
|
||||||
|
border: 'none',
|
||||||
|
borderRadius: '4px',
|
||||||
|
backgroundColor: '#dc3545',
|
||||||
|
color: 'white',
|
||||||
|
cursor: 'pointer'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Sair
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
return (
|
<div id="sidebar" className={isActive ? "active" : ""}>
|
||||||
<li key={index} className="sidebar-item">
|
<div className="sidebar-wrapper active">
|
||||||
{renderLink(item)}
|
<div className="sidebar-header">
|
||||||
</li>
|
<div className="d-flex justify-content-between">
|
||||||
);
|
<div className="logo">
|
||||||
})}
|
<Link to="/">
|
||||||
{/* 3. Adiciona o botão de logout no final do menu */}
|
<h1>MediConnect</h1>
|
||||||
<li className="sidebar-item" onClick={onLogout}>
|
</Link>
|
||||||
<button type="button" className="sidebar-link btn">
|
</div>
|
||||||
<i className="bi bi-box-arrow-right"></i>
|
<div className="toggler">
|
||||||
<span>Sair (Logout)</span>
|
<button
|
||||||
</button>
|
type="button"
|
||||||
</li>
|
className="sidebar-hide d-xl-none d-block btn"
|
||||||
|
onClick={toggleSidebar}
|
||||||
|
>
|
||||||
|
<i className="bi bi-x bi-middle"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<TrocardePerfis />
|
<div className="sidebar-menu">
|
||||||
|
<ul className="menu">
|
||||||
|
{menuItems && menuItems.map((item, index) => {
|
||||||
|
if (item.isTitle) {
|
||||||
|
return (
|
||||||
|
<li key={index} className="sidebar-title">
|
||||||
|
{item.name}
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
</ul>
|
if (item.submenu) {
|
||||||
</div>
|
return (
|
||||||
|
<li
|
||||||
<button className="sidebar-toggler btn x" onClick={toggleSidebar}>
|
key={index}
|
||||||
<i data-feather="x"></i>
|
className={`sidebar-item has-sub ${openSubmenu === item.key ? "active" : ""
|
||||||
</button>
|
}`}
|
||||||
</div>
|
>
|
||||||
</div>
|
<button
|
||||||
);
|
type="button"
|
||||||
|
className="sidebar-link btn"
|
||||||
|
onClick={() => handleSubmenuClick(item.key)}
|
||||||
|
>
|
||||||
|
<i className={`bi bi-${item.icon}`}></i>
|
||||||
|
<span>{item.name}</span>
|
||||||
|
</button>
|
||||||
|
<ul
|
||||||
|
className={`submenu ${openSubmenu === item.key ? "active" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{item.submenu.map((subItem, subIndex) => (
|
||||||
|
<li key={subIndex} className="submenu-item">
|
||||||
|
{renderLink(subItem)}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li key={index} className="sidebar-item">
|
||||||
|
{renderLink(item)}
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
<li className="sidebar-item">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="sidebar-link btn"
|
||||||
|
onClick={handleLogoutClick}
|
||||||
|
>
|
||||||
|
<i className="bi bi-box-arrow-right"></i>
|
||||||
|
<span>Sair (Logout)</span>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<TrocardePerfis />
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button className="sidebar-toggler btn x" onClick={toggleSidebar}>
|
||||||
|
<i data-feather="x"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Sidebar;
|
export default Sidebar;
|
||||||
Loading…
x
Reference in New Issue
Block a user