// Shared JavaScript across all pages class ChatApp { constructor() { this.apiKey = localStorage.getItem('openai-api-key') || ''; this.messages = []; this.init(); } init() { this.bindEvents(); this.loadApiKey(); this.updateApiKeyDisplay(); } bindEvents() { document.getElementById('send-button').addEventListener('click', () => this.sendMessage()); document.getElementById('message-input').addEventListener('keypress', (e) => { if (e.key === 'Enter') this.sendMessage(); }); document.getElementById('save-api-key').addEventListener('click', () => this.saveApiKey()); } loadApiKey() { const savedKey = localStorage.getItem('openai-api-key'); if (savedKey) { this.apiKey = savedKey; document.getElementById('api-key-input').value = savedKey; } } saveApiKey() { const keyInput = document.getElementById('api-key-input'); if (keyInput.value.trim()) { this.apiKey = keyInput.value.trim(); localStorage.setItem('openai-api-key', this.apiKey); this.updateApiKeyDisplay(); this.showNotification('API key saved successfully!', 'success'); } else { this.showNotification('Please enter a valid API key', 'error'); } } updateApiKeyDisplay() { const keyInput = document.getElementById('api-key-input'); if (this.apiKey) { keyInput.placeholder = 'API key saved'; } else { keyInput.placeholder = 'Enter your OpenAI API key'; } } async sendMessage() { const input = document.getElementById('message-input'); const message = input.value.trim(); if (!message) return; if (!this.apiKey) { this.showNotification('Please enter your OpenAI API key first', 'error'); return; } // Add user message to UI this.addMessage(message, 'user'); input.value = ''; // Show typing indicator const typingIndicator = this.addTypingIndicator(); try { const response = await this.callOpenAI(message); // Remove typing indicator typingIndicator.remove(); // Add assistant response this.addMessage(response, 'assistant'); } catch (error) { // Remove typing indicator typingIndicator.remove(); this.addMessage('Sorry, I encountered an error. Please try again.', 'assistant'); console.error('Error:', error); } } addMessage(content, sender) { const messagesContainer = document.getElementById('messages'); const messageDiv = document.createElement('div'); messageDiv.className = `message ${sender}-message rounded-lg p-4 max-w-[80%] ${sender === 'user' ? 'ml-auto' : ''}`; if (sender === 'user') { messageDiv.innerHTML = `
You
${content}
`; } else { messageDiv.innerHTML = `
Assistant
${content}
`; } messagesContainer.appendChild(messageDiv); messagesContainer.scrollTop = messagesContainer.scrollHeight; return messageDiv; } addTypingIndicator() { const messagesContainer = document.getElementById('messages'); const typingDiv = document.createElement('div'); typingDiv.className = 'message assistant-message rounded-lg p-4'; typingDiv.innerHTML = `
Assistant
`; messagesContainer.appendChild(typingDiv); messagesContainer.scrollTop = messagesContainer.scrollHeight; return typingDiv; } async callOpenAI(message) { const response = await fetch('https://api.openai.com/v1/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.apiKey}` }, body: JSON.stringify({ model: 'gpt-3.5-turbo', messages: [ { role: 'system', content: 'You are a helpful assistant.' }, { role: 'user', content: message } ], temperature: 0.7 }) }); if (!response.ok) { if (response.status === 401) { throw new Error('Invalid API key. Please check your API key and try again.'); } else if (response.status === 429) { throw new Error('Rate limit exceeded. Please wait before sending another request.'); } else { throw new Error(`API request failed with status ${response.status}`); } } const data = await response.json(); return data.choices[0].message.content; } showNotification(message, type) { // Remove existing notifications const existing = document.querySelector('.notification'); if (existing) existing.remove(); const notification = document.createElement('div'); notification.className = `notification fixed top-4 right-4 px-6 py-4 rounded-lg shadow-lg z-50 ${ type === 'success' ? 'bg-green-600' : 'bg-red-600' } text-white`; notification.textContent = message; document.body.appendChild(notification); setTimeout(() => { notification.remove(); }, 3000); } } // Initialize the app when DOM is loaded document.addEventListener('DOMContentLoaded', () => { window.chatApp = new ChatApp(); });