Prototipo do chatsuporte

This commit is contained in:
RafaelMTA13 2025-10-09 23:18:15 -03:00
parent b2e2423978
commit c9d1457775
8 changed files with 331 additions and 33 deletions

View File

@ -23,6 +23,6 @@
<!-- <script src="%PUBLIC_URL%/vendors/perfect-scrollbar/perfect-scrollbar.min.js"></script>
<script src="%PUBLIC_URL%/js/bootstrap.bundle.min.js"></script>
<script src="%PUBLIC_URL%/js/main.js"></script> -->
<script src="https://website-widgets.pages.dev/dist/sienna.min.js" defer></script>
</body>
</html>

View File

@ -45,3 +45,48 @@ html[data-bs-theme="dark"] .App-header {
html[data-bs-theme="dark"] .App-link {
color: #bb86fc;
}
.top-right-chat-button-wrapper {
position: fixed; /* 'fixed' faz ele flutuar mesmo com scroll */
top: 20px;
right: 20px;
z-index: 1001; /* Garante que fique acima de outros elementos */
}
/* App.css */
/* Container principal */
.app-wrapper {
display: flex; /* Organiza o conteúdo principal e o chat lado a lado */
}
.main-content {
position: relative; /* Essencial para ser o 'pai' */
flex-grow: 1;
transition: margin-right 0.4s ease-in-out;
}
.main-content.chat-open {
margin-right: 350px;
}
/* Posicionamento do botão que abre o chat */
.chat-button-container {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 999;
}
/* App.css */
.floating-buttons-container {
/* Posicionamento do GRUPO */
position: absolute;
bottom: 20px;
right: 20px;
z-index: 1000;
/* Alinhamento dos botões */
display: flex;
gap: 10px; /* Espaçamento entre os botões */
}

View File

@ -1,40 +1,43 @@
import React, { useState } from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import './App.css';
// Suas páginas
import Login from "./pages/Login";
import Register from "./pages/Register";
import Forgot from "./pages/ForgotPassword";
import PerfilSecretaria from "./perfis/perfil_secretaria/PerfilSecretaria";
import LandingPage from './pages/LandingPage';
import PerfilFinanceiro from "./perfis/perfil_financeiro/PerfilFinanceiro";
import Perfiladm from "./perfis/Perfil_adm/Perfiladm";
import PerfilMedico from "./perfis/Perfil_medico/PerfilMedico";
import PerfilSecretaria from "./perfis/perfil_secretaria/PerfilSecretaria";
// Componentes globais de acessibilidade
import VlibrasWidget from "./components/VlibrasWidget";
import BotaoAcessibilidade from "./components/botaoacessibilidade.jsx";
import ChatToggleButton from './components/ChatButton/ChatButton';
import ChatSidebar from './components/ChatSidebar/ChatSidebar';
function App() {
const [isChatOpen, setIsChatOpen] = useState(false);
const toggleChat = () => {
setIsChatOpen(!isChatOpen);
};
return (
<Router>
<VlibrasWidget />
<BotaoAcessibilidade />
<div className="app-wrapper">
<div className={`main-content ${isChatOpen ? 'chat-open' : ''}`}>
<VlibrasWidget />
<Routes>
<Route path="/" element={<LandingPage />} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
<Route path="/forgotPassword" element={<Forgot />} />
<Route path="/secretaria/*" element={<PerfilSecretaria />} />
<Route path="/financeiro/*" element={<PerfilFinanceiro />} />
<Route path="/medico/*" element={<PerfilMedico />} />
<Route path="/admin/*" element={<Perfiladm />} />
<Route path="*" element={<h2>Página não encontrada</h2>} />
</Routes>
<div className="floating-buttons-container">
<BotaoAcessibilidade />
<ChatToggleButton onClick={toggleChat} />
</div>
<Routes>
<Route path="/" element={<LandingPage />} />
<Route path="/secretaria/*" element={<PerfilSecretaria />} />
</Routes>
</div>
<ChatSidebar isOpen={isChatOpen} onClose={toggleChat} />
</div>
</Router>
);
}
export default App;

View File

@ -0,0 +1,27 @@
.chat-toggle-button {
width: 60px;
height: 60px;
border-radius: 50%;
background-color: #007bff;
color: white;
border: none;
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: background-color 0.3s ease;
}
.chat-toggle-button:hover {
background-color: #0056b3;
}
.chat-toggle-button svg {
width: 30px;
height: 30px;
fill: white;
}

View File

@ -0,0 +1,15 @@
import React from 'react';
import './ChatButton.css';
const ChatButton = ({ onClick }) => {
return (
<button className="chat-toggle-button" onClick={onClick} aria-label="Abrir chat">
{/* Ícone de Chat (SVG) */}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z"></path>
</svg>
</button>
);
};
export default ChatButton;

View File

@ -0,0 +1,134 @@
/* ================================================= */
/* Novo Estilo para ChatSidebar.css */
/* Inspirado no Design "MediConnect" */
/* ================================================= */
.chat-sidebar {
/* Layout e Posição */
height: 100vh;
width: 350px;
position: fixed;
top: 0;
right: 0;
/* Estilo MediConnect */
background-color: #FFFFFF; /* Fundo branco limpo, como os cards */
color: #333; /* Texto escuro padrão */
font-family: Arial, sans-serif; /* Use a mesma fonte do seu site, se souber */
/* Animação (sem alteração) */
transform: translateX(100%);
transition: transform 0.4s ease-in-out;
/* Sombra suave, como a dos cards */
box-shadow: -2px 0 15px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
z-index: 1000;
}
.chat-sidebar.open {
transform: translateX(0);
}
/* Cabeçalho */
.chat-header {
padding: 15px 20px;
background-color: #F8F9FA; /* Cinza bem claro, como o fundo do site */
border-bottom: 1px solid #E9ECEF; /* Borda sutil */
display: flex;
justify-content: space-between;
align-items: center;
}
.chat-header h3 {
margin: 0;
font-size: 18px;
font-weight: 600;
color: #212529; /* Cor do título dos cards */
}
.chat-close-button {
background: none;
border: none;
font-size: 24px;
cursor: pointer;
color: #6c757d; /* Cinza sutil para o ícone de fechar */
transition: color 0.2s;
}
.chat-close-button:hover {
color: #000;
}
/* Área das Mensagens */
.chat-messages {
flex-grow: 1;
padding: 20px;
overflow-y: auto;
background-color: #F8F9FA; /* Fundo igual ao header para consistência */
display: flex;
flex-direction: column;
gap: 12px; /* Espaçamento entre as mensagens */
}
/* Adicionando estilo para os balões de mensagem */
.message {
padding: 10px 15px;
border-radius: 18px;
max-width: 80%;
line-height: 1.4;
}
.message.received {
background-color: #E9ECEF; /* Cinza claro para mensagens recebidas */
color: #212529;
align-self: flex-start; /* Alinha à esquerda */
border-bottom-left-radius: 4px; /* Detalhe de estilo */
}
.message.sent {
background-color: #6C63FF; /* Cor principal do seu site */
color: white;
align-self: flex-end; /* Alinha à direita */
border-bottom-right-radius: 4px; /* Detalhe de estilo */
}
/* Área de Input */
.chat-input-area {
padding: 15px 20px;
display: flex;
gap: 10px; /* Espaço entre o input e o botão */
border-top: 1px solid #E9ECEF;
background-color: #FFFFFF; /* Fundo branco para destacar */
}
.chat-input-area input {
flex-grow: 1;
border: 1px solid #DEE2E6; /* Borda padrão */
border-radius: 8px; /* Bordas arredondadas como os elementos do site */
padding: 12px 15px;
font-size: 15px;
color: #333;
transition: border-color 0.2s;
}
.chat-input-area input:focus {
outline: none;
border-color: #6C63FF; /* Destaque com a cor principal */
box-shadow: 0 0 0 2px rgba(108, 99, 255, 0.2);
}
.chat-input-area button {
background-color: #6C63FF; /* Cor principal do seu site */
border: none;
color: white;
padding: 0 25px;
border-radius: 8px; /* Mesma borda do input */
font-weight: bold;
cursor: pointer;
transition: background-color 0.2s;
}
.chat-input-area button:hover {
background-color: #574ee6; /* Um tom um pouco mais escuro ao passar o mouse */
}

View File

@ -0,0 +1,79 @@
import React, { useState, useEffect, useRef } from 'react';
import './ChatSidebar.css';
const ChatSidebar = ({ isOpen, onClose }) => {
const [messages, setMessages] = useState([
{ id: 1, text: 'Olá! Como podemos ajudar você hoje?', sender: 'support' }
]);
const [inputValue, setInputValue] = useState('');
const messagesEndRef = useRef(null);
const sidebarClassName = `chat-sidebar ${isOpen ? 'open' : ''}`;
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
};
useEffect(() => {
scrollToBottom();
}, [messages]);
const handleSendMessage = () => {
if (inputValue.trim() === '') return;
const newMessage = {
id: messages.length + 1,
text: inputValue,
sender: 'user'
};
setMessages(currentMessages => [...currentMessages, newMessage]);
setInputValue('');
setTimeout(() => {
const supportReply = {
id: messages.length + 2,
text: 'Obrigado por sua mensagem. Um de nossos atendentes responderá em breve.',
sender: 'support'
};
setMessages(currentMessages => [...currentMessages, supportReply]);
}, 1000);
};
const handleKeyPress = (event) => {
if (event.key === 'Enter') {
handleSendMessage();
}
};
return (
<div className={sidebarClassName}>
<div className="chat-header">
<h3>Suporte Online</h3>
<button onClick={onClose} className="chat-close-button">X</button>
</div>
<div className="chat-messages">
{/* Mapeia a lista de mensagens e cria um balão para cada uma */}
{messages.map(message => (
<div
key={message.id}
className={`message ${message.sender === 'user' ? 'sent' : 'received'}`}
>
{message.text}
</div>
))}
{/* Elemento invisível no final para o scroll automático */}
<div ref={messagesEndRef} />
</div>
<div className="chat-input-area">
<input
type="text"
placeholder="Digite sua mensagem..."
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onKeyPress={handleKeyPress}
/>
<button onClick={handleSendMessage}>Enviar</button>
</div>
</div>
);
};
export default ChatSidebar;

View File

@ -4,12 +4,7 @@
display: none !important;
}
.container-acessibilidade {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 10000;
}
.botao-flutuante-acessibilidade {
width: 60px;
height: 60px;