|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>Lux - AI 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> |
|
|
.chat-message.user { |
|
|
animation: slideInLeft 0.3s ease-out; |
|
|
} |
|
|
.chat-message.ai { |
|
|
animation: slideInRight 0.3s ease-out; |
|
|
} |
|
|
@keyframes slideInLeft { |
|
|
from { transform: translateX(-20px); opacity: 0; } |
|
|
to { transform: translateX(0); opacity: 1; } |
|
|
} |
|
|
@keyframes slideInRight { |
|
|
from { transform: translateX(20px); opacity: 0; } |
|
|
to { transform: translateX(0); opacity: 1; } |
|
|
} |
|
|
.typing-indicator { |
|
|
display: inline-block; |
|
|
} |
|
|
.typing-indicator span { |
|
|
height: 8px; |
|
|
width: 8px; |
|
|
background: #9CA3AF; |
|
|
border-radius: 50%; |
|
|
display: inline-block; |
|
|
margin: 0 2px; |
|
|
animation: bounce 1.5s infinite ease-in-out; |
|
|
} |
|
|
.typing-indicator span:nth-child(2) { |
|
|
animation-delay: 0.2s; |
|
|
} |
|
|
.typing-indicator span:nth-child(3) { |
|
|
animation-delay: 0.4s; |
|
|
} |
|
|
@keyframes bounce { |
|
|
0%, 60%, 100% { transform: translateY(0); } |
|
|
30% { transform: translateY(-5px); } |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body class="bg-gray-100 min-h-screen"> |
|
|
<div class="container mx-auto max-w-4xl px-4 py-8"> |
|
|
|
|
|
<header class="flex items-center justify-between mb-8"> |
|
|
<div class="flex items-center space-x-3"> |
|
|
<div class="bg-indigo-600 text-white p-3 rounded-full"> |
|
|
<i class="fas fa-robot text-xl"></i> |
|
|
</div> |
|
|
<h1 class="text-2xl font-bold text-gray-800">Lux</h1> |
|
|
</div> |
|
|
<div class="text-sm text-gray-500"> |
|
|
Powered by OpenAI |
|
|
</div> |
|
|
</header> |
|
|
|
|
|
|
|
|
<div class="bg-white rounded-xl shadow-lg overflow-hidden"> |
|
|
|
|
|
<div class="bg-indigo-600 text-white px-6 py-4 flex items-center"> |
|
|
<div class="w-3 h-3 bg-green-400 rounded-full mr-2"></div> |
|
|
<div class="flex-1"> |
|
|
<h2 class="font-semibold">AI Assistant</h2> |
|
|
<p class="text-xs opacity-80">Always learning, always helpful</p> |
|
|
</div> |
|
|
<button class="text-white opacity-70 hover:opacity-100"> |
|
|
<i class="fas fa-ellipsis-v"></i> |
|
|
</button> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div id="chat" class="h-96 overflow-y-auto p-4 space-y-4 bg-gray-50"> |
|
|
|
|
|
<div class="chat-message ai flex"> |
|
|
<div class="flex-shrink-0 mr-3"> |
|
|
<div class="bg-indigo-100 text-indigo-800 rounded-full w-8 h-8 flex items-center justify-center"> |
|
|
<i class="fas fa-robot"></i> |
|
|
</div> |
|
|
</div> |
|
|
<div class="bg-white p-3 rounded-lg shadow-sm max-w-xs md:max-w-md lg:max-w-lg"> |
|
|
<p class="text-gray-800">Hello! I'm Lux, your AI assistant. How can I help you today?</p> |
|
|
<p class="text-xs text-gray-500 mt-1">Just now</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="border-t border-gray-200 p-4 bg-white"> |
|
|
<div class="flex items-center space-x-2"> |
|
|
<button class="text-gray-500 hover:text-indigo-600 p-2 rounded-full hover:bg-gray-100"> |
|
|
<i class="fas fa-paperclip"></i> |
|
|
</button> |
|
|
<input |
|
|
id="message" |
|
|
type="text" |
|
|
placeholder="Type your message here..." |
|
|
class="flex-1 border border-gray-300 rounded-full py-2 px-4 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent" |
|
|
onkeypress="if(event.keyCode === 13) sendMessage()" |
|
|
> |
|
|
<button |
|
|
id="sendButton" |
|
|
onclick="sendMessage()" |
|
|
class="bg-indigo-600 text-white p-2 rounded-full hover:bg-indigo-700 transition-colors" |
|
|
> |
|
|
<i class="fas fa-paper-plane"></i> |
|
|
</button> |
|
|
</div> |
|
|
<p class="text-xs text-gray-500 mt-2 text-center"> |
|
|
AI may produce inaccurate information. Consider verifying important facts. |
|
|
</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<script> |
|
|
let isTyping = false; |
|
|
|
|
|
async function sendMessage() { |
|
|
const messageInput = document.getElementById('message'); |
|
|
const msg = messageInput.value.trim(); |
|
|
if(!msg || isTyping) return; |
|
|
|
|
|
|
|
|
addMessage(msg, 'user'); |
|
|
messageInput.value = ''; |
|
|
|
|
|
|
|
|
showTypingIndicator(); |
|
|
isTyping = true; |
|
|
|
|
|
try { |
|
|
const res = await fetch('/chat', { |
|
|
method: 'POST', |
|
|
headers: { 'Content-Type': 'application/json' }, |
|
|
body: JSON.stringify({ message: msg }) |
|
|
}); |
|
|
|
|
|
const data = await res.json(); |
|
|
|
|
|
|
|
|
removeTypingIndicator(); |
|
|
|
|
|
|
|
|
addMessage(data.reply, 'ai'); |
|
|
isTyping = false; |
|
|
|
|
|
} catch (error) { |
|
|
console.error('Error:', error); |
|
|
removeTypingIndicator(); |
|
|
addMessage("Apologies, I'm experiencing some technical difficulties. Please check your internet connection and try again in a moment. If the issue persists, it might be on our end - we're working hard to keep things running smoothly!", 'ai'); |
|
|
isTyping = false; |
|
|
} |
|
|
} |
|
|
|
|
|
function addMessage(content, sender) { |
|
|
const chatContainer = document.getElementById('chat'); |
|
|
|
|
|
const messageDiv = document.createElement('div'); |
|
|
messageDiv.className = `chat-message ${sender} flex ${sender === 'user' ? 'justify-end' : ''}`; |
|
|
|
|
|
if (sender === 'user') { |
|
|
messageDiv.innerHTML = ` |
|
|
<div class="flex flex-col items-end"> |
|
|
<div class="bg-indigo-600 text-white p-3 rounded-lg shadow-sm max-w-xs md:max-w-md lg:max-w-lg"> |
|
|
<p class="text-white">${content}</p> |
|
|
</div> |
|
|
<p class="text-xs text-gray-500 mt-1">Just now</p> |
|
|
</div> |
|
|
`; |
|
|
} else { |
|
|
messageDiv.innerHTML = ` |
|
|
<div class="flex-shrink-0 mr-3"> |
|
|
<div class="bg-indigo-100 text-indigo-800 rounded-full w-8 h-8 flex items-center justify-center"> |
|
|
<i class="fas fa-robot"></i> |
|
|
</div> |
|
|
</div> |
|
|
<div class="bg-white p-3 rounded-lg shadow-sm max-w-xs md:max-w-md lg:max-w-lg"> |
|
|
<p class="text-gray-800">${content}</p> |
|
|
<p class="text-xs text-gray-500 mt-1">Just now</p> |
|
|
</div> |
|
|
`; |
|
|
} |
|
|
|
|
|
chatContainer.appendChild(messageDiv); |
|
|
chatContainer.scrollTop = chatContainer.scrollHeight; |
|
|
} |
|
|
|
|
|
function showTypingIndicator() { |
|
|
const chatContainer = document.getElementById('chat'); |
|
|
|
|
|
const typingDiv = document.createElement('div'); |
|
|
typingDiv.className = 'chat-message ai flex'; |
|
|
typingDiv.id = 'typing-indicator'; |
|
|
typingDiv.innerHTML = ` |
|
|
<div class="flex-shrink-0 mr-3"> |
|
|
<div class="bg-indigo-100 text-indigo-800 rounded-full w-8 h-8 flex items-center justify-center"> |
|
|
<i class="fas fa-robot"></i> |
|
|
</div> |
|
|
</div> |
|
|
<div class="bg-white p-3 rounded-lg shadow-sm"> |
|
|
<div class="typing-indicator"> |
|
|
<span></span> |
|
|
<span></span> |
|
|
<span></span> |
|
|
</div> |
|
|
</div> |
|
|
`; |
|
|
|
|
|
chatContainer.appendChild(typingDiv); |
|
|
chatContainer.scrollTop = chatContainer.scrollHeight; |
|
|
} |
|
|
|
|
|
function removeTypingIndicator() { |
|
|
const typingIndicator = document.getElementById('typing-indicator'); |
|
|
if (typingIndicator) { |
|
|
typingIndicator.remove(); |
|
|
} |
|
|
} |
|
|
</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=Abel222/lux" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
|
|
</html> |