Implementação da IA
This commit is contained in:
parent
626fcc8124
commit
f80e0eee81
2
.env
Normal file
2
.env
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
OPENAI_API_KEY=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
|
||||||
|
PORT=5000
|
||||||
899
package-lock.json
generated
899
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -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
38
server.js
Normal 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"));
|
||||||
@ -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
13
src/openaiService.js
Normal 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;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user