Add auto-refresh toggle and tab persistence via URL hash

- Auto-refresh checkbox with configurable interval (30s-5min)
- URL hash (#support, #customers etc.) persists active tab on refresh
- switchToTab() centralized function for tab switching
- Logo click uses same function

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 10:20:24 +02:00
parent 7fcf0a3b31
commit f918952c3f
2 changed files with 73 additions and 18 deletions

View File

@@ -265,6 +265,15 @@
<input type="checkbox" id="ticket-show-closed"> Suljetut <input type="checkbox" id="ticket-show-closed"> Suljetut
</label> </label>
<button class="btn-secondary" id="btn-ticket-rules" style="padding:7px 14px;font-size:0.82rem;">&#9881; Säännöt</button> <button class="btn-secondary" id="btn-ticket-rules" style="padding:7px 14px;font-size:0.82rem;">&#9881; Säännöt</button>
<label style="display:flex;align-items:center;gap:0.4rem;font-size:0.82rem;color:#777;cursor:pointer;white-space:nowrap;margin-left:auto;">
<input type="checkbox" id="ticket-auto-refresh"> Autopäivitys
<select id="ticket-refresh-interval" style="padding:3px 6px;border:1px solid #ddd;border-radius:5px;font-size:0.8rem;">
<option value="30">30s</option>
<option value="60" selected>1 min</option>
<option value="120">2 min</option>
<option value="300">5 min</option>
</select>
</label>
</div> </div>
<div id="ticket-fetch-status" style="display:none;padding:0.75rem 1rem;border-radius:8px;margin-bottom:1rem;font-size:0.9rem;"></div> <div id="ticket-fetch-status" style="display:none;padding:0.75rem 1rem;border-radius:8px;margin-bottom:1rem;font-size:0.9rem;"></div>
<div id="bulk-actions-toolbar" style="display:none;align-items:center;gap:0.75rem;padding:0.6rem 1rem;background:#fff3cd;border:1px solid #ffc107;border-radius:8px;margin-bottom:0.75rem;font-size:0.85rem;"> <div id="bulk-actions-toolbar" style="display:none;align-items:center;gap:0.75rem;padding:0.6rem 1rem;background:#fff3cd;border:1px solid #ffc107;border-radius:8px;margin-bottom:0.75rem;font-size:0.85rem;">

View File

@@ -170,35 +170,43 @@ async function showDashboard() {
// Näytä admin-toiminnot vain adminille // Näytä admin-toiminnot vain adminille
document.getElementById('btn-users').style.display = currentUser.role === 'admin' ? '' : 'none'; document.getElementById('btn-users').style.display = currentUser.role === 'admin' ? '' : 'none';
document.getElementById('tab-settings').style.display = currentUser.role === 'admin' ? '' : 'none'; document.getElementById('tab-settings').style.display = currentUser.role === 'admin' ? '' : 'none';
await loadCustomers(); // Avaa oikea tabi URL-hashin perusteella (tai customers oletuks)
const hash = window.location.hash.replace('#', '');
const validTabs = ['customers', 'leads', 'archive', 'changelog', 'support', 'users', 'settings'];
const startTab = validTabs.includes(hash) ? hash : 'customers';
switchToTab(startTab);
} }
// ==================== TABS ==================== // ==================== TABS ====================
document.querySelectorAll('.tab').forEach(tab => { function switchToTab(target) {
tab.addEventListener('click', () => {
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active')); document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active')); document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
tab.classList.add('active'); const tabBtn = document.querySelector(`.tab[data-tab="${target}"]`);
const target = tab.dataset.tab; if (tabBtn) tabBtn.classList.add('active');
document.getElementById('tab-content-' + target).classList.add('active'); const content = document.getElementById('tab-content-' + target);
if (content) content.classList.add('active');
// Tallenna aktiivinen tabi URL-hashiin
window.location.hash = target;
// Lataa sisältö tarvittaessa // Lataa sisältö tarvittaessa
if (target === 'customers') loadCustomers();
if (target === 'leads') loadLeads(); if (target === 'leads') loadLeads();
if (target === 'archive') loadArchive(); if (target === 'archive') loadArchive();
if (target === 'changelog') loadChangelog(); if (target === 'changelog') loadChangelog();
if (target === 'support') { loadTickets(); showTicketListView(); } if (target === 'support') { loadTickets(); showTicketListView(); }
if (target === 'users') loadUsers(); if (target === 'users') loadUsers();
if (target === 'settings') loadSettings(); if (target === 'settings') loadSettings();
}
document.querySelectorAll('.tab').forEach(tab => {
tab.addEventListener('click', () => {
switchToTab(tab.dataset.tab);
}); });
}); });
// Logo -> Asiakkaat (alkunäkymä) // Logo -> Asiakkaat (alkunäkymä)
document.getElementById('brand-home').addEventListener('click', () => { document.getElementById('brand-home').addEventListener('click', () => {
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active')); switchToTab('customers');
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
document.querySelector('.tab[data-tab="customers"]').classList.add('active');
document.getElementById('tab-content-customers').classList.add('active');
loadCustomers();
}); });
// Käyttäjät-nappi headerissa // Käyttäjät-nappi headerissa
@@ -1291,6 +1299,44 @@ document.getElementById('btn-fetch-emails').addEventListener('click', async () =
} }
}); });
// ==================== TICKET AUTO-REFRESH ====================
let ticketAutoRefreshTimer = null;
function startTicketAutoRefresh() {
stopTicketAutoRefresh();
const seconds = parseInt(document.getElementById('ticket-refresh-interval').value) || 60;
ticketAutoRefreshTimer = setInterval(() => {
// Vain jos support-tabi on aktiivinen ja listanäkymä näkyy
const supportActive = document.getElementById('tab-content-support').classList.contains('active');
const listVisible = document.getElementById('ticket-list-view').style.display !== 'none';
if (supportActive && listVisible) {
loadTickets();
}
}, seconds * 1000);
}
function stopTicketAutoRefresh() {
if (ticketAutoRefreshTimer) {
clearInterval(ticketAutoRefreshTimer);
ticketAutoRefreshTimer = null;
}
}
document.getElementById('ticket-auto-refresh').addEventListener('change', function() {
if (this.checked) {
startTicketAutoRefresh();
} else {
stopTicketAutoRefresh();
}
});
document.getElementById('ticket-refresh-interval').addEventListener('change', function() {
if (document.getElementById('ticket-auto-refresh').checked) {
startTicketAutoRefresh(); // Käynnistä uudelleen uudella intervallilla
}
});
// ==================== TICKET RULES (AUTOMAATTISÄÄNNÖT) ==================== // ==================== TICKET RULES (AUTOMAATTISÄÄNNÖT) ====================
let ticketRules = []; let ticketRules = [];