Spaces:
Sleeping
Sleeping
// === Yardımcı Fonksiyonlar === | |
const qs = (selector) => document.querySelector(selector); | |
const qsa = (selector) => document.querySelectorAll(selector); | |
// === DOM Elemanları === | |
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') || ''; | |
// === Tema Renkleri === | |
const themeColors = { | |
default: '#4f46e5', blue: '#3b82f6', green: '#10b981', purple: '#8b5cf6', red: '#ef4444' | |
}; | |
// === Başlangıç Ayarları === | |
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'); | |
} | |
// === Tema Değiştirici === | |
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); | |
} | |
// === Karanlık Mod Değiştirici === | |
toggleThemeBtn?.addEventListener('click', () => { | |
document.body.classList.toggle('dark'); | |
localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light'); | |
}); | |
// === Event Listeners === | |
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'); | |
} | |
}); | |
// === Yeni Sohbet Başlat === | |
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'); | |
}); | |
// === Mesaj Gönderme === | |
let isWaitingResponse = false; | |
chatForm.addEventListener('submit', async (e) => { | |
e.preventDefault(); | |
if (isWaitingResponse) return; // Aynı anda birden fazla istek gönderilmesini engeller | |
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(); | |
}); | |
// === Mesajları Kaydetme === | |
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)); | |
} | |
// === Görsel İşlevler === | |
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); | |
} | |
// === Mesaj Ekleme === | |
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(); | |
} | |
// === Sohbet Geçmişi === | |
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); | |
}); | |
} | |
// === Global Fonksiyonlar === | |
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'); | |
}; | |
// === Emoji ve Quick Reply === | |
function addEmoji(emoji) { | |
messageInput.value += emoji; | |
messageInput.focus(); | |
} | |
function quickReply(text) { | |
messageInput.value = text; | |
chatForm.dispatchEvent(new Event('submit')); | |
} | |
// === Başlat === | |
initializeSettings(); | |
renderChatHistory(); | |