iamseyhmus7's picture
Upload 17 files
70d956a verified
// === 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();