Los-Angeles-Events / index.html
vishurdx's picture
Create index.html
16cc416 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LA Festival Guide AI</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
.typing-dot {
animation: typing 1.4s infinite ease-in-out both;
}
.typing-dot:nth-child(1) { animation-delay: -0.32s; }
.typing-dot:nth-child(2) { animation-delay: -0.16s; }
@keyframes typing {
0%, 80%, 100% { transform: scale(0); }
40% { transform: scale(1); }
}
</style>
</head>
<body class="bg-gray-100 h-screen flex flex-col items-center justify-center p-4">
<!-- Main Card -->
<div class="w-full max-w-2xl bg-white rounded-2xl shadow-xl overflow-hidden flex flex-col h-[80vh]">
<!-- Header -->
<div class="bg-gradient-to-r from-blue-600 to-purple-600 p-6 text-white">
<h1 class="text-2xl font-bold">🌴 LA Festival Guide</h1>
<p class="text-blue-100 text-sm">Ask about events, dates, and festivals in LA</p>
</div>
<!-- Chat Area -->
<div id="chat-box" class="flex-1 overflow-y-auto p-6 space-y-4 bg-gray-50">
<!-- Bot Welcome Message -->
<div class="flex items-start">
<div class="bg-blue-100 p-3 rounded-lg rounded-tl-none max-w-[80%] text-gray-800">
Hello! I'm your LA events concierge. What are you looking for today?
</div>
</div>
</div>
<!-- Input Area -->
<div class="p-4 bg-white border-t border-gray-200">
<form id="chat-form" class="flex gap-2">
<input type="text" id="user-input"
class="flex-1 px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="e.g., Music festivals in August..." autocomplete="off">
<button type="submit"
class="bg-blue-600 text-white px-6 py-3 rounded-lg font-semibold hover:bg-blue-700 transition-colors">
Send
</button>
</form>
</div>
</div>
<script>
const chatBox = document.getElementById('chat-box');
const chatForm = document.getElementById('chat-form');
const userInput = document.getElementById('user-input');
function appendMessage(text, isUser) {
const div = document.createElement('div');
div.className = `flex ${isUser ? 'justify-end' : 'items-start'}`;
const bubble = document.createElement('div');
bubble.className = isUser
? 'bg-blue-600 text-white p-3 rounded-lg rounded-tr-none max-w-[80%]'
: 'bg-white border border-gray-200 p-3 rounded-lg rounded-tl-none max-w-[80%] text-gray-800 shadow-sm';
// Allow basic markdown-like formatting for bot
bubble.innerHTML = isUser ? text : text.replace(/\n/g, '<br>');
div.appendChild(bubble);
chatBox.appendChild(div);
chatBox.scrollTop = chatBox.scrollHeight;
}
function showTyping() {
const div = document.createElement('div');
div.id = 'typing-indicator';
div.className = 'flex items-start';
div.innerHTML = `
<div class="bg-gray-200 p-3 rounded-lg rounded-tl-none flex space-x-1">
<div class="w-2 h-2 bg-gray-500 rounded-full typing-dot"></div>
<div class="w-2 h-2 bg-gray-500 rounded-full typing-dot"></div>
<div class="w-2 h-2 bg-gray-500 rounded-full typing-dot"></div>
</div>
`;
chatBox.appendChild(div);
chatBox.scrollTop = chatBox.scrollHeight;
}
function removeTyping() {
const el = document.getElementById('typing-indicator');
if (el) el.remove();
}
chatForm.addEventListener('submit', async (e) => {
e.preventDefault();
const message = userInput.value.trim();
if (!message) return;
// 1. Show User Message
appendMessage(message, true);
userInput.value = '';
showTyping();
try {
// 2. Call Python Backend
const response = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: message })
});
const data = await response.json();
// 3. Show Bot Response
removeTyping();
if (response.ok) {
appendMessage(data.response, false);
} else {
appendMessage("⚠️ Error: " + (data.detail || "Failed to fetch"), false);
}
} catch (err) {
removeTyping();
appendMessage("⚠️ Network error. Please try again.", false);
console.error(err);
}
});
</script>
</body>
</html>