chatb / index.html
Ikyy's picture
Update index.html
ef5fdbc verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Glow Chatbot</title>
<style>
:root {
--neon-color: #0ff;
--bg-color: #0a0a0a;
--text-color: rgba(255,255,255,0.9);
}
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
background: var(--bg-color);
font-family: 'Courier New', monospace;
color: var(--text-color);
touch-action: manipulation;
height: 100vh;
overflow: hidden;
}
.chat-container {
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
background: radial-gradient(circle at center, #1a1a1a 0%, #0a0a0a 100%);
}
.chat-header {
padding: 1rem;
text-align: center;
background: rgba(0,0,0,0.3);
border-bottom: 2px solid var(--neon-color);
box-shadow: 0 0 15px var(--neon-color);
position: relative;
z-index: 2;
}
.chat-messages {
flex: 1;
overflow-y: auto;
padding: 1rem;
display: flex;
flex-direction: column;
gap: 15px;
-webkit-overflow-scrolling: touch;
}
.message {
max-width: 85%;
padding: 12px 18px;
border-radius: 20px;
position: relative;
animation: messageAppear 0.3s ease;
word-break: break-word;
line-height: 1.4;
}
.user-message {
background: linear-gradient(145deg, #006666, #009999);
align-self: flex-end;
color: white;
border: 1px solid var(--neon-color);
box-shadow: 0 0 10px var(--neon-color);
}
.bot-message {
background: linear-gradient(145deg, #1a1a1a, #2a2a2a);
align-self: flex-start;
border: 1px solid #444;
box-shadow: 0 0 10px rgba(0,255,255,0.2);
}
.input-container {
display: flex;
padding: 1rem;
gap: 10px;
background: rgba(0,0,0,0.5);
border-top: 1px solid var(--neon-color);
position: relative;
z-index: 2;
}
input[type="text"] {
flex: 1;
padding: 15px;
border: none;
border-radius: 25px;
background: rgba(255,255,255,0.1);
color: var(--neon-color);
font-size: 16px;
text-shadow: 0 0 5px var(--neon-color);
caret-color: var(--neon-color);
}
input::placeholder {
color: #4d4d4d;
font-style: italic;
}
button {
background: linear-gradient(145deg, #006666, #009999);
border: none;
padding: 0 25px;
border-radius: 25px;
color: white;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
min-width: 50px;
}
button:active {
transform: scale(0.95);
filter: brightness(1.2);
}
.typing-indicator {
display: inline-flex;
padding: 10px 15px;
background: rgba(0,0,0,0.5);
border-radius: 15px;
gap: 5px;
align-items: center;
}
.typing-dot {
width: 8px;
height: 8px;
background: var(--neon-color);
border-radius: 50%;
animation: typing 1.4s infinite ease-in-out;
}
@keyframes messageAppear {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes typing {
0%, 100% {
transform: translateY(0);
opacity: 0.5;
}
50% {
transform: translateY(-5px);
opacity: 1;
}
}
/* Scrollbar Styling */
::-webkit-scrollbar {
width: 5px;
}
::-webkit-scrollbar-track {
background: rgba(0,0,0,0.2);
}
::-webkit-scrollbar-thumb {
background: var(--neon-color);
border-radius: 5px;
}
@media (max-width: 480px) {
.message {
max-width: 90%;
padding: 10px 15px;
font-size: 14px;
}
input[type="text"] {
padding: 12px;
font-size: 14px;
}
button {
padding: 0 20px;
font-size: 14px;
}
.typing-dot {
width: 6px;
height: 6px;
}
}
</style>
</head>
<body>
<div class="chat-container">
<div class="chat-header">
<h1 style="color: var(--neon-color); text-shadow: 0 0 10px var(--neon-color); margin: 0;">GLOW CHAT</h1>
</div>
<div class="chat-messages" id="chatMessages">
<!-- Pesan akan muncul di sini -->
</div>
<div class="input-container">
<input type="text" id="userInput" placeholder="Ketik pesan..." autocomplete="off">
<button onclick="sendMessage()"></button>
</div>
</div>
<script>
const chatMessages = document.getElementById('chatMessages');
const userInput = document.getElementById('userInput');
let isBotTyping = false;
function createTypingIndicator() {
const container = document.createElement('div');
container.className = 'message bot-message typing-indicator';
for(let i = 0; i < 3; i++) {
const dot = document.createElement('div');
dot.className = 'typing-dot';
dot.style.animationDelay = `${i * 0.2}s`;
container.appendChild(dot);
}
return container;
}
async function sendMessage() {
const message = userInput.value.trim();
if (!message || isBotTyping) return;
// Tambahkan pesan pengguna
const userDiv = document.createElement('div');
userDiv.className = 'message user-message';
userDiv.textContent = message;
chatMessages.appendChild(userDiv);
userInput.value = '';
scrollToBottom();
// Tampilkan typing indicator
isBotTyping = true;
const typingIndicator = createTypingIndicator();
chatMessages.appendChild(typingIndicator);
scrollToBottom();
try {
const response = await fetch('http://localhost:3000/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message })
});
const data = await response.json();
// Hapus typing indicator dan tampilkan balasan
typingIndicator.remove();
const botDiv = document.createElement('div');
botDiv.className = 'message bot-message';
botDiv.textContent = data.reply;
chatMessages.appendChild(botDiv);
scrollToBottom();
} catch (error) {
typingIndicator.remove();
const errorDiv = document.createElement('div');
errorDiv.className = 'message bot-message';
errorDiv.textContent = '⚠️ Gagal terhubung ke server';
chatMessages.appendChild(errorDiv);
scrollToBottom();
} finally {
isBotTyping = false;
}
}
function scrollToBottom() {
chatMessages.scrollTop = chatMessages.scrollHeight;
}
// Handle keyboard events
userInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
sendMessage();
}
});
// Auto-focus input saat halaman dimuat
window.addEventListener('load', () => {
userInput.focus();
});
</script>
</body>
</html>