|
|
|
const qs = (selector) => document.querySelector(selector);
|
|
const qsa = (selector) => document.querySelectorAll(selector);
|
|
|
|
|
|
const sidebar = qs('#sidebar');
|
|
const openSidebarBtn = qs('#open-sidebar');
|
|
const closeSidebarBtn = qs('#close-sidebar');
|
|
const chatForm = qs('#chat-form');
|
|
const messageInput = qs('#message-input');
|
|
const messagesContainer = qs('#messages');
|
|
const newChatBtn = qs('#new-chat');
|
|
const chatHistoryContainer = qs('#chat-history');
|
|
const toggleThemeBtn = qs('#toggle-theme');
|
|
const emojiPickerBtn = qs('#emoji-picker-btn');
|
|
const emojiPicker = qs('#emoji-picker');
|
|
const usernameInput = qs('#username-input');
|
|
const themeSelector = qs('#theme-selector');
|
|
const themePreview = qs('#theme-preview');
|
|
const chatSearch = qs('#chat-search');
|
|
const bubbleStyle = qs('#bubble-style');
|
|
const chatContainer = qs('#chat-container') || messagesContainer;
|
|
|
|
let chats = JSON.parse(localStorage.getItem('chats')) || [];
|
|
let currentChatId = null;
|
|
let currentUser = localStorage.getItem('username') || 'Kullanıcı';
|
|
let lastSender = null;
|
|
let messageDraft = localStorage.getItem('messageDraft') || '';
|
|
|
|
|
|
const themeColors = {
|
|
default: '#4f46e5', blue: '#3b82f6', green: '#10b981', purple: '#8b5cf6', red: '#ef4444'
|
|
};
|
|
|
|
|
|
function initializeSettings() {
|
|
usernameInput.value = currentUser;
|
|
messageInput.value = messageDraft;
|
|
if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
|
|
const savedColor = localStorage.getItem('colorTheme') || 'default';
|
|
const savedBubble = localStorage.getItem('bubbleStyle') || 'rounded';
|
|
themeSelector.value = savedColor;
|
|
bubbleStyle.value = savedBubble;
|
|
themePreview.style.background = themeColors[savedColor];
|
|
document.body.classList.add(`theme-${savedColor}`);
|
|
document.documentElement.style.setProperty('--bubble-radius', savedBubble === 'rounded' ? '12px' : '4px');
|
|
}
|
|
|
|
|
|
function applyTheme(theme) {
|
|
document.body.className = document.body.className.replace(/theme-\w+/g, '');
|
|
document.body.classList.add(`theme-${theme}`);
|
|
themePreview.style.background = themeColors[theme];
|
|
localStorage.setItem('colorTheme', theme);
|
|
}
|
|
|
|
|
|
toggleThemeBtn?.addEventListener('click', () => {
|
|
document.body.classList.toggle('dark');
|
|
localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light');
|
|
});
|
|
|
|
|
|
usernameInput.addEventListener('change', () => {
|
|
currentUser = usernameInput.value.trim() || 'Kullanıcı';
|
|
localStorage.setItem('username', currentUser);
|
|
renderChatHistory();
|
|
});
|
|
|
|
messageInput.addEventListener('input', () => {
|
|
localStorage.setItem('messageDraft', messageInput.value);
|
|
});
|
|
|
|
themeSelector.addEventListener('change', () => applyTheme(themeSelector.value));
|
|
themeSelector.addEventListener('mouseover', () => themePreview.style.background = themeColors[themeSelector.value]);
|
|
|
|
bubbleStyle.addEventListener('change', () => {
|
|
const radius = bubbleStyle.value === 'rounded' ? '12px' : '4px';
|
|
document.documentElement.style.setProperty('--bubble-radius', radius);
|
|
localStorage.setItem('bubbleStyle', bubbleStyle.value);
|
|
});
|
|
|
|
openSidebarBtn?.addEventListener('click', () => sidebar.classList.remove('hidden'));
|
|
closeSidebarBtn?.addEventListener('click', () => sidebar.classList.add('hidden'));
|
|
emojiPickerBtn?.addEventListener('click', () => emojiPicker.classList.toggle('hidden'));
|
|
chatSearch.addEventListener('input', () => renderChatHistory(chatSearch.value.toLowerCase()));
|
|
|
|
messageInput.addEventListener('keydown', (e) => {
|
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
e.preventDefault();
|
|
chatForm.dispatchEvent(new Event('submit'));
|
|
} else if (e.key === 'Escape') {
|
|
emojiPicker.classList.add('hidden');
|
|
}
|
|
});
|
|
|
|
|
|
newChatBtn.addEventListener('click', () => {
|
|
currentChatId = Date.now().toString();
|
|
chats.push({ id: currentChatId, messages: [] });
|
|
saveChats();
|
|
renderChatHistory();
|
|
messagesContainer.innerHTML = '';
|
|
lastSender = null;
|
|
showNotification('Yeni sohbet başlatıldı!', 'success');
|
|
});
|
|
|
|
|
|
let isWaitingResponse = false;
|
|
chatForm.addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
if (isWaitingResponse) return;
|
|
|
|
const query = messageInput.value.trim();
|
|
if (!query) return showNotification('Lütfen bir mesaj yazın!', 'error');
|
|
|
|
isWaitingResponse = true;
|
|
addMessage(query, 'user');
|
|
showTypingIndicator();
|
|
|
|
try {
|
|
const res = await fetch('/api/ask', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ query: query })
|
|
});
|
|
const data = await res.json();
|
|
removeTypingIndicator();
|
|
addMessage(data.answer || 'Bir hata oluştu.', 'bot');
|
|
saveMessage(data.answer || 'Bir hata oluştu.', 'bot');
|
|
} catch {
|
|
removeTypingIndicator();
|
|
addMessage('Cevap alınamadı.', 'bot');
|
|
saveMessage('Cevap alınamadı.', 'bot');
|
|
}
|
|
|
|
saveMessage(query, 'user');
|
|
messageInput.value = '';
|
|
localStorage.removeItem('messageDraft');
|
|
isWaitingResponse = false;
|
|
scrollToBottom();
|
|
});
|
|
|
|
|
|
|
|
function saveMessage(text, sender) {
|
|
if (!currentChatId) {
|
|
currentChatId = Date.now().toString();
|
|
chats.push({ id: currentChatId, messages: [] });
|
|
}
|
|
const chat = chats.find(c => c.id === currentChatId);
|
|
chat.messages.push({ id: Date.now().toString(), text, sender, timestamp: new Date().toLocaleTimeString(), isPinned: false, reactions: '' });
|
|
saveChats();
|
|
renderChatHistory();
|
|
}
|
|
|
|
function saveChats() {
|
|
localStorage.setItem('chats', JSON.stringify(chats));
|
|
}
|
|
|
|
|
|
function scrollToBottom() {
|
|
chatContainer.scrollTop = chatContainer.scrollHeight;
|
|
}
|
|
|
|
function showTypingIndicator() {
|
|
const typingDiv = document.createElement('div');
|
|
typingDiv.id = 'typing-indicator';
|
|
typingDiv.className = 'typing';
|
|
typingDiv.innerHTML = '<span></span><span></span><span></span>';
|
|
messagesContainer.appendChild(typingDiv);
|
|
scrollToBottom();
|
|
}
|
|
|
|
function removeTypingIndicator() {
|
|
qs('#typing-indicator')?.remove();
|
|
}
|
|
|
|
function showNotification(text, type = 'success') {
|
|
const notif = document.createElement('div');
|
|
notif.className = `notification fixed bottom-4 left-4 p-3 rounded-lg text-white ${type === 'success' ? 'bg-green-500' : 'bg-red-500'}`;
|
|
notif.textContent = text;
|
|
document.body.appendChild(notif);
|
|
setTimeout(() => notif.remove(), 3000);
|
|
}
|
|
|
|
|
|
function addMessage(text, sender, id = Date.now().toString(), isPinned = false) {
|
|
const isSameSender = sender === lastSender;
|
|
const div = document.createElement('div');
|
|
div.className = `message chat-group ${sender === 'user' ? 'user-message' : 'bot-message'}${isSameSender ? ' mt-1' : ''}${isPinned ? ' pinned-message' : ''}`;
|
|
div.dataset.id = id;
|
|
div.innerHTML = `
|
|
<img src="${sender === 'user' ? 'https://img.icons8.com/color/48/000000/user.png' : 'https://img.icons8.com/color/48/000000/bot.png'}" class="w-8 h-8 rounded-full ${isSameSender && !isPinned ? 'invisible' : ''}">
|
|
<div class="flex-1">
|
|
<div class="flex justify-between items-baseline">
|
|
<span class="text-sm font-semibold ${sender === 'user' ? 'text-white' : 'text-gray-700 dark:text-gray-300'}">${sender === 'user' ? currentUser : 'Bot'}</span>
|
|
<span class="text-xs text-gray-400">${new Date().toLocaleTimeString()}</span>
|
|
</div>
|
|
<div class="break-words">${text}</div>
|
|
</div>`;
|
|
messagesContainer.appendChild(div);
|
|
lastSender = sender;
|
|
scrollToBottom();
|
|
}
|
|
|
|
|
|
function renderChatHistory(query = '') {
|
|
chatHistoryContainer.innerHTML = '';
|
|
chats.filter(chat => !query || chat.messages.some(m => m.text.toLowerCase().includes(query)))
|
|
.forEach(chat => {
|
|
const last = chat.messages.at(-1);
|
|
const item = document.createElement('div');
|
|
item.className = `p-3 rounded-lg flex justify-between items-center cursor-pointer ${currentChatId === chat.id ? 'bg-indigo-100' : 'bg-gray-100'} hover:bg-indigo-50`;
|
|
item.innerHTML = `
|
|
<div class="flex-1" onclick="loadChat('${chat.id}')">
|
|
<div class="text-sm font-semibold text-gray-800">${chat.messages[0]?.text.substring(0, 25) || 'Yeni Sohbet'}...</div>
|
|
<div class="text-xs text-gray-500">${last?.timestamp || ''}</div>
|
|
</div>
|
|
<button onclick="deleteChat('${chat.id}')" class="text-red-500 hover:text-red-700"><i class="fas fa-trash"></i></button>
|
|
`;
|
|
chatHistoryContainer.appendChild(item);
|
|
});
|
|
}
|
|
|
|
|
|
window.loadChat = function(id) {
|
|
currentChatId = id;
|
|
const chat = chats.find(c => c.id === id);
|
|
messagesContainer.innerHTML = '';
|
|
lastSender = null;
|
|
chat.messages.forEach(msg => addMessage(msg.text, msg.sender, msg.id, msg.isPinned));
|
|
scrollToBottom();
|
|
sidebar.classList.add('hidden');
|
|
};
|
|
|
|
window.deleteChat = function(id) {
|
|
chats = chats.filter(c => c.id !== id);
|
|
saveChats();
|
|
renderChatHistory();
|
|
if (currentChatId === id) {
|
|
messagesContainer.innerHTML = '';
|
|
currentChatId = null;
|
|
lastSender = null;
|
|
}
|
|
showNotification('Sohbet silindi!', 'success');
|
|
};
|
|
|
|
|
|
function addEmoji(emoji) {
|
|
messageInput.value += emoji;
|
|
messageInput.focus();
|
|
}
|
|
|
|
function quickReply(text) {
|
|
messageInput.value = text;
|
|
chatForm.dispatchEvent(new Event('submit'));
|
|
}
|
|
|
|
|
|
initializeSettings();
|
|
renderChatHistory();
|
|
|