adding chat pot
This commit is contained in:
parent
290e13038f
commit
f5e53da1b1
BIN
ai/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
ai/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
ai/__pycache__/local_ai_api.cpython-311.pyc
Normal file
BIN
ai/__pycache__/local_ai_api.cpython-311.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -21,6 +21,9 @@
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
<link rel="stylesheet" href="{% static 'css/custom.css' %}?v={{ deployment_timestamp }}">
|
||||
<!-- Chatbot Widget CSS -->
|
||||
<link rel="stylesheet" href="{% static 'css/chatbot.css' %}?v={{ deployment_timestamp }}">
|
||||
|
||||
{% block head %}{% endblock %}
|
||||
<style>
|
||||
body { font-family: 'Outfit', sans-serif; background-color: #f8f9fa; }
|
||||
@ -185,8 +188,40 @@
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Chatbot Widget HTML -->
|
||||
<div id="chatbot-widget">
|
||||
<button id="chatbot-button" title="{% trans 'Chat with MASAR AI' %}">
|
||||
<i class="fa-solid fa-robot"></i>
|
||||
</button>
|
||||
|
||||
<div id="chatbot-window">
|
||||
<div id="chatbot-header">
|
||||
<h5>MASAR AI</h5>
|
||||
<button id="chatbot-close">×</button>
|
||||
</div>
|
||||
<div id="chatbot-messages">
|
||||
<div class="chat-message bot">
|
||||
{% trans "Hello! I am MASAR, your AI assistant. How can I help you today?" %}
|
||||
</div>
|
||||
</div>
|
||||
<div id="chatbot-input-container">
|
||||
<input type="text" id="chatbot-input" placeholder="{% trans 'Type a message...' %}">
|
||||
<button id="chatbot-send">
|
||||
<i class="fa-solid fa-paper-plane"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="px-3 pb-2 text-center">
|
||||
<a href="https://wa.me/{{ app_settings.contact_phone|default:'' }}" target="_blank" class="small text-muted text-decoration-none">
|
||||
<i class="fa-brands fa-whatsapp text-success"></i> {% trans "Talk to a Human" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bootstrap 5 JS Bundle -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<!-- Chatbot Widget JS -->
|
||||
<script src="{% static 'js/chatbot.js' %}?v={{ deployment_timestamp }}"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@ -33,4 +33,5 @@ urlpatterns = [
|
||||
path("admin/financials/", views.admin_financials, name="admin_financials"),
|
||||
path("admin/refund/<str:receipt_number>/", views.issue_refund, name="issue_refund"),
|
||||
path("admin/settings/", views.admin_app_settings, name="admin_app_settings"),
|
||||
path("api/chat/", views.chat_api, name="chat_api"),
|
||||
]
|
||||
@ -7,7 +7,7 @@ from django.utils import timezone
|
||||
from django.urls import reverse
|
||||
from .models import (
|
||||
Profile, Truck, Shipment, Bid, Message, OTPCode, Country, City,
|
||||
AppSetting, Banner, HomeSection, Transaction, ContactMessage, Testimonial
|
||||
AppSetting, Banner, HomeSection, Transaction, ContactMessage, Testimonial, WhatsAppConfig
|
||||
)
|
||||
from .forms import (
|
||||
TruckForm, ShipmentForm, BidForm, UserRegistrationForm,
|
||||
@ -23,8 +23,10 @@ from django.contrib.auth.forms import AuthenticationForm
|
||||
from django.core.mail import send_mail
|
||||
from django.conf import settings
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.http import HttpResponse
|
||||
from django.http import HttpResponse, JsonResponse
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.utils.translation import get_language
|
||||
from ai.local_ai_api import LocalAIApi
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
@ -778,4 +780,52 @@ def contact(request):
|
||||
return render(request, 'core/contact.html', {
|
||||
'form': form,
|
||||
'app_settings': app_settings
|
||||
})
|
||||
})
|
||||
|
||||
@csrf_exempt
|
||||
def chat_api(request):
|
||||
if request.method != 'POST':
|
||||
return JsonResponse({'success': False, 'error': 'Method not allowed'}, status=405)
|
||||
|
||||
try:
|
||||
data = json.loads(request.body)
|
||||
user_message = data.get('message', '')
|
||||
if not user_message:
|
||||
return JsonResponse({'success': False, 'error': 'Message is empty'})
|
||||
|
||||
# Maintain conversation history in session
|
||||
history = request.session.get('chat_history', [])
|
||||
|
||||
# System prompt to define the bot's personality
|
||||
system_prompt = {
|
||||
"role": "system",
|
||||
"content": "You are MASAR, the AI assistant for MASAR CARGO, a logistics and trucking marketplace in Oman. "
|
||||
"You help shippers find trucks and truck owners find shipments. "
|
||||
"Answer questions politely and concisely. If the user asks for something you can't do, "
|
||||
"suggest contacting support via WhatsApp. "
|
||||
"Current language: " + (get_language() or 'en')
|
||||
}
|
||||
|
||||
messages_input = [system_prompt] + history + [{"role": "user", "content": user_message}]
|
||||
|
||||
response = LocalAIApi.create_response({
|
||||
"input": messages_input
|
||||
})
|
||||
|
||||
if response.get("success"):
|
||||
ai_reply = LocalAIApi.extract_text(response)
|
||||
|
||||
# Update history
|
||||
history.append({"role": "user", "content": user_message})
|
||||
history.append({"role": "assistant", "content": ai_reply})
|
||||
# Keep only last 10 messages for context efficiency
|
||||
request.session['chat_history'] = history[-10:]
|
||||
|
||||
return JsonResponse({'success': True, 'reply': ai_reply})
|
||||
else:
|
||||
logger.error(f"AI Error: {response.get('error')}")
|
||||
return JsonResponse({'success': False, 'error': 'AI failed to respond'})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Chat API Error: {str(e)}")
|
||||
return JsonResponse({'success': False, 'error': str(e)})
|
||||
|
||||
Binary file not shown.
@ -2093,3 +2093,15 @@ msgstr "حدث خطأ أثناء تحديث شاحنتك. يرجى التحقق
|
||||
|
||||
#~ msgid "Contact for Renewal"
|
||||
#~ msgstr "الاتصال للتجديد"
|
||||
|
||||
msgid "Chat with MASAR AI"
|
||||
msgstr "تحدث مع مسار الذكي"
|
||||
|
||||
msgid "Hello! I am MASAR, your AI assistant. How can I help you today?"
|
||||
msgstr "أهلاً بك! أنا مسار، مساعدك الذكي. كيف يمكنني مساعدتك اليوم؟"
|
||||
|
||||
msgid "Type a message..."
|
||||
msgstr "اكتب رسالة..."
|
||||
|
||||
msgid "Talk to a Human"
|
||||
msgstr "تحدث مع شخص حقيقي"
|
||||
|
||||
165
static/css/chatbot.css
Normal file
165
static/css/chatbot.css
Normal file
@ -0,0 +1,165 @@
|
||||
/* Chatbot Floating Widget Styles */
|
||||
#chatbot-widget {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
z-index: 1000;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
}
|
||||
|
||||
#chatbot-button {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #007bff, #0056b3);
|
||||
color: white;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
#chatbot-button:hover {
|
||||
transform: scale(1.1);
|
||||
box-shadow: 0 6px 20px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
#chatbot-button svg {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
#chatbot-window {
|
||||
position: absolute;
|
||||
bottom: 80px;
|
||||
right: 0;
|
||||
width: 350px;
|
||||
height: 500px;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(10px);
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.15);
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
#chatbot-window.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#chatbot-header {
|
||||
background: linear-gradient(135deg, #007bff, #0056b3);
|
||||
color: white;
|
||||
padding: 15px 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#chatbot-header h5 {
|
||||
margin: 0;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#chatbot-close {
|
||||
background: none;
|
||||
border: none;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
font-size: 1.5rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
#chatbot-messages {
|
||||
flex: 1;
|
||||
padding: 15px;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.chat-message {
|
||||
max-width: 80%;
|
||||
padding: 10px 15px;
|
||||
border-radius: 15px;
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.chat-message.bot {
|
||||
align-self: flex-start;
|
||||
background: #f0f2f5;
|
||||
color: #333;
|
||||
border-bottom-left-radius: 5px;
|
||||
}
|
||||
|
||||
.chat-message.user {
|
||||
align-self: flex-end;
|
||||
background: #007bff;
|
||||
color: white;
|
||||
border-bottom-right-radius: 5px;
|
||||
}
|
||||
|
||||
#chatbot-input-container {
|
||||
padding: 15px;
|
||||
border-top: 1px solid #eee;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
#chatbot-input {
|
||||
flex: 1;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 20px;
|
||||
padding: 8px 15px;
|
||||
outline: none;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
#chatbot-send {
|
||||
background: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* RTL Support */
|
||||
[dir="rtl"] #chatbot-widget {
|
||||
right: auto;
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
[dir="rtl"] #chatbot-window {
|
||||
right: auto;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
[dir="rtl"] .chat-message.bot {
|
||||
border-bottom-left-radius: 15px;
|
||||
border-bottom-right-radius: 5px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .chat-message.user {
|
||||
border-bottom-right-radius: 15px;
|
||||
border-bottom-left-radius: 5px;
|
||||
}
|
||||
|
||||
.typing-indicator {
|
||||
font-style: italic;
|
||||
font-size: 0.8rem;
|
||||
color: #888;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
99
static/js/chatbot.js
Normal file
99
static/js/chatbot.js
Normal file
@ -0,0 +1,99 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const chatbotButton = document.getElementById('chatbot-button');
|
||||
const chatbotWindow = document.getElementById('chatbot-window');
|
||||
const chatbotClose = document.getElementById('chatbot-close');
|
||||
const chatbotInput = document.getElementById('chatbot-input');
|
||||
const chatbotSend = document.getElementById('chatbot-send');
|
||||
const chatbotMessages = document.getElementById('chatbot-messages');
|
||||
|
||||
if (!chatbotButton) return;
|
||||
|
||||
// Toggle window
|
||||
chatbotButton.addEventListener('click', () => {
|
||||
chatbotWindow.classList.toggle('active');
|
||||
if (chatbotWindow.classList.contains('active')) {
|
||||
chatbotInput.focus();
|
||||
}
|
||||
});
|
||||
|
||||
chatbotClose.addEventListener('click', () => {
|
||||
chatbotWindow.classList.remove('active');
|
||||
});
|
||||
|
||||
// Send message function
|
||||
async function sendMessage() {
|
||||
const message = chatbotInput.value.trim();
|
||||
if (!message) return;
|
||||
|
||||
// Add user message to UI
|
||||
appendMessage('user', message);
|
||||
chatbotInput.value = '';
|
||||
|
||||
// Add typing indicator
|
||||
const typingId = 'typing-' + Date.now();
|
||||
const typingDiv = document.createElement('div');
|
||||
typingDiv.id = typingId;
|
||||
typingDiv.className = 'typing-indicator';
|
||||
typingDiv.innerText = document.documentElement.lang === 'ar' ? 'جاري الكتابة...' : 'Typing...';
|
||||
chatbotMessages.appendChild(typingDiv);
|
||||
chatbotMessages.scrollTop = chatbotMessages.scrollHeight;
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/chat/', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
},
|
||||
body: JSON.stringify({ message: message })
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// Remove typing indicator
|
||||
const typingElement = document.getElementById(typingId);
|
||||
if (typingElement) typingElement.remove();
|
||||
|
||||
if (data.success) {
|
||||
appendMessage('bot', data.reply);
|
||||
} else {
|
||||
appendMessage('bot', 'Sorry, I encountered an error. Please try again later.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
const typingElement = document.getElementById(typingId);
|
||||
if (typingElement) typingElement.remove();
|
||||
appendMessage('bot', 'Network error. Please check your connection.');
|
||||
}
|
||||
}
|
||||
|
||||
function appendMessage(role, text) {
|
||||
const msgDiv = document.createElement('div');
|
||||
msgDiv.className = `chat-message ${role}`;
|
||||
msgDiv.innerText = text;
|
||||
chatbotMessages.appendChild(msgDiv);
|
||||
chatbotMessages.scrollTop = chatbotMessages.scrollHeight;
|
||||
}
|
||||
|
||||
// Event listeners for sending
|
||||
chatbotSend.addEventListener('click', sendMessage);
|
||||
chatbotInput.addEventListener('keypress', (e) => {
|
||||
if (e.key === 'Enter') sendMessage();
|
||||
});
|
||||
|
||||
// CSRF helper
|
||||
function getCookie(name) {
|
||||
let cookieValue = null;
|
||||
if (document.cookie && document.cookie !== '') {
|
||||
const cookies = document.cookie.split(';');
|
||||
for (let i = 0; i < cookies.length; i++) {
|
||||
const cookie = cookies[i].trim();
|
||||
if (cookie.substring(0, name.length + 1) === (name + '=')) {
|
||||
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cookieValue;
|
||||
}
|
||||
});
|
||||
165
staticfiles/css/chatbot.css
Normal file
165
staticfiles/css/chatbot.css
Normal file
@ -0,0 +1,165 @@
|
||||
/* Chatbot Floating Widget Styles */
|
||||
#chatbot-widget {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
z-index: 1000;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
}
|
||||
|
||||
#chatbot-button {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #007bff, #0056b3);
|
||||
color: white;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
#chatbot-button:hover {
|
||||
transform: scale(1.1);
|
||||
box-shadow: 0 6px 20px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
#chatbot-button svg {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
#chatbot-window {
|
||||
position: absolute;
|
||||
bottom: 80px;
|
||||
right: 0;
|
||||
width: 350px;
|
||||
height: 500px;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(10px);
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.15);
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
#chatbot-window.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#chatbot-header {
|
||||
background: linear-gradient(135deg, #007bff, #0056b3);
|
||||
color: white;
|
||||
padding: 15px 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#chatbot-header h5 {
|
||||
margin: 0;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#chatbot-close {
|
||||
background: none;
|
||||
border: none;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
font-size: 1.5rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
#chatbot-messages {
|
||||
flex: 1;
|
||||
padding: 15px;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.chat-message {
|
||||
max-width: 80%;
|
||||
padding: 10px 15px;
|
||||
border-radius: 15px;
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.chat-message.bot {
|
||||
align-self: flex-start;
|
||||
background: #f0f2f5;
|
||||
color: #333;
|
||||
border-bottom-left-radius: 5px;
|
||||
}
|
||||
|
||||
.chat-message.user {
|
||||
align-self: flex-end;
|
||||
background: #007bff;
|
||||
color: white;
|
||||
border-bottom-right-radius: 5px;
|
||||
}
|
||||
|
||||
#chatbot-input-container {
|
||||
padding: 15px;
|
||||
border-top: 1px solid #eee;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
#chatbot-input {
|
||||
flex: 1;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 20px;
|
||||
padding: 8px 15px;
|
||||
outline: none;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
#chatbot-send {
|
||||
background: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* RTL Support */
|
||||
[dir="rtl"] #chatbot-widget {
|
||||
right: auto;
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
[dir="rtl"] #chatbot-window {
|
||||
right: auto;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
[dir="rtl"] .chat-message.bot {
|
||||
border-bottom-left-radius: 15px;
|
||||
border-bottom-right-radius: 5px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .chat-message.user {
|
||||
border-bottom-right-radius: 15px;
|
||||
border-bottom-left-radius: 5px;
|
||||
}
|
||||
|
||||
.typing-indicator {
|
||||
font-style: italic;
|
||||
font-size: 0.8rem;
|
||||
color: #888;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
99
staticfiles/js/chatbot.js
Normal file
99
staticfiles/js/chatbot.js
Normal file
@ -0,0 +1,99 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const chatbotButton = document.getElementById('chatbot-button');
|
||||
const chatbotWindow = document.getElementById('chatbot-window');
|
||||
const chatbotClose = document.getElementById('chatbot-close');
|
||||
const chatbotInput = document.getElementById('chatbot-input');
|
||||
const chatbotSend = document.getElementById('chatbot-send');
|
||||
const chatbotMessages = document.getElementById('chatbot-messages');
|
||||
|
||||
if (!chatbotButton) return;
|
||||
|
||||
// Toggle window
|
||||
chatbotButton.addEventListener('click', () => {
|
||||
chatbotWindow.classList.toggle('active');
|
||||
if (chatbotWindow.classList.contains('active')) {
|
||||
chatbotInput.focus();
|
||||
}
|
||||
});
|
||||
|
||||
chatbotClose.addEventListener('click', () => {
|
||||
chatbotWindow.classList.remove('active');
|
||||
});
|
||||
|
||||
// Send message function
|
||||
async function sendMessage() {
|
||||
const message = chatbotInput.value.trim();
|
||||
if (!message) return;
|
||||
|
||||
// Add user message to UI
|
||||
appendMessage('user', message);
|
||||
chatbotInput.value = '';
|
||||
|
||||
// Add typing indicator
|
||||
const typingId = 'typing-' + Date.now();
|
||||
const typingDiv = document.createElement('div');
|
||||
typingDiv.id = typingId;
|
||||
typingDiv.className = 'typing-indicator';
|
||||
typingDiv.innerText = document.documentElement.lang === 'ar' ? 'جاري الكتابة...' : 'Typing...';
|
||||
chatbotMessages.appendChild(typingDiv);
|
||||
chatbotMessages.scrollTop = chatbotMessages.scrollHeight;
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/chat/', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
},
|
||||
body: JSON.stringify({ message: message })
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// Remove typing indicator
|
||||
const typingElement = document.getElementById(typingId);
|
||||
if (typingElement) typingElement.remove();
|
||||
|
||||
if (data.success) {
|
||||
appendMessage('bot', data.reply);
|
||||
} else {
|
||||
appendMessage('bot', 'Sorry, I encountered an error. Please try again later.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
const typingElement = document.getElementById(typingId);
|
||||
if (typingElement) typingElement.remove();
|
||||
appendMessage('bot', 'Network error. Please check your connection.');
|
||||
}
|
||||
}
|
||||
|
||||
function appendMessage(role, text) {
|
||||
const msgDiv = document.createElement('div');
|
||||
msgDiv.className = `chat-message ${role}`;
|
||||
msgDiv.innerText = text;
|
||||
chatbotMessages.appendChild(msgDiv);
|
||||
chatbotMessages.scrollTop = chatbotMessages.scrollHeight;
|
||||
}
|
||||
|
||||
// Event listeners for sending
|
||||
chatbotSend.addEventListener('click', sendMessage);
|
||||
chatbotInput.addEventListener('keypress', (e) => {
|
||||
if (e.key === 'Enter') sendMessage();
|
||||
});
|
||||
|
||||
// CSRF helper
|
||||
function getCookie(name) {
|
||||
let cookieValue = null;
|
||||
if (document.cookie && document.cookie !== '') {
|
||||
const cookies = document.cookie.split(';');
|
||||
for (let i = 0; i < cookies.length; i++) {
|
||||
const cookie = cookies[i].trim();
|
||||
if (cookie.substring(0, name.length + 1) === (name + '=')) {
|
||||
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cookieValue;
|
||||
}
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user