From 28f12b467ccb2bc06fc49bb9da5ea6aa4560df1b Mon Sep 17 00:00:00 2001 From: Caio Miguel Lima Nunes Date: Tue, 14 Oct 2025 19:04:07 -0300 Subject: [PATCH] =?UTF-8?q?Cria=C3=A7=C3=A3o=20da=20tela/fun=C3=A7=C3=A3o?= =?UTF-8?q?=20de=20suporte?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Header/Header.css | 340 +++++++++++++++++++++++++++++-- src/components/Header/Header.jsx | 268 ++++++++++++++++++++++-- 2 files changed, 569 insertions(+), 39 deletions(-) diff --git a/src/components/Header/Header.css b/src/components/Header/Header.css index dd15ca0..09ee387 100644 --- a/src/components/Header/Header.css +++ b/src/components/Header/Header.css @@ -1,33 +1,31 @@ -/* src/components/Header/Header.css */ .header-container { width: 100%; - position: absolute; /* Permite posicionamento livre sobre o conteúdo */ + position: absolute; top: 0; left: 0; display: flex; - justify-content: flex-end; /* Alinha os elementos do container à direita */ + justify-content: flex-end; padding: 10px 20px; box-sizing: border-box; - z-index: 1000; /* Garante que fique acima de outros elementos */ + z-index: 1000; } .right-corner-elements { display: flex; align-items: center; - gap: 20px; /* Espaço entre o telefone e a seção de perfil */ + gap: 20px; } -/* --- ÍCONE DE TELEFONE --- */ .phone-icon-container { font-size: 24px; cursor: pointer; - padding: 5px; /* Área clicável um pouco maior */ -} -.phone-icon { - display: block; /* Garante que o emoji fique bem centralizado */ + padding: 5px; +} + +.phone-icon { + display: block; } -/* --- SEÇÃO DE PERFIL --- */ .profile-section { position: relative; display: flex; @@ -37,19 +35,18 @@ .profile-picture-container { width: 40px; height: 40px; - border-radius: 50%; /* Círculo */ + border-radius: 50%; overflow: hidden; cursor: pointer; - border: 2px solid #ccc; /* Borda simples */ + border: 2px solid #ccc; box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); } .profile-placeholder { width: 100%; height: 100%; - background-color: #A9A9A9; /* Cor cinza escura para o fundo */ + background-color: #A9A9A9; border-radius: 50%; - /* Adicionando um ícone simples de pessoa em branco para simular o ícone */ position: relative; } @@ -64,13 +61,12 @@ background-image: url('data:image/svg+xml;utf8,'); background-size: contain; background-repeat: no-repeat; - opacity: 0.8; /* Suaviza um pouco o ícone */ + opacity: 0.8; } -/* --- DROPDOWN (MENU) --- */ .profile-dropdown { position: absolute; - top: 50px; /* Posição abaixo da foto de perfil (40px + 10px de espaço) */ + top: 50px; right: 0; background-color: white; border: 1px solid #ddd; @@ -78,9 +74,9 @@ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); display: flex; flex-direction: column; - z-index: 10; + z-index: 1000; min-width: 150px; - overflow: hidden; /* Garante que bordas fiquem visíveis */ + overflow: hidden; } .dropdown-button { @@ -99,9 +95,311 @@ } .logout-button { - color: #cc0000; /* Cor vermelha para o botão de logout */ + 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; } \ No newline at end of file diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.jsx index 533c1a2..449a7aa 100644 --- a/src/components/Header/Header.jsx +++ b/src/components/Header/Header.jsx @@ -1,58 +1,290 @@ -// src/components/Header/Header.jsx -import React, { useState } from 'react'; +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 = () => { - // Redireciona para uma página de perfil (Rota que adicionaremos no App.js) navigate('/perfil'); setIsDropdownOpen(false); }; - const handleLogout = () => { - // Ação de Logout: Exibe um alerta e redireciona para a tela de Login - alert('Você foi desconectado. Executando ação de logout...'); - setIsDropdownOpen(false); - navigate('/login'); + const handleSuporteClick = () => { + setIsSuporteCardOpen(!isSuporteCardOpen); + if (isDropdownOpen) setIsDropdownOpen(false); + if (isChatOpen) setIsChatOpen(false); }; - const handleSupportClick = () => { - // Funcionalidade de suporte (futuramente implementada em TelefoneSuporte) - alert('Função de Suporte de Telefone em desenvolvimento.'); + 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 = () => ( +
+

Suporte

+

Entre em contato conosco através dos canais abaixo

+ +
+
+
Email
+
suporte@mediconnect.com
+
+
+ +
+
+
Telefone
+
(11) 3333-4444
+
+
+ +
+
+
Chat Online
+
Disponível 24/7
+
+
+
+ ); + + const ChatOnline = () => ( +
+
+

Chat de Suporte

+ +
+ +
+ {mensagens.map((msg) => ( +
+
{msg.texto}
+
{msg.hora}
+
+ ))} +
+ +
+ setMensagem(e.target.value)} + placeholder="Digite sua mensagem..." + className="chat-campo" + autoFocus + /> + +
+
+ ); + return (
- - {/* Ícone de Telefone */} -
+
📞
- {/* Seção de Perfil com Dropdown */}
- {/* O div "profile-placeholder" simula a foto de perfil circular colorida */}
{isDropdownOpen && (
- - + +
)}
+ + {/* Modal de Logout */} + {showLogoutModal && ( +
+
+

Confirmar Logout

+

Tem certeza que deseja encerrar a sessão?

+
+ + +
+
+
+ )} + + {isSuporteCardOpen && ( +
+
e.stopPropagation()}> + +
+
+ )} + + {isChatOpen && ( +
+
+ +
+
+ )}
); };