Compare commits
3 Commits
83f88e34d7
...
28f12b467c
| Author | SHA1 | Date | |
|---|---|---|---|
| 28f12b467c | |||
| a01c62440e | |||
| 3833764438 |
@ -9,6 +9,8 @@ import LandingPage from './pages/LandingPage';
|
|||||||
import PerfilFinanceiro from "./perfis/perfil_financeiro/PerfilFinanceiro";
|
import PerfilFinanceiro from "./perfis/perfil_financeiro/PerfilFinanceiro";
|
||||||
import Perfiladm from "./perfis/Perfil_adm/Perfiladm";
|
import Perfiladm from "./perfis/Perfil_adm/Perfiladm";
|
||||||
import PerfilMedico from "./perfis/Perfil_medico/PerfilMedico";
|
import PerfilMedico from "./perfis/Perfil_medico/PerfilMedico";
|
||||||
|
import ProfilePage from "./pages/ProfilePage";
|
||||||
|
import Header from "./components/Header/Header";
|
||||||
|
|
||||||
// Componentes globais de acessibilidade
|
// Componentes globais de acessibilidade
|
||||||
import VlibrasWidget from "./components/VlibrasWidget";
|
import VlibrasWidget from "./components/VlibrasWidget";
|
||||||
@ -20,6 +22,7 @@ function App() {
|
|||||||
<Router>
|
<Router>
|
||||||
<VlibrasWidget />
|
<VlibrasWidget />
|
||||||
<BotaoAcessibilidade />
|
<BotaoAcessibilidade />
|
||||||
|
<Header />
|
||||||
|
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<LandingPage />} />
|
<Route path="/" element={<LandingPage />} />
|
||||||
@ -30,6 +33,7 @@ function App() {
|
|||||||
<Route path="/financeiro/*" element={<PerfilFinanceiro />} />
|
<Route path="/financeiro/*" element={<PerfilFinanceiro />} />
|
||||||
<Route path="/medico/*" element={<PerfilMedico />} />
|
<Route path="/medico/*" element={<PerfilMedico />} />
|
||||||
<Route path="/admin/*" element={<Perfiladm />} />
|
<Route path="/admin/*" element={<Perfiladm />} />
|
||||||
|
<Route path="/perfil" element={<ProfilePage />} />
|
||||||
<Route path="*" element={<h2>Página não encontrada</h2>} />
|
<Route path="*" element={<h2>Página não encontrada</h2>} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</Router>
|
</Router>
|
||||||
@ -37,4 +41,3 @@ function App() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|
||||||
|
|||||||
405
src/components/Header/Header.css
Normal file
405
src/components/Header/Header.css
Normal file
@ -0,0 +1,405 @@
|
|||||||
|
.header-container {
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding: 10px 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-corner-elements {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-icon-container {
|
||||||
|
font-size: 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-icon {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-section {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-picture-container {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 2px solid #ccc;
|
||||||
|
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-placeholder {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #A9A9A9;
|
||||||
|
border-radius: 50%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-placeholder::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 60%;
|
||||||
|
height: 60%;
|
||||||
|
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="%23FFFFFF" d="M224 256c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm-45.7 48C79.8 304 0 383.8 0 482.3c0 16.7 13.5 30.2 30.2 30.2h387.6c16.7 0 30.2-13.5 30.2-30.2 0-98.5-79.8-178.3-178.3-178.3h-45.7z"/></svg>');
|
||||||
|
background-size: contain;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-dropdown {
|
||||||
|
position: absolute;
|
||||||
|
top: 50px;
|
||||||
|
right: 0;
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
z-index: 1000;
|
||||||
|
min-width: 150px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-button {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
padding: 10px 15px;
|
||||||
|
text-align: left;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-button:hover {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-button {
|
||||||
|
color: #cc0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-button:hover {
|
||||||
|
background-color: #ffe0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suporte-card-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: flex-start;
|
||||||
|
z-index: 2000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suporte-card-container {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2001;
|
||||||
|
margin-top: 80px;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suporte-card {
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
|
||||||
|
padding: 2rem;
|
||||||
|
max-width: 400px;
|
||||||
|
width: 100%;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suporte-titulo {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suporte-subtitulo {
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contato-item {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contato-item:hover {
|
||||||
|
background-color: #e9ecef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contato-item.clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #e3f2fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contato-item.clickable:hover {
|
||||||
|
background-color: #bbdefb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contato-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contato-nome {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contato-descricao {
|
||||||
|
color: #666;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contato-item:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: flex-start;
|
||||||
|
z-index: 3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-container {
|
||||||
|
position: relative;
|
||||||
|
z-index: 3001;
|
||||||
|
margin-top: 80px;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-online {
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
|
||||||
|
width: 350px;
|
||||||
|
height: 500px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-header {
|
||||||
|
background-color: #1e3a8a;
|
||||||
|
color: white;
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 12px 12px 0 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-titulo {
|
||||||
|
color: white;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fechar-chat {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fechar-chat:hover {
|
||||||
|
background-color: rgba(255, 255, 255, 0.2);
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-mensagens {
|
||||||
|
flex: 1;
|
||||||
|
padding: 1rem;
|
||||||
|
overflow-y: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mensagem {
|
||||||
|
max-width: 80%;
|
||||||
|
padding: 0.75rem;
|
||||||
|
border-radius: 12px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mensagem.usuario {
|
||||||
|
align-self: flex-end;
|
||||||
|
background-color: #e3f2fd;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mensagem.suporte {
|
||||||
|
align-self: flex-start;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mensagem-texto {
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mensagem-hora {
|
||||||
|
font-size: 0.7rem;
|
||||||
|
color: #666;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mensagem.suporte .mensagem-hora {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-input {
|
||||||
|
display: flex;
|
||||||
|
padding: 1rem;
|
||||||
|
border-top: 1px solid #e0e0e0;
|
||||||
|
gap: 0.5rem;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 0 0 12px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-campo {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0.75rem;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 20px;
|
||||||
|
outline: none;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-campo:focus {
|
||||||
|
border-color: #1e3a8a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-enviar {
|
||||||
|
background-color: #1e3a8a;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
border-radius: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-enviar:hover {
|
||||||
|
background-color: #1e40af;
|
||||||
|
}
|
||||||
|
/* Modal de Logout */
|
||||||
|
.logout-modal-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-modal-content {
|
||||||
|
background-color: white;
|
||||||
|
padding: 2rem;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
|
||||||
|
max-width: 400px;
|
||||||
|
width: 90%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-modal-content h3 {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
color: #333;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-modal-content p {
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-modal-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-cancel-button {
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: transparent;
|
||||||
|
color: #333;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-cancel-button:hover {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-confirm-button {
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: #dc3545;
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-confirm-button:hover {
|
||||||
|
background-color: #c82333;
|
||||||
|
}
|
||||||
292
src/components/Header/Header.jsx
Normal file
292
src/components/Header/Header.jsx
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
import React, { useState, useRef, useEffect } from 'react';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import './Header.css';
|
||||||
|
|
||||||
|
const Header = () => {
|
||||||
|
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
||||||
|
const [isSuporteCardOpen, setIsSuporteCardOpen] = useState(false);
|
||||||
|
const [isChatOpen, setIsChatOpen] = useState(false);
|
||||||
|
const [mensagem, setMensagem] = useState('');
|
||||||
|
const [mensagens, setMensagens] = useState([]);
|
||||||
|
const [showLogoutModal, setShowLogoutModal] = useState(false);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const chatInputRef = useRef(null);
|
||||||
|
const mensagensContainerRef = useRef(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isChatOpen && chatInputRef.current) {
|
||||||
|
chatInputRef.current.focus();
|
||||||
|
}
|
||||||
|
}, [isChatOpen]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (mensagensContainerRef.current) {
|
||||||
|
mensagensContainerRef.current.scrollTop = mensagensContainerRef.current.scrollHeight;
|
||||||
|
}
|
||||||
|
}, [mensagens]);
|
||||||
|
|
||||||
|
// Funções de Logout (do seu código)
|
||||||
|
const handleLogoutClick = () => {
|
||||||
|
setShowLogoutModal(true);
|
||||||
|
setIsDropdownOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLogoutConfirm = async () => {
|
||||||
|
try {
|
||||||
|
const token =
|
||||||
|
localStorage.getItem("token") ||
|
||||||
|
localStorage.getItem("authToken") ||
|
||||||
|
localStorage.getItem("userToken") ||
|
||||||
|
localStorage.getItem("access_token") ||
|
||||||
|
sessionStorage.getItem("token") ||
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clearAuthData();
|
||||||
|
navigate("/login");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Erro durante logout:", error);
|
||||||
|
clearAuthData();
|
||||||
|
navigate("/login");
|
||||||
|
} finally {
|
||||||
|
setShowLogoutModal(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearAuthData = () => {
|
||||||
|
["token","authToken","userToken","access_token","user","auth","userData"].forEach(key => {
|
||||||
|
localStorage.removeItem(key);
|
||||||
|
sessionStorage.removeItem(key);
|
||||||
|
});
|
||||||
|
|
||||||
|
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 handleProfileClick = () => {
|
||||||
|
setIsDropdownOpen(!isDropdownOpen);
|
||||||
|
if (isSuporteCardOpen) setIsSuporteCardOpen(false);
|
||||||
|
if (isChatOpen) setIsChatOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleViewProfile = () => {
|
||||||
|
navigate('/perfil');
|
||||||
|
setIsDropdownOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSuporteClick = () => {
|
||||||
|
setIsSuporteCardOpen(!isSuporteCardOpen);
|
||||||
|
if (isDropdownOpen) setIsDropdownOpen(false);
|
||||||
|
if (isChatOpen) setIsChatOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCloseSuporteCard = () => {
|
||||||
|
setIsSuporteCardOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChatClick = () => {
|
||||||
|
setIsChatOpen(true);
|
||||||
|
setIsSuporteCardOpen(false);
|
||||||
|
setMensagens([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
texto: 'Olá! Bem-vindo ao suporte Mediconnect. Como podemos ajudar você hoje?',
|
||||||
|
remetente: 'suporte',
|
||||||
|
hora: new Date().toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' })
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCloseChat = () => {
|
||||||
|
setIsChatOpen(false);
|
||||||
|
setMensagem('');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEnviarMensagem = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (mensagem.trim() === '') return;
|
||||||
|
|
||||||
|
const novaMensagemUsuario = {
|
||||||
|
id: Date.now(),
|
||||||
|
texto: mensagem,
|
||||||
|
remetente: 'usuario',
|
||||||
|
hora: new Date().toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' })
|
||||||
|
};
|
||||||
|
|
||||||
|
setMensagens(prev => [...prev, novaMensagemUsuario]);
|
||||||
|
setMensagem('');
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
if (chatInputRef.current) {
|
||||||
|
chatInputRef.current.focus();
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const respostas = [
|
||||||
|
'Entendi sua dúvida. Vou verificar isso para você.',
|
||||||
|
'Obrigado pela informação. Estou analisando seu caso.',
|
||||||
|
'Pode me dar mais detalhes sobre o problema?',
|
||||||
|
'Já encaminhei sua solicitação para nossa equipe técnica.',
|
||||||
|
'Vou ajudar você a resolver isso!'
|
||||||
|
];
|
||||||
|
|
||||||
|
const respostaSuporte = {
|
||||||
|
id: Date.now() + 1,
|
||||||
|
texto: respostas[Math.floor(Math.random() * respostas.length)],
|
||||||
|
remetente: 'suporte',
|
||||||
|
hora: new Date().toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' })
|
||||||
|
};
|
||||||
|
|
||||||
|
setMensagens(prev => [...prev, respostaSuporte]);
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SuporteCard = () => (
|
||||||
|
<div className="suporte-card">
|
||||||
|
<h2 className="suporte-titulo">Suporte</h2>
|
||||||
|
<p className="suporte-subtitulo">Entre em contato conosco através dos canais abaixo</p>
|
||||||
|
|
||||||
|
<div className="contato-item">
|
||||||
|
<div className="contato-info">
|
||||||
|
<div className="contato-nome">Email</div>
|
||||||
|
<div className="contato-descricao">suporte@mediconnect.com</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="contato-item">
|
||||||
|
<div className="contato-info">
|
||||||
|
<div className="contato-nome">Telefone</div>
|
||||||
|
<div className="contato-descricao">(11) 3333-4444</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="contato-item clickable" onClick={handleChatClick}>
|
||||||
|
<div className="contato-info">
|
||||||
|
<div className="contato-nome">Chat Online</div>
|
||||||
|
<div className="contato-descricao">Disponível 24/7</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const ChatOnline = () => (
|
||||||
|
<div className="chat-online">
|
||||||
|
<div className="chat-header">
|
||||||
|
<h3 className="chat-titulo">Chat de Suporte</h3>
|
||||||
|
<button type="button" className="fechar-chat" onClick={handleCloseChat}>×</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="chat-mensagens" ref={mensagensContainerRef}>
|
||||||
|
{mensagens.map((msg) => (
|
||||||
|
<div key={msg.id} className={`mensagem ${msg.remetente}`}>
|
||||||
|
<div className="mensagem-texto">{msg.texto}</div>
|
||||||
|
<div className="mensagem-hora">{msg.hora}</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form className="chat-input" onSubmit={handleEnviarMensagem}>
|
||||||
|
<input
|
||||||
|
ref={chatInputRef}
|
||||||
|
type="text"
|
||||||
|
value={mensagem}
|
||||||
|
onChange={(e) => setMensagem(e.target.value)}
|
||||||
|
placeholder="Digite sua mensagem..."
|
||||||
|
className="chat-campo"
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
<button type="submit" className="chat-enviar">Enviar</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="header-container">
|
||||||
|
<div className="right-corner-elements">
|
||||||
|
<div className="phone-icon-container" onClick={handleSuporteClick}>
|
||||||
|
<span className="phone-icon" role="img" aria-label="telefone">📞</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="profile-section">
|
||||||
|
<div className="profile-picture-container" onClick={handleProfileClick}>
|
||||||
|
<div className="profile-placeholder"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isDropdownOpen && (
|
||||||
|
<div className="profile-dropdown">
|
||||||
|
<button type="button" onClick={handleViewProfile} className="dropdown-button">Ver Perfil</button>
|
||||||
|
<button type="button" onClick={handleLogoutClick} className="dropdown-button logout-button">Sair (Logout)</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Modal de Logout */}
|
||||||
|
{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>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{isSuporteCardOpen && (
|
||||||
|
<div className="suporte-card-overlay" onClick={handleCloseSuporteCard}>
|
||||||
|
<div className="suporte-card-container" onClick={(e) => e.stopPropagation()}>
|
||||||
|
<SuporteCard />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{isChatOpen && (
|
||||||
|
<div className="chat-overlay">
|
||||||
|
<div className="chat-container">
|
||||||
|
<ChatOnline />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Header;
|
||||||
206
src/pages/ProfilePage.jsx
Normal file
206
src/pages/ProfilePage.jsx
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
// src/pages/ProfilePage.jsx
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
|
// import { useAuth } from '../components/utils/AuthProvider'; // <-- NOVO: Se você puder importar isso.
|
||||||
|
|
||||||
|
// --- SIMULAÇÃO DE DADOS DE USUÁRIO ---
|
||||||
|
// COMO NÃO PODEMOS IMPORTAR O useAuth SEM MEXER EM OUTROS ARQUIVOS, VAMOS USAR ESTA SIMULAÇÃO:
|
||||||
|
const simulatedUserData = {
|
||||||
|
// ESTA SIMULAÇÃO DEVERIA SER SUBTITUÍDA PELO SEU CONTEXTO DE AUTENTICAÇÃO REAL.
|
||||||
|
// O EMAIL REALMENTE LOGADO VEM DO CONTEXTO DE AUTENTICAÇÃO (useAuth)
|
||||||
|
email: 'admin@squad23.com',
|
||||||
|
role: 'Administrador' // Vamos forçar um valor para fins de visualização
|
||||||
|
};
|
||||||
|
|
||||||
|
const ProfilePage = () => {
|
||||||
|
const location = useLocation();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
// const { user } = useAuth(); // Descomente esta linha e comente o bloco simulatedUserData se puder usar o useAuth!
|
||||||
|
|
||||||
|
// --- Lógica de Cargo (AGORA CORRIGIDA PARA PEGAR DA URL SE O CONTEXTO FALHAR) ---
|
||||||
|
const getRoleFromPath = () => {
|
||||||
|
const path = location.pathname;
|
||||||
|
if (path.includes('/admin')) return 'Administrador';
|
||||||
|
if (path.includes('/secretaria')) return 'Secretária';
|
||||||
|
if (path.includes('/medico')) return 'Médico';
|
||||||
|
if (path.includes('/financeiro')) return 'Financeiro';
|
||||||
|
return 'Usuário Padrão';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use a simulação ou o dado real:
|
||||||
|
const userRole = simulatedUserData.role || getRoleFromPath();
|
||||||
|
const userEmail = simulatedUserData.email || 'email.nao.encontrado@mediconnect.com';
|
||||||
|
|
||||||
|
// --- Estados do Componente ---
|
||||||
|
|
||||||
|
// Se o nome do usuário vier do contexto de autenticação, use-o aqui
|
||||||
|
const [userName, setUserName] = useState('Admin Padrão');
|
||||||
|
const [isEditingName, setIsEditingName] = useState(false);
|
||||||
|
|
||||||
|
// --- Funções de Interação ---
|
||||||
|
|
||||||
|
const handleNameChange = (e) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
setIsEditingName(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
navigate(-1); // Volta para a página anterior
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={styles.overlay}>
|
||||||
|
<div style={styles.modalContainer}>
|
||||||
|
|
||||||
|
{/* Botão de Fechar (X) */}
|
||||||
|
<button onClick={handleClose} style={styles.closeButton} aria-label="Fechar Perfil">
|
||||||
|
×
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* 1. Área da Foto de Perfil (Quadrada) */}
|
||||||
|
<div style={styles.profilePictureContainer}>
|
||||||
|
<div style={styles.profilePicturePlaceholder}></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={styles.infoContainer}>
|
||||||
|
|
||||||
|
{/* 2. Nome do Usuário com Edição */}
|
||||||
|
<div style={styles.nameSection}>
|
||||||
|
{isEditingName ? (
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={userName}
|
||||||
|
onChange={(e) => setUserName(e.target.value)}
|
||||||
|
onBlur={() => setIsEditingName(false)}
|
||||||
|
onKeyPress={handleNameChange}
|
||||||
|
autoFocus
|
||||||
|
style={styles.nameInput}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<h2 style={styles.userName}>{userName}</h2>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={() => setIsEditingName(!isEditingName)}
|
||||||
|
style={styles.editButton}
|
||||||
|
aria-label="Editar Nome"
|
||||||
|
>
|
||||||
|
<span role="img" aria-label="lapis">✏️</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 3. Email (AGORA EXIBE O VALOR SIMULADO/CORRIGIDO) */}
|
||||||
|
<p style={styles.emailText}>Email: <strong>{userEmail}</strong></p>
|
||||||
|
|
||||||
|
{/* 4. Cargo (AGORA EXIBE O VALOR SIMULADO/CORRIGIDO) */}
|
||||||
|
<p style={styles.roleText}>Cargo: <strong>{userRole}</strong></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Estilos Atualizados para Aumentar o Tamanho do Modal
|
||||||
|
const styles = {
|
||||||
|
overlay: {
|
||||||
|
position: 'fixed',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
zIndex: 1100,
|
||||||
|
},
|
||||||
|
modalContainer: {
|
||||||
|
position: 'relative',
|
||||||
|
padding: '50px 70px', // Aumentado o padding
|
||||||
|
backgroundColor: 'white',
|
||||||
|
borderRadius: '15px',
|
||||||
|
boxShadow: '0 8px 30px rgba(0, 0, 0, 0.3)',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignItems: 'center',
|
||||||
|
minWidth: '400px',
|
||||||
|
width: '60%', // Aumentando a largura para cobrir mais a tela
|
||||||
|
maxWidth: '500px', // Limite máximo para não ficar gigante em telas grandes
|
||||||
|
height: 'auto',
|
||||||
|
},
|
||||||
|
closeButton: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: '15px',
|
||||||
|
right: '20px',
|
||||||
|
background: 'none',
|
||||||
|
border: 'none',
|
||||||
|
fontSize: '30px',
|
||||||
|
cursor: 'pointer',
|
||||||
|
color: '#666',
|
||||||
|
lineHeight: '1',
|
||||||
|
},
|
||||||
|
// ... (Os estilos de profilePictureContainer, infoContainer, etc., permanecem iguais)
|
||||||
|
profilePictureContainer: {
|
||||||
|
width: '120px',
|
||||||
|
height: '120px',
|
||||||
|
borderRadius: '15px',
|
||||||
|
overflow: 'hidden',
|
||||||
|
boxShadow: '0 4px 10px rgba(0, 0, 0, 0.15)',
|
||||||
|
marginBottom: '20px',
|
||||||
|
},
|
||||||
|
profilePicturePlaceholder: {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
backgroundColor: '#A9A9A9',
|
||||||
|
backgroundImage: 'url(\'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="%23FFFFFF" d="M224 256c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm-45.7 48C79.8 304 0 383.8 0 482.3c0 16.7 13.5 30.2 30.2 30.2h387.6c16.7 0 30.2-13.5 30.2-30.2 0-98.5-79.8-178.3-178.3-178.3h-45.7z"/></svg>\')',
|
||||||
|
backgroundSize: '80%',
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundPosition: 'center',
|
||||||
|
},
|
||||||
|
infoContainer: {
|
||||||
|
textAlign: 'center',
|
||||||
|
maxWidth: '400px',
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
nameSection: {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
marginBottom: '10px',
|
||||||
|
},
|
||||||
|
userName: {
|
||||||
|
margin: '0 5px 0 0',
|
||||||
|
fontSize: '1.8rem',
|
||||||
|
color: '#333',
|
||||||
|
},
|
||||||
|
nameInput: {
|
||||||
|
fontSize: '1.8rem',
|
||||||
|
padding: '5px',
|
||||||
|
border: '1px solid #ccc',
|
||||||
|
borderRadius: '5px',
|
||||||
|
textAlign: 'center',
|
||||||
|
marginRight: '5px',
|
||||||
|
},
|
||||||
|
editButton: {
|
||||||
|
background: 'none',
|
||||||
|
border: 'none',
|
||||||
|
cursor: 'pointer',
|
||||||
|
fontSize: '1.2rem',
|
||||||
|
marginLeft: '5px',
|
||||||
|
},
|
||||||
|
emailText: {
|
||||||
|
fontSize: '1rem',
|
||||||
|
color: '#666',
|
||||||
|
margin: '5px 0',
|
||||||
|
},
|
||||||
|
roleText: {
|
||||||
|
fontSize: '1.1rem',
|
||||||
|
color: '#333',
|
||||||
|
marginTop: '15px',
|
||||||
|
paddingTop: '10px',
|
||||||
|
borderTop: '1px solid #eee',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProfilePage;
|
||||||
10
src/pages/Support.jsx
Normal file
10
src/pages/Support.jsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export default function Support() {
|
||||||
|
return (
|
||||||
|
<div style={{padding:40}}>
|
||||||
|
<h3>Suporte por telefone</h3>
|
||||||
|
<p>Funcionalidade de chamada/suporte será implementada em breve.</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
0
src/pages/style/ProfilePage.css
Normal file
0
src/pages/style/ProfilePage.css
Normal file
@ -1,62 +0,0 @@
|
|||||||
.container-perfis {
|
|
||||||
position: absolute;
|
|
||||||
top: 80px;
|
|
||||||
left: 30px;
|
|
||||||
width: calc(100% - 60px);
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
z-index: 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
.acesso-text {
|
|
||||||
font-size: 15px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #1e2b57;
|
|
||||||
margin-bottom: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* estilo visual refinado do select */
|
|
||||||
.perfil-select {
|
|
||||||
width: 100%;
|
|
||||||
padding: 10px 14px;
|
|
||||||
border-radius: 10px;
|
|
||||||
border: 1.8px solid #d0d5dd;
|
|
||||||
background-color: #f9fafc;
|
|
||||||
color: #1e2b57;
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 14px;
|
|
||||||
outline: none;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
box-shadow: 0 1px 3px rgba(30, 43, 87, 0.08);
|
|
||||||
}
|
|
||||||
|
|
||||||
.perfil-select:hover {
|
|
||||||
border-color: #7a85ff;
|
|
||||||
background-color: #ffffff;
|
|
||||||
box-shadow: 0 2px 6px rgba(30, 43, 87, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.perfil-select:focus {
|
|
||||||
border-color: #5a46ff;
|
|
||||||
box-shadow: 0 0 0 3px rgba(90, 70, 255, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.perfil-select option[value=""] {
|
|
||||||
color: #777;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* responsivo */
|
|
||||||
@media (max-width: 780px) {
|
|
||||||
.container-perfis {
|
|
||||||
top: 60px;
|
|
||||||
left: 20px;
|
|
||||||
width: calc(100% - 40px);
|
|
||||||
}
|
|
||||||
.perfil-select {
|
|
||||||
font-size: 13px;
|
|
||||||
padding: 8px 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user