Implementação da IA

This commit is contained in:
RafaelMTA13 2025-10-29 16:02:47 -03:00
parent 626fcc8124
commit f80e0eee81
6 changed files with 765 additions and 254 deletions

2
.env Normal file
View File

@ -0,0 +1,2 @@
OPENAI_API_KEY=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
PORT=5000

899
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -18,10 +18,15 @@
"apexcharts": "^5.3.4", "apexcharts": "^5.3.4",
"bootstrap": "^5.3.8", "bootstrap": "^5.3.8",
"bootstrap-icons": "^1.13.1", "bootstrap-icons": "^1.13.1",
"cors": "^2.8.5",
"dayjs": "^1.11.18", "dayjs": "^1.11.18",
"dotenv": "^17.2.3",
"express": "^5.1.0",
"flatpickr": "^4.6.13", "flatpickr": "^4.6.13",
"html2pdf.js": "^0.12.1", "html2pdf.js": "^0.12.1",
"lucide-react": "^0.543.0", "lucide-react": "^0.543.0",
"node-fetch": "^3.3.2",
"openai": "^6.7.0",
"perfect-scrollbar": "^1.5.6", "perfect-scrollbar": "^1.5.6",
"powershell": "^2.3.3", "powershell": "^2.3.3",
"quill": "^2.0.3", "quill": "^2.0.3",

38
server.js Normal file
View File

@ -0,0 +1,38 @@
import express from "express";
import cors from "cors";
import dotenv from "dotenv";
import OpenAI from "openai";
dotenv.config();
const app = express();
app.use(cors());
app.use(express.json());
const client = new OpenAI({
apiKey: process.env.OPENAI_API_KEY, // Coloque sua chave no .env
});
app.post("/api/chat", async (req, res) => {
try {
const { message } = req.body;
const completion = await client.chat.completions.create({
model: "gpt-4o-mini", // modelo rápido e leve
messages: [
{
role: "system",
content: "Você é o assistente virtual do site Mediconnect. Responda de forma amigável e informativa, explicando sobre o funcionamento do site, cadastro, agendamento, e suporte técnico.",
},
{ role: "user", content: message },
],
});
const resposta = completion.choices[0].message.content;
res.json({ resposta });
} catch (error) {
console.error("Erro no servidor:", error);
res.status(500).json({ erro: "Erro ao conectar com a IA" });
}
});
app.listen(5000, () => console.log("Servidor rodando na porta 5000"));

View File

@ -25,7 +25,7 @@ const Header = () => {
} }
}, [mensagens]); }, [mensagens]);
// Funções de Logout (do seu código) // --- Logout ---
const handleLogoutClick = () => { const handleLogoutClick = () => {
setShowLogoutModal(true); setShowLogoutModal(true);
setIsDropdownOpen(false); setIsDropdownOpen(false);
@ -77,7 +77,7 @@ const Header = () => {
}; };
const clearAuthData = () => { const clearAuthData = () => {
["token","authToken","userToken","access_token","user","auth","userData"].forEach(key => { ["token", "authToken", "userToken", "access_token", "user", "auth", "userData"].forEach(key => {
localStorage.removeItem(key); localStorage.removeItem(key);
sessionStorage.removeItem(key); sessionStorage.removeItem(key);
}); });
@ -100,7 +100,7 @@ const Header = () => {
}; };
const handleViewProfile = () => { const handleViewProfile = () => {
navigate('/perfil'); navigate('/perfil');
setIsDropdownOpen(false); setIsDropdownOpen(false);
}; };
@ -120,7 +120,7 @@ const Header = () => {
setMensagens([ setMensagens([
{ {
id: 1, id: 1,
texto: 'Olá! Bem-vindo ao suporte Mediconnect. Como podemos ajudar você hoje?', texto: 'Olá! 👋 Bem-vindo ao suporte Mediconnect. Como posso te ajudar hoje?',
remetente: 'suporte', remetente: 'suporte',
hora: new Date().toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' }) hora: new Date().toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' })
} }
@ -132,10 +132,12 @@ const Header = () => {
setMensagem(''); setMensagem('');
}; };
const handleEnviarMensagem = (e) => { // 🚀 Envio de mensagem com IA
const handleEnviarMensagem = async (e) => {
e.preventDefault(); e.preventDefault();
if (mensagem.trim() === '') return; if (mensagem.trim() === '') return;
// Mensagem do usuário
const novaMensagemUsuario = { const novaMensagemUsuario = {
id: Date.now(), id: Date.now(),
texto: mensagem, texto: mensagem,
@ -146,51 +148,55 @@ const Header = () => {
setMensagens(prev => [...prev, novaMensagemUsuario]); setMensagens(prev => [...prev, novaMensagemUsuario]);
setMensagem(''); setMensagem('');
setTimeout(() => { try {
if (chatInputRef.current) { const response = await fetch("http://localhost:5000/api/chat", {
chatInputRef.current.focus(); method: "POST",
} headers: { "Content-Type": "application/json" },
}, 0); body: JSON.stringify({ message: mensagem }),
});
setTimeout(() => { const data = await response.json();
const respostas = [
'Entendi sua dúvida. Vou verificar isso para você.', // Resposta da IA
'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 = { const respostaSuporte = {
id: Date.now() + 1, id: Date.now() + 1,
texto: respostas[Math.floor(Math.random() * respostas.length)], texto: data.resposta || data.reply || "Desculpe, não consegui processar sua pergunta no momento 😅",
remetente: 'suporte', remetente: 'suporte',
hora: new Date().toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' }) hora: new Date().toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' })
}; };
setMensagens(prev => [...prev, respostaSuporte]); setMensagens(prev => [...prev, respostaSuporte]);
}, 1000); } catch (error) {
console.error("Erro ao conectar com o servidor:", error);
const erroMsg = {
id: Date.now() + 1,
texto: "Ops! 😥 Ocorreu um erro ao tentar falar com o suporte.",
remetente: 'suporte',
hora: new Date().toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' })
};
setMensagens(prev => [...prev, erroMsg]);
}
}; };
const SuporteCard = () => ( const SuporteCard = () => (
<div className="suporte-card"> <div className="suporte-card">
<h2 className="suporte-titulo">Suporte</h2> <h2 className="suporte-titulo">Suporte</h2>
<p className="suporte-subtitulo">Entre em contato conosco através dos canais abaixo</p> <p className="suporte-subtitulo">Entre em contato conosco através dos canais abaixo</p>
<div className="contato-item"> <div className="contato-item">
<div className="contato-info"> <div className="contato-info">
<div className="contato-nome">Email</div> <div className="contato-nome">Email</div>
<div className="contato-descricao">suporte@mediconnect.com</div> <div className="contato-descricao">suporte@mediconnect.com</div>
</div> </div>
</div> </div>
<div className="contato-item"> <div className="contato-item">
<div className="contato-info"> <div className="contato-info">
<div className="contato-nome">Telefone</div> <div className="contato-nome">Telefone</div>
<div className="contato-descricao">(11) 3333-4444</div> <div className="contato-descricao">(11) 3333-4444</div>
</div> </div>
</div> </div>
<div className="contato-item clickable" onClick={handleChatClick}> <div className="contato-item clickable" onClick={handleChatClick}>
<div className="contato-info"> <div className="contato-info">
<div className="contato-nome">Chat Online</div> <div className="contato-nome">Chat Online</div>
@ -206,7 +212,7 @@ const Header = () => {
<h3 className="chat-titulo">Chat de Suporte</h3> <h3 className="chat-titulo">Chat de Suporte</h3>
<button type="button" className="fechar-chat" onClick={handleCloseChat}>×</button> <button type="button" className="fechar-chat" onClick={handleCloseChat}>×</button>
</div> </div>
<div className="chat-mensagens" ref={mensagensContainerRef}> <div className="chat-mensagens" ref={mensagensContainerRef}>
{mensagens.map((msg) => ( {mensagens.map((msg) => (
<div key={msg.id} className={`mensagem ${msg.remetente}`}> <div key={msg.id} className={`mensagem ${msg.remetente}`}>
@ -215,7 +221,7 @@ const Header = () => {
</div> </div>
))} ))}
</div> </div>
<form className="chat-input" onSubmit={handleEnviarMensagem}> <form className="chat-input" onSubmit={handleEnviarMensagem}>
<input <input
ref={chatInputRef} ref={chatInputRef}
@ -240,7 +246,7 @@ const Header = () => {
<div className="profile-section"> <div className="profile-section">
<div className="profile-picture-container" onClick={handleProfileClick}> <div className="profile-picture-container" onClick={handleProfileClick}>
<div className="profile-placeholder"></div> <div className="profile-placeholder"></div>
</div> </div>
{isDropdownOpen && ( {isDropdownOpen && (
@ -289,4 +295,4 @@ const Header = () => {
); );
}; };
export default Header; export default Header;

13
src/openaiService.js Normal file
View File

@ -0,0 +1,13 @@
// src/services/openaiService.js
export async function perguntarOpenAI(mensagem) {
const resposta = await fetch("http://localhost:5000/api/chat", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ message: mensagem }),
});
const data = await resposta.json();
return data.reply;
}