botserver/templates/chat.html

159 lines
5.7 KiB
HTML

{% extends "base.html" %}
{% block title %}Chat - General Bots{% endblock %}
{% block content %}
<div class="chat-layout">
<!-- Session Sidebar -->
<aside class="chat-sidebar" id="chat-sidebar">
<div class="sidebar-header">
<h3>Sessions</h3>
<button class="btn-new-session"
hx-post="/api/chat/sessions/new"
hx-target="#sessions-list"
hx-swap="afterbegin">
+ New Chat
</button>
</div>
<div id="sessions-list" class="sessions-list"
hx-get="/api/chat/sessions"
hx-trigger="load"
hx-swap="innerHTML">
<!-- Sessions loaded here -->
</div>
</aside>
<!-- Chat Main -->
<div class="chat-main">
<!-- Connection Status -->
<div id="connection-status" class="connection-status"
hx-sse="connect:/api/chat/status swap:innerHTML">
<span class="status-dot"></span>
<span class="status-text">Connecting...</span>
</div>
<!-- Messages Container -->
<div id="messages" class="messages"
hx-get="/api/chat/messages?session_id={{ session_id }}"
hx-trigger="load"
hx-swap="innerHTML">
<!-- Messages loaded here -->
</div>
<!-- Typing Indicator -->
<div id="typing-indicator" class="typing-indicator hidden">
<div class="typing-dots">
<span></span>
<span></span>
<span></span>
</div>
</div>
<!-- Suggestions -->
<div id="suggestions" class="suggestions"
hx-get="/api/chat/suggestions"
hx-trigger="load"
hx-swap="innerHTML">
<!-- Suggestions loaded here -->
</div>
<!-- Input Form -->
<form class="chat-input-container"
hx-post="/api/chat/send"
hx-target="#messages"
hx-swap="beforeend"
hx-ext="json-enc"
hx-on::before-request="document.getElementById('typing-indicator').classList.remove('hidden')"
hx-on::after-request="this.reset(); document.getElementById('typing-indicator').classList.add('hidden'); document.getElementById('message-input').focus()">
<input type="hidden" name="session_id" value="{{ session_id }}">
<div class="input-group">
<textarea
id="message-input"
name="content"
class="message-input"
placeholder="Type your message..."
rows="1"
required
autofocus
hx-trigger="keydown[key=='Enter' && !shiftKey] from:body"
hx-post="/api/chat/send"
hx-target="#messages"
hx-swap="beforeend"></textarea>
<!-- Voice Button -->
<button type="button"
class="btn-voice"
hx-post="/api/voice/toggle"
hx-swap="none"
title="Voice input">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path>
<path d="M19 10v2a7 7 0 0 1-14 0v-2"></path>
<line x1="12" y1="19" x2="12" y2="23"></line>
</svg>
</button>
<!-- Send Button -->
<button type="submit" class="btn-send" title="Send">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="22" y1="2" x2="11" y2="13"></line>
<polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
</svg>
</button>
</div>
<!-- Context Selector -->
<div class="context-selector"
hx-get="/api/chat/contexts"
hx-trigger="load"
hx-swap="innerHTML">
<!-- Contexts loaded here -->
</div>
</form>
</div>
<!-- Scroll to Bottom -->
<button id="scroll-to-bottom" class="scroll-to-bottom hidden"
onclick="document.getElementById('messages').scrollTo(0, document.getElementById('messages').scrollHeight)">
</button>
</div>
{% endblock %}
{% block scripts %}
<script>
// Auto-resize textarea
const textarea = document.getElementById('message-input');
textarea.addEventListener('input', function() {
this.style.height = 'auto';
this.style.height = Math.min(this.scrollHeight, 120) + 'px';
});
// Monitor scroll position
const messages = document.getElementById('messages');
const scrollBtn = document.getElementById('scroll-to-bottom');
messages.addEventListener('scroll', function() {
const isAtBottom = this.scrollHeight - this.scrollTop <= this.clientHeight + 50;
scrollBtn.classList.toggle('hidden', isAtBottom);
});
// Auto-scroll on new messages
messages.addEventListener('htmx:afterSettle', function(event) {
if (event.detail.target === this) {
this.scrollTo(0, this.scrollHeight);
}
});
// Handle suggestion clicks
document.addEventListener('click', function(e) {
if (e.target.classList.contains('suggestion-chip')) {
textarea.value = e.target.textContent;
textarea.form.dispatchEvent(new Event('submit'));
}
});
</script>
{% endblock %}