feat: add loading spinners on tab switch for data-driven tabs

Show a CSS spinner overlay when switching to Autonomous Stats (tab6),
Memories (tab9), and DM Management (tab10). Spinner only shows on
first visit when content is empty, removed after data loads.
This commit is contained in:
2026-03-01 00:29:03 +02:00
parent 0cdf26dc34
commit f0b5d71097

View File

@@ -455,6 +455,28 @@
.tab-content.active {
display: block;
}
/* Tab loading spinner */
.tab-loading-overlay {
display: flex;
align-items: center;
justify-content: center;
padding: 3rem 1rem;
color: #888;
font-size: 1rem;
gap: 0.75rem;
}
.tab-loading-overlay .spinner {
width: 24px;
height: 24px;
border: 3px solid #444;
border-top-color: #4CAF50;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
/* Chat Interface Styles */
.chat-message {
@@ -1852,16 +1874,43 @@ function switchTab(tabId) {
loadStatus();
loadLastPrompt();
}
if (tabId === 'tab6') {
showTabLoading('tab6');
loadAutonomousStats().finally(() => hideTabLoading('tab6'));
}
if (tabId === 'tab9') {
console.log('🧠 Refreshing memory stats for Memories tab');
refreshMemoryStats();
showTabLoading('tab9');
refreshMemoryStats().finally(() => hideTabLoading('tab9'));
}
if (tabId === 'tab10') {
console.log('📱 Loading DM users for DM Management tab');
loadDMUsers();
showTabLoading('tab10');
loadDMUsers().finally(() => hideTabLoading('tab10'));
}
}
function showTabLoading(tabId) {
const tab = document.getElementById(tabId);
if (!tab) return;
// Only show if no data loaded yet (first visit)
if (tab.querySelector('.tab-loading-overlay')) return;
const sections = tab.querySelectorAll('.section');
const hasContent = Array.from(sections).some(s => s.querySelector('[id]')?.innerHTML?.trim());
if (hasContent) return; // Data already loaded, skip spinner
const overlay = document.createElement('div');
overlay.className = 'tab-loading-overlay';
overlay.innerHTML = '<div class="spinner"></div> Loading...';
tab.prepend(overlay);
}
function hideTabLoading(tabId) {
const tab = document.getElementById(tabId);
if (!tab) return;
const overlay = tab.querySelector('.tab-loading-overlay');
if (overlay) overlay.remove();
}
// ============================================================================
// Initialization — all setup in one DOMContentLoaded
// ============================================================================