Spaces:
Running
Running
| <html lang="cs"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <title>LuxAI Chat</title> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> | |
| <script src="https://unpkg.com/feather-icons"></script> | |
| <link rel="stylesheet" href="style.css"> | |
| <script> | |
| tailwind.config = { | |
| theme: { | |
| extend: { | |
| colors: { | |
| primary: { | |
| 50: '#f0fdfa', | |
| 100: '#ccfbf1', | |
| 500: '#10a37f', | |
| 600: '#0d9488', | |
| 700: '#0f766e', | |
| }, | |
| dark: { | |
| 800: '#1e293b', | |
| 900: '#0f172a', | |
| } | |
| } | |
| } | |
| } | |
| } | |
| </script> | |
| </head> | |
| <body class="bg-gray-50 dark:bg-dark-900 text-gray-900 dark:text-gray-100 h-screen flex flex-col"> | |
| <!-- Header --> | |
| <header class="bg-gradient-to-r from-purple-500 to-pink-500 dark:from-purple-700 dark:to-pink-700 h-14 px-4 flex items-center justify-between shadow-lg"> | |
| <div class="flex items-center space-x-2"> | |
| <div class="w-8 h-8 rounded-full bg-white flex items-center justify-center"> | |
| <i data-feather="cpu" class="text-purple-600 w-4 h-4"></i> | |
| </div> | |
| <h1 class="font-bold text-lg text-white">Rainbow AI</h1> | |
| </div> | |
| <button id="newChat" class="flex items-center space-x-1 bg-white/20 hover:bg-white/30 text-white border border-white/30 rounded-lg px-3 py-1.5 text-sm transition-colors backdrop-blur-sm"> | |
| <i data-feather="plus" class="w-4 h-4"></i> | |
| <span>Nový chat</span> | |
| </button> | |
| </header> | |
| <!-- Chat Area --> | |
| <main class="flex-1 overflow-y-auto p-4 md:p-6"> | |
| <div class="max-w-3xl mx-auto space-y-4" id="chat"> | |
| <div class="text-center text-gray-500 dark:text-gray-400 mt-12"> | |
| <i data-feather="message-square" class="w-12 h-12 mx-auto mb-4 opacity-30"></i> | |
| <p class="text-lg">Začni nový rozhovor</p> | |
| </div> | |
| </div> | |
| </main> | |
| <!-- Input Area --> | |
| <form id="chatForm" class="bg-gradient-to-r from-blue-500/10 to-purple-500/10 dark:from-blue-700/20 dark:to-purple-700/20 border-t border-gray-200/50 dark:border-gray-700/50 px-4 py-3 backdrop-blur-sm"> | |
| <div class="max-w-3xl mx-auto"> | |
| <div class="flex items-center gap-2 mb-2"> | |
| <select id="modelSelect" class="bg-white/80 dark:bg-dark-800/80 border border-gray-200/50 dark:border-gray-700/50 rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-purple-500 shadow-sm"> | |
| <option value="gpt-a">GPT-A</option> | |
| <option value="gpt2">GPT-2</option> | |
| </select> | |
| <div class="text-xs text-gray-500 dark:text-gray-400">Press Shift+Enter for new line</div> | |
| </div> | |
| <div class="flex items-end gap-2"> | |
| <div class="flex-1 relative"> | |
| <textarea id="input" rows="2" placeholder="Napiš zprávu…" | |
| class="w-full bg-white/80 dark:bg-dark-700/80 border border-gray-200/50 dark:border-gray-600/50 rounded-xl px-4 py-3 pr-10 focus:outline-none focus:ring-2 focus:ring-purple-500 resize-none shadow-sm"></textarea> | |
| <button type="submit" class="absolute right-3 bottom-3 bg-gradient-to-r from-purple-500 to-pink-500 text-white p-1 rounded-full hover:opacity-90 transition-opacity shadow-md"> | |
| <i data-feather="arrow-up" class="w-5 h-5"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </form> | |
| <script> | |
| // Rainbow color animation for empty state icon | |
| function animateRainbowIcon() { | |
| const icon = document.querySelector('.empty i'); | |
| if (icon) { | |
| let hue = 0; | |
| setInterval(() => { | |
| hue = (hue + 1) % 360; | |
| icon.style.color = `hsl(${hue}, 100%, 70%)`; | |
| }, 50); | |
| } | |
| } | |
| const MODELS = { | |
| "gpt-a": { | |
| name: "GPT-A", | |
| url: "https://luxopes-gpt-a.hf.space/generate" | |
| }, | |
| "gpt2": { | |
| name: "GPT-2", | |
| url: "https://luxopes-gpt2-backend.hf.space/generate" | |
| } | |
| }; | |
| let currentModel = "gpt-a"; | |
| const chat = document.getElementById("chat"); | |
| const input = document.getElementById("input"); | |
| const form = document.getElementById("chatForm"); | |
| function appendMessage(text, cls, model=null) { | |
| const div = document.createElement("div"); | |
| div.className = cls === "user" | |
| ? "bg-gradient-to-r from-purple-500 to-pink-500 text-white px-5 py-4 rounded-xl rounded-tr-none max-w-[85%] ml-auto shadow-lg" | |
| : "bg-white/90 dark:bg-dark-700/90 border border-gray-200/50 dark:border-gray-600/50 px-5 py-4 rounded-xl rounded-tl-none max-w-[85%] shadow-lg backdrop-blur-sm"; | |
| if (model) { | |
| const modelIndicator = document.createElement("div"); | |
| modelIndicator.className = "text-xs text-gray-500 dark:text-gray-400 mb-1"; | |
| modelIndicator.textContent = model; | |
| div.appendChild(modelIndicator); | |
| } | |
| const content = document.createElement("div"); | |
| content.className = cls === "user" ? "text-white" : "text-gray-800 dark:text-gray-100"; | |
| content.textContent = text; | |
| div.appendChild(content); | |
| chat.appendChild(div); | |
| chat.scrollTop = chat.scrollHeight; | |
| document.querySelector(".empty")?.remove(); | |
| return div; | |
| } | |
| form.addEventListener("submit", async e => { | |
| e.preventDefault(); | |
| const msg = input.value.trim(); | |
| if (!msg) return; | |
| appendMessage(msg, "user"); | |
| input.value = ""; | |
| input.disabled = true; | |
| const bot = appendMessage( | |
| `${MODELS[currentModel].name} přemýšlí…`, | |
| "bot", | |
| MODELS[currentModel].name | |
| ); | |
| bot.classList.add("opacity-80"); | |
| try { | |
| const res = await fetch(MODELS[currentModel].url, { | |
| method: "POST", | |
| headers: { "Content-Type": "application/json" }, | |
| body: JSON.stringify({ user_input: msg, model: currentModel }) | |
| }); | |
| const data = await res.json(); | |
| bot.classList.remove("opacity-80"); | |
| bot.lastChild.textContent = data.response || "Chyba odpovědi"; | |
| } catch (e) { | |
| bot.classList.remove("opacity-80"); | |
| bot.lastChild.textContent = "Chyba připojení"; | |
| } | |
| input.disabled = false; | |
| input.focus(); | |
| }); | |
| document.getElementById("modelSelect").onchange = e => { | |
| currentModel = e.target.value; | |
| appendMessage(`Přepnuto na ${MODELS[currentModel].name}`, "bot", "System"); | |
| }; | |
| document.getElementById("newChat").onclick = () => { | |
| chat.innerHTML = ` | |
| <div class="text-center text-gray-500 dark:text-gray-400 mt-12"> | |
| <i data-feather="message-square" class="w-12 h-12 mx-auto mb-4 opacity-30"></i> | |
| <p class="text-lg">Začni nový rozhovor</p> | |
| </div> | |
| `; | |
| feather.replace(); | |
| input.focus(); | |
| }; | |
| input.addEventListener("keydown", e => { | |
| if (e.key === "Enter" && !e.shiftKey) { | |
| e.preventDefault(); | |
| form.requestSubmit(); | |
| } | |
| }); | |
| feather.replace(); | |
| animateRainbowIcon(); | |
| </script> | |
| <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script> | |
| </body> | |
| </html> |