Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>QAdmar AI - Intelligent Chat Assistant</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| /* Custom scrollbar */ | |
| ::-webkit-scrollbar { | |
| width: 8px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: #f1f1f1; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: #888; | |
| border-radius: 4px; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: #555; | |
| } | |
| /* Chat bubble animations */ | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(10px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .message-animation { | |
| animation: fadeIn 0.3s ease-out; | |
| } | |
| /* Typing indicator */ | |
| .typing-indicator { | |
| display: inline-flex; | |
| align-items: center; | |
| } | |
| .typing-dot { | |
| width: 8px; | |
| height: 8px; | |
| background-color: #6b7280; | |
| border-radius: 50%; | |
| margin: 0 2px; | |
| animation: typingAnimation 1.4s infinite ease-in-out; | |
| } | |
| .typing-dot:nth-child(1) { | |
| animation-delay: 0s; | |
| } | |
| .typing-dot:nth-child(2) { | |
| animation-delay: 0.2s; | |
| } | |
| .typing-dot:nth-child(3) { | |
| animation-delay: 0.4s; | |
| } | |
| @keyframes typingAnimation { | |
| 0%, 60%, 100% { transform: translateY(0); } | |
| 30% { transform: translateY(-5px); } | |
| } | |
| /* Dark mode toggle */ | |
| .dark-mode-toggle { | |
| transition: all 0.3s ease; | |
| } | |
| .dark-mode-toggle:hover { | |
| transform: rotate(30deg); | |
| } | |
| /* RTL support */ | |
| .rtl { | |
| direction: rtl; | |
| text-align: right; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50 dark:bg-gray-900 transition-colors duration-300 min-h-screen flex flex-col"> | |
| <!-- Header --> | |
| <header class="bg-indigo-600 dark:bg-indigo-800 text-white shadow-md"> | |
| <div class="container mx-auto px-4 py-3 flex justify-between items-center"> | |
| <div class="flex items-center space-x-3"> | |
| <div class="w-10 h-10 rounded-full bg-white dark:bg-gray-700 flex items-center justify-center"> | |
| <i class="fas fa-robot text-indigo-600 dark:text-indigo-300 text-xl"></i> | |
| </div> | |
| <h1 class="text-xl font-bold">QAdmar AI</h1> | |
| </div> | |
| <div class="flex items-center space-x-4"> | |
| <button id="languageToggle" class="px-3 py-1 bg-white dark:bg-gray-700 text-indigo-600 dark:text-indigo-300 rounded-full text-sm font-medium hover:bg-indigo-100 dark:hover:bg-gray-600 transition"> | |
| العربية | |
| </button> | |
| <button id="darkModeToggle" class="dark-mode-toggle text-white hover:text-indigo-200"> | |
| <i class="fas fa-moon text-xl"></i> | |
| </button> | |
| <button id="newChatBtn" class="px-3 py-1 bg-white dark:bg-gray-700 text-indigo-600 dark:text-indigo-300 rounded-full text-sm font-medium hover:bg-indigo-100 dark:hover:bg-gray-600 transition flex items-center"> | |
| <i class="fas fa-plus mr-1"></i> New Chat | |
| </button> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Main Chat Area --> | |
| <main class="flex-1 container mx-auto px-4 py-6 flex flex-col max-w-4xl"> | |
| <!-- Welcome message --> | |
| <div id="welcomeMessage" class="text-center mb-8 message-animation"> | |
| <div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6 inline-block max-w-2xl"> | |
| <h2 class="text-2xl font-bold text-indigo-600 dark:text-indigo-400 mb-2">Welcome to QAdmar AI</h2> | |
| <p class="text-gray-600 dark:text-gray-300">I'm your intelligent assistant. Ask me anything, and I'll do my best to help you!</p> | |
| <div class="mt-4 grid grid-cols-1 md:grid-cols-3 gap-3"> | |
| <button class="suggestion-btn px-4 py-2 bg-indigo-100 dark:bg-gray-700 text-indigo-700 dark:text-indigo-300 rounded-lg text-sm hover:bg-indigo-200 dark:hover:bg-gray-600 transition"> | |
| "Explain quantum computing" | |
| </button> | |
| <button class="suggestion-btn px-4 py-2 bg-indigo-100 dark:bg-gray-700 text-indigo-700 dark:text-indigo-300 rounded-lg text-sm hover:bg-indigo-200 dark:hover:bg-gray-600 transition"> | |
| "Write a poem about AI" | |
| </button> | |
| <button class="suggestion-btn px-4 py-2 bg-indigo-100 dark:bg-gray-700 text-indigo-700 dark:text-indigo-300 rounded-lg text-sm hover:bg-indigo-200 dark:hover:bg-gray-600 transition"> | |
| "How to learn JavaScript?" | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Chat messages container --> | |
| <div id="chatContainer" class="flex-1 overflow-y-auto mb-4 space-y-4 hidden"> | |
| <!-- Messages will be added here dynamically --> | |
| </div> | |
| <!-- Typing indicator (hidden by default) --> | |
| <div id="typingIndicator" class="mb-4 hidden"> | |
| <div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-4 max-w-xs md:max-w-md"> | |
| <div class="typing-indicator"> | |
| <span class="typing-dot"></span> | |
| <span class="typing-dot"></span> | |
| <span class="typing-dot"></span> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| <!-- Input Area --> | |
| <div class="bg-white dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700 py-4 sticky bottom-0"> | |
| <div class="container mx-auto px-4 max-w-4xl"> | |
| <form id="chatForm" class="flex items-end space-x-2"> | |
| <div class="flex-1 relative"> | |
| <textarea | |
| id="messageInput" | |
| rows="1" | |
| class="w-full px-4 py-3 pr-12 bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 rounded-lg border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 resize-none" | |
| placeholder="Type your message here..." | |
| style="min-height: 50px; max-height: 150px;"></textarea> | |
| <button | |
| type="button" | |
| id="sendButton" | |
| class="absolute right-3 bottom-3 bg-indigo-600 text-white rounded-full p-2 hover:bg-indigo-700 transition disabled:opacity-50 disabled:cursor-not-allowed" | |
| disabled> | |
| <i class="fas fa-paper-plane"></i> | |
| </button> | |
| </div> | |
| <button | |
| type="button" | |
| id="voiceButton" | |
| class="bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-full p-3 hover:bg-gray-300 dark:hover:bg-gray-600 transition"> | |
| <i class="fas fa-microphone"></i> | |
| </button> | |
| </form> | |
| <p class="text-xs text-gray-500 dark:text-gray-400 mt-2 text-center"> | |
| QAdmar AI may produce inaccurate information. Consider verifying important information. | |
| </p> | |
| </div> | |
| </div> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // DOM Elements | |
| const chatForm = document.getElementById('chatForm'); | |
| const messageInput = document.getElementById('messageInput'); | |
| const sendButton = document.getElementById('sendButton'); | |
| const voiceButton = document.getElementById('voiceButton'); | |
| const chatContainer = document.getElementById('chatContainer'); | |
| const welcomeMessage = document.getElementById('welcomeMessage'); | |
| const typingIndicator = document.getElementById('typingIndicator'); | |
| const darkModeToggle = document.getElementById('darkModeToggle'); | |
| const languageToggle = document.getElementById('languageToggle'); | |
| const newChatBtn = document.getElementById('newChatBtn'); | |
| const suggestionBtns = document.querySelectorAll('.suggestion-btn'); | |
| // State variables | |
| let isRTL = false; | |
| let isDarkMode = false; | |
| let chatHistory = []; | |
| // Initialize | |
| checkDarkModePreference(); | |
| // Event Listeners | |
| messageInput.addEventListener('input', handleInputChange); | |
| chatForm.addEventListener('submit', handleSubmit); | |
| sendButton.addEventListener('click', handleSubmit); | |
| voiceButton.addEventListener('click', handleVoiceInput); | |
| darkModeToggle.addEventListener('click', toggleDarkMode); | |
| languageToggle.addEventListener('click', toggleLanguage); | |
| newChatBtn.addEventListener('click', startNewChat); | |
| suggestionBtns.forEach(btn => btn.addEventListener('click', handleSuggestionClick)); | |
| // Functions | |
| function handleInputChange() { | |
| // Auto-resize textarea | |
| messageInput.style.height = 'auto'; | |
| messageInput.style.height = (messageInput.scrollHeight) + 'px'; | |
| // Enable/disable send button based on input | |
| sendButton.disabled = messageInput.value.trim() === ''; | |
| } | |
| function handleSubmit(e) { | |
| e.preventDefault(); | |
| const message = messageInput.value.trim(); | |
| if (message) { | |
| // Add user message to chat | |
| addMessage(message, 'user'); | |
| // Clear input | |
| messageInput.value = ''; | |
| messageInput.style.height = 'auto'; | |
| sendButton.disabled = true; | |
| // Hide welcome message if it's the first message | |
| if (welcomeMessage.style.display !== 'none') { | |
| welcomeMessage.classList.add('hidden'); | |
| chatContainer.classList.remove('hidden'); | |
| } | |
| // Show typing indicator | |
| typingIndicator.classList.remove('hidden'); | |
| // Simulate AI response after a delay | |
| setTimeout(() => { | |
| typingIndicator.classList.add('hidden'); | |
| const aiResponse = generateAIResponse(message); | |
| addMessage(aiResponse, 'ai'); | |
| // Scroll to bottom | |
| chatContainer.scrollTop = chatContainer.scrollHeight; | |
| }, 1000 + Math.random() * 2000); // Random delay between 1-3 seconds | |
| } | |
| } | |
| function addMessage(content, sender) { | |
| const messageDiv = document.createElement('div'); | |
| messageDiv.classList.add('message-animation'); | |
| if (sender === 'user') { | |
| messageDiv.innerHTML = ` | |
| <div class="flex justify-end"> | |
| <div class="bg-indigo-600 text-white rounded-l-lg rounded-br-lg shadow-md p-4 max-w-xs md:max-w-md lg:max-w-lg"> | |
| <p class="${isRTL ? 'rtl' : ''}">${content}</p> | |
| </div> | |
| </div> | |
| `; | |
| } else { | |
| messageDiv.innerHTML = ` | |
| <div class="flex justify-start"> | |
| <div class="bg-white dark:bg-gray-800 rounded-r-lg rounded-bl-lg shadow-md p-4 max-w-xs md:max-w-md lg:max-w-lg"> | |
| <p class="${isRTL ? 'rtl' : ''}">${content}</p> | |
| <div class="mt-2 flex justify-end space-x-2 text-xs text-gray-500 dark:text-gray-400"> | |
| <button class="copy-btn hover:text-indigo-600 dark:hover:text-indigo-400" title="Copy"> | |
| <i class="fas fa-copy"></i> | |
| </button> | |
| <button class="regenerate-btn hover:text-indigo-600 dark:hover:text-indigo-400" title="Regenerate"> | |
| <i class="fas fa-sync-alt"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| } | |
| chatContainer.appendChild(messageDiv); | |
| // Add copy and regenerate functionality to new AI messages | |
| if (sender === 'ai') { | |
| const copyBtn = messageDiv.querySelector('.copy-btn'); | |
| const regenerateBtn = messageDiv.querySelector('.regenerate-btn'); | |
| copyBtn.addEventListener('click', () => { | |
| navigator.clipboard.writeText(content); | |
| copyBtn.innerHTML = '<i class="fas fa-check"></i>'; | |
| setTimeout(() => { | |
| copyBtn.innerHTML = '<i class="fas fa-copy"></i>'; | |
| }, 2000); | |
| }); | |
| regenerateBtn.addEventListener('click', () => { | |
| messageDiv.remove(); | |
| typingIndicator.classList.remove('hidden'); | |
| setTimeout(() => { | |
| typingIndicator.classList.add('hidden'); | |
| const newResponse = generateAIResponse(chatHistory[chatHistory.length - 1].content); | |
| addMessage(newResponse, 'ai'); | |
| }, 1000 + Math.random() * 2000); | |
| }); | |
| } | |
| // Add to chat history | |
| chatHistory.push({ content, sender }); | |
| // Scroll to bottom | |
| chatContainer.scrollTop = chatContainer.scrollHeight; | |
| } | |
| function generateAIResponse(userMessage) { | |
| // This is a mock response generator - in a real app, you'd call your AI API here | |
| const responses = [ | |
| `I understand you're asking about "${userMessage}". While I don't have real-time data, I can provide general information on this topic.`, | |
| `That's an interesting question about "${userMessage}". Here's what I know: [AI-generated response would appear here in a real implementation].`, | |
| `Regarding "${userMessage}", my current knowledge suggests that [AI would generate a detailed response here]. Would you like me to elaborate?`, | |
| `I've analyzed your query about "${userMessage}". Based on my training data, here's the most relevant information I can provide.` | |
| ]; | |
| const arabicResponses = [ | |
| `أنا أفهم أنك تسأل عن "${userMessage}". بينما لا أملك بيانات في الوقت الحقيقي، يمكنني تقديم معلومات عامة حول هذا الموضوع.`, | |
| `هذا سؤال مثير للاهتمام حول "${userMessage}". إليك ما أعرفه: [سيظهر هنا رد تم إنشاؤه بواسطة الذكاء الاصطناعي في التنفيذ الحقيقي].`, | |
| `بخصوص "${userMessage}"، تشير معرفتي الحالية إلى أن [سيولد الذكاء الاصطناعي ردًا مفصلاً هنا]. هل تريد مني أن أشرح أكثر؟`, | |
| `لقد قمت بتحليل استفسارك حول "${userMessage}". بناءً على بياناتي التدريبية، إليك المعلومات الأكثر صلة التي يمكنني تقديمها.` | |
| ]; | |
| return isRTL | |
| ? arabicResponses[Math.floor(Math.random() * arabicResponses.length)] | |
| : responses[Math.floor(Math.random() * responses.length)]; | |
| } | |
| function handleVoiceInput() { | |
| voiceButton.innerHTML = '<i class="fas fa-microphone-slash"></i>'; | |
| voiceButton.classList.remove('bg-gray-200', 'dark:bg-gray-700'); | |
| voiceButton.classList.add('bg-red-500', 'text-white'); | |
| // In a real app, this would use the Web Speech API | |
| setTimeout(() => { | |
| const spokenText = isRTL | |
| ? "هذه ميزة التعرف على الصوت. في التطبيق الحقيقي، سيقوم هذا بالاستماع إلى كلامك." | |
| : "This is voice input. In a real app, this would listen to your speech."; | |
| messageInput.value = spokenText; | |
| handleInputChange(); | |
| voiceButton.innerHTML = '<i class="fas fa-microphone"></i>'; | |
| voiceButton.classList.remove('bg-red-500', 'text-white'); | |
| voiceButton.classList.add('bg-gray-200', 'dark:bg-gray-700'); | |
| }, 2000); | |
| } | |
| function toggleDarkMode() { | |
| isDarkMode = !isDarkMode; | |
| document.documentElement.classList.toggle('dark', isDarkMode); | |
| localStorage.setItem('darkMode', isDarkMode); | |
| darkModeToggle.innerHTML = isDarkMode | |
| ? '<i class="fas fa-sun text-xl"></i>' | |
| : '<i class="fas fa-moon text-xl"></i>'; | |
| } | |
| function checkDarkModePreference() { | |
| if (localStorage.getItem('darkMode') === 'true' || | |
| (!localStorage.getItem('darkMode') && window.matchMedia('(prefers-color-scheme: dark)').matches)) { | |
| isDarkMode = true; | |
| document.documentElement.classList.add('dark'); | |
| darkModeToggle.innerHTML = '<i class="fas fa-sun text-xl"></i>'; | |
| } | |
| } | |
| function toggleLanguage() { | |
| isRTL = !isRTL; | |
| languageToggle.textContent = isRTL ? 'English' : 'العربية'; | |
| // Update all existing messages | |
| const messages = document.querySelectorAll('#chatContainer p'); | |
| messages.forEach(msg => { | |
| msg.classList.toggle('rtl', isRTL); | |
| }); | |
| // Update input placeholder | |
| messageInput.placeholder = isRTL ? 'اكتب رسالتك هنا...' : 'Type your message here...'; | |
| // Update welcome message if visible | |
| if (!welcomeMessage.classList.contains('hidden')) { | |
| welcomeMessage.querySelector('p').textContent = isRTL | |
| ? 'أنا مساعدك الذكي. اسألني عن أي شيء، وسأبذل قصارى جهدي لمساعدتك!' | |
| : 'I\'m your intelligent assistant. Ask me anything, and I\'ll do my best to help you!'; | |
| const suggestionBtns = welcomeMessage.querySelectorAll('.suggestion-btn'); | |
| if (isRTL) { | |
| suggestionBtns[0].textContent = '"اشرح الحوسبة الكمومية"'; | |
| suggestionBtns[1].textContent = '"اكتب قصيدة عن الذكاء الاصطناعي"'; | |
| suggestionBtns[2].textContent = '"كيف أتعلم جافا سكريبت؟"'; | |
| } else { | |
| suggestionBtns[0].textContent = '"Explain quantum computing"'; | |
| suggestionBtns[1].textContent = '"Write a poem about AI"'; | |
| suggestionBtns[2].textContent = '"How to learn JavaScript?"'; | |
| } | |
| } | |
| } | |
| function startNewChat() { | |
| chatContainer.innerHTML = ''; | |
| chatHistory = []; | |
| welcomeMessage.classList.remove('hidden'); | |
| chatContainer.classList.add('hidden'); | |
| } | |
| function handleSuggestionClick(e) { | |
| messageInput.value = e.target.textContent.trim().replace(/^"|"$/g, ''); | |
| handleInputChange(); | |
| } | |
| }); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=HAMZACROSS1/ai" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |