ixg_platform/templates/portal/chat.html

159 lines
5.8 KiB
HTML

{% extends 'portal/base_portal.html' %}
{% load static %}
{% block title %}AI Chat - IXG Buyer Portal{% endblock %}
{% block content %}
<div class="page-header d-flex justify-content-between align-items-center">
<h2>AI Assistant</h2>
<div>
<select id="agent-select" class="form-select form-select-sm d-inline-block" style="width:auto;">
{% for a in agents %}
<option value="{{ a.id }}"{% if a.is_default %} selected{% endif %}>{{ a.name }}{% if a.is_default %} (default){% endif %}</option>
{% empty %}
<option value="">No agents configured</option>
{% endfor %}
</select>
<button class="btn btn-sm btn-outline-secondary" onclick="clearChat()">New Chat</button>
</div>
</div>
<div class="row">
<div class="col-md-8">
<div class="stat-card d-flex flex-column" style="height: calc(100vh - 260px);">
<div id="chat-messages" class="flex-grow-1 overflow-auto mb-3" style="min-height: 300px;">
<div class="text-center text-muted py-5" id="welcome-msg">
<i class="bi bi-robot fs-1"></i>
<p class="mt-2">Select an agent and start a conversation.</p>
</div>
</div>
<form id="chat-form" class="d-flex gap-2">
<input type="text" id="chat-input" class="form-control" placeholder="Type your message..." autofocus>
<button type="submit" class="btn btn-primary"><i class="bi bi-send"></i></button>
</form>
</div>
</div>
<div class="col-md-4">
<div class="stat-card" style="height: calc(100vh - 260px); overflow-y: auto;">
<h6 class="mb-3">Chat Sessions</h6>
<div id="session-list">
<p class="text-muted small">No previous sessions</p>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script>
var currentSessionId = "";
var currentAgentId = document.getElementById("agent-select").value;
document.getElementById("agent-select").addEventListener("change", function() {
currentAgentId = this.value;
});
async function loadSessions() {
try {
var resp = await fetch("/api/ai-interactions/sessions/");
var sessions = await resp.json();
var container = document.getElementById("session-list");
if (sessions.length === 0) {
container.innerHTML = '<p class="text-muted small">No previous sessions</p>';
return;
}
container.innerHTML = "<ul class="list-unstyled mb-0">" +
sessions.map(function(s) { return "<li class="border-bottom py-1"><a href="#" onclick="loadSession('" + s + "');return false;" class="text-decoration-none small">" + s.substring(0, 8) + "...</a></li>"; }).join("") +
"</ul>";
} catch(e) {
console.log("Sessions unavailable:", e);
}
}
async function loadSession(sessionId) {
currentSessionId = sessionId;
try {
var resp = await fetch("/api/ai-interactions/?session_id=" + sessionId);
var msgs = await resp.json();
var container = document.getElementById("chat-messages");
container.innerHTML = "";
document.getElementById("welcome-msg").style.display = "none";
msgs.forEach(function(m) {
addMessage(m.message_role, m.message_content);
});
container.scrollTop = container.scrollHeight;
} catch(e) {
console.log("Session load error:", e);
}
}
function addMessage(role, content) {
var container = document.getElementById("chat-messages");
document.getElementById("welcome-msg").style.display = "none";
var div = document.createElement("div");
div.className = "mb-3 " + (role === "user" ? "text-end" : "");
var bubble = document.createElement("div");
bubble.className = "d-inline-block p-3 rounded-3 " +
(role === "user" ? "bg-primary text-white" : "bg-light");
bubble.style.maxWidth = "80%";
bubble.style.textAlign = "left";
if (role === "assistant") {
bubble.innerHTML = marked.parse(content);
} else {
bubble.textContent = content;
}
div.appendChild(bubble);
container.appendChild(div);
container.scrollTop = container.scrollHeight;
}
document.getElementById("chat-form").addEventListener("submit", async function(e) {
e.preventDefault();
var input = document.getElementById("chat-input");
var message = input.value.trim();
if (!message || !currentAgentId) return;
input.value = "";
addMessage("user", message);
var historyDivs = document.querySelectorAll("#chat-messages > div");
var history = [];
historyDivs.forEach(function(d) {
var bubble = d.querySelector(".d-inline-block");
if (!bubble) return;
var role = d.classList.contains("text-end") ? "user" : "assistant";
history.push({ role: role, content: bubble.textContent });
});
try {
var resp = await fetch("/api/ai-interactions/chat/", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ agent_id: parseInt(currentAgentId), message: message, session_id: currentSessionId, history: history.slice(-20) }),
});
var data = await resp.json();
if (data.session_id) currentSessionId = data.session_id;
if (data.response) {
addMessage("assistant", data.response);
} else if (data.error) {
addMessage("assistant", "Error: " + data.error);
}
} catch(e) {
addMessage("assistant", "Connection error. Please try again.");
}
loadSessions();
});
function clearChat() {
currentSessionId = "";
document.getElementById("chat-messages").innerHTML = '<div class="text-center text-muted py-5" id="welcome-msg"><i class="bi bi-robot fs-1"></i><p class="mt-2">Select an agent and start a conversation.</p></div>';
document.getElementById("session-list").innerHTML = '<p class="text-muted small">No previous sessions</p>';
loadSessions();
}
loadSessions();
</script>
<style>
#chat-messages { scroll-behavior: smooth; }
#chat-messages .bg-light { background: #f0fdf4 !important; border: 1px solid #d1fae5; }
#chat-messages .bg-primary { background: #065f46 !important; }
</style>
{% endblock %}