// Shared timezone utility — used by setup wizard and settings modal window.populateTimezoneSelect = function(selectEl, selectedTz) { const timezones = Intl.supportedValuesOf('timeZone'); const detected = selectedTz || Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC'; selectEl.innerHTML = ''; for (const tz of timezones) { const opt = document.createElement('option'); opt.value = tz; opt.textContent = tz.replace(/_/g, ' '); if (tz === detected) opt.selected = true; selectEl.appendChild(opt); } }; // Setup Wizard System - Server-side config storage (function () { let currentConfigType = 'homelab'; let serverConfig = null; // Check server for existing config on page load async function checkServerConfig() { try { const response = await fetch('/api/v1/config'); if (response.ok) { serverConfig = await response.json(); if (serverConfig && serverConfig.setupComplete) { // Config exists on server - don't show wizard document.getElementById('setup-wizard').style.display = 'none'; return true; } } } catch (error) { console.warn('Could not fetch server config, checking localStorage fallback:', error.message); } // Fallback: check localStorage for backwards compatibility const localSetup = safeGet('dashcaddy-setup'); if (localSetup) { document.getElementById('setup-wizard').style.display = 'none'; return true; } // No config found - show wizard document.getElementById('setup-wizard').style.display = 'flex'; return false; } // Initialize on page load checkServerConfig(); // Populate timezone dropdown with auto-detection const setupTzSelect = document.getElementById('setup-timezone'); if (setupTzSelect) window.populateTimezoneSelect(setupTzSelect); // Step navigation function showStep(stepId) { document.querySelectorAll('.setup-step').forEach(step => { step.style.display = 'none'; }); const targetStep = document.getElementById(stepId); if (targetStep) { targetStep.style.display = 'block'; } } // Show summary function showSummary() { const summaryContent = document.getElementById('setup-summary-content'); if (!summaryContent) return; let html = '
'; if (currentConfigType === 'homelab') { const tld = document.getElementById('setup-tld')?.value?.trim() || '.home'; const caName = document.getElementById('setup-ca-name')?.value?.trim() || ''; const dnsIP = document.getElementById('setup-dns-ip')?.value?.trim() || ''; const dnsPort = document.getElementById('setup-dns-port')?.value?.trim() || DC.DEFAULTS.DNS_PORT; html += `

Home Lab Configuration

TLD: ${tld}
Certificate Authority: ${caName}
DNS Server: ${dnsIP}:${dnsPort}
Example URLs: https://uptime${tld}, https://nextcloud${tld}
`; } else if (currentConfigType === 'simple') { const ip = document.getElementById('setup-simple-ip')?.value?.trim() || 'localhost'; html += `

Simple Setup

Access Method: IP:Port only
Default IP: ${ip}
SSL: None (HTTP only)
Example URLs: http://${ip}:8080, http://${ip}:3000
`; } else if (currentConfigType === 'public') { const domain = document.getElementById('setup-public-domain')?.value?.trim() || ''; const email = document.getElementById('setup-public-email')?.value?.trim() || ''; html += `

Public Server

Domain: ${domain}
SSL: Let's Encrypt
Email: ${email}
Example URLs: https://app.${domain}, https://cloud.${domain}
`; } // Timezone (universal across all config types) const tz = document.getElementById('setup-timezone')?.value || Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC'; html += `
Timezone: ${tz.replace(/_/g, ' ')}
`; html += '
'; summaryContent.innerHTML = html; showStep('setup-step-summary'); } // Save config to server async function saveConfigToServer(config) { try { const response = await secureFetch('/api/v1/config', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(config) }); if (response.ok) { await response.json(); return true; } else { console.error('Failed to save config to server:', response.status); return false; } } catch (error) { console.error('Error saving config to server:', error); return false; } } // Finish setup handler async function finishSetup() { const config = { setupComplete: true, configurationType: currentConfigType, timestamp: new Date().toISOString(), timezone: document.getElementById('setup-timezone')?.value || Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC' }; if (currentConfigType === 'homelab') { config.tld = document.getElementById('setup-tld')?.value?.trim() || '.home'; config.caName = document.getElementById('setup-ca-name')?.value?.trim() || ''; config.dns = { provider: 'technitium', ip: document.getElementById('setup-dns-ip')?.value?.trim() || '', port: document.getElementById('setup-dns-port')?.value?.trim() || DC.DEFAULTS.DNS_PORT, token: document.getElementById('setup-dns-token')?.value?.trim() || '' }; config.defaults = { dnsType: 'private', sslType: 'internal', targetIP: 'localhost' }; } else if (currentConfigType === 'simple') { config.defaultIP = document.getElementById('setup-simple-ip')?.value?.trim() || 'localhost'; config.defaults = { dnsType: 'none', sslType: 'none', targetIP: config.defaultIP }; } else if (currentConfigType === 'public') { config.domain = document.getElementById('setup-public-domain')?.value?.trim() || ''; config.email = document.getElementById('setup-public-email')?.value?.trim() || ''; config.defaults = { dnsType: 'public', sslType: 'letsencrypt', targetIP: 'localhost' }; } // Save to server (primary) and localStorage (fallback) const savedToServer = await saveConfigToServer(config); safeSet('dashcaddy-config', JSON.stringify(config)); safeSet('dashcaddy-setup', 'completed'); // Hide wizard document.getElementById('setup-wizard').style.display = 'none'; // Show success notification const configName = currentConfigType === 'homelab' ? 'Professional Home Lab' : currentConfigType === 'simple' ? 'Simple Setup' : 'Public Server'; const saveLocation = savedToServer ? 'server (shared across all devices)' : 'locally (this browser only)'; showNotification(`Setup Complete! Configured for: ${configName}. Settings saved to: ${saveLocation}`, 'success', 5000); // Reload page to apply configuration setTimeout(() => location.reload(), 500); } // ===== Event Handlers using direct onclick for reliability ===== // Step 1: Continue button const step1Next = document.getElementById('setup-step-1-next'); if (step1Next) { step1Next.onclick = function(e) { e.preventDefault(); const selected = document.querySelector('input[name="config-type"]:checked'); if (selected) { currentConfigType = selected.value; } if (currentConfigType === 'homelab') { showStep('setup-step-homelab'); } else if (currentConfigType === 'simple') { showStep('setup-step-simple'); } else if (currentConfigType === 'public') { showStep('setup-step-public'); } else { showStep('setup-step-homelab'); } }; } // Skip setup button const skipBtn = document.getElementById('setup-skip'); if (skipBtn) { skipBtn.onclick = async function(e) { e.preventDefault(); if (confirm('Skip setup? You can run it later from Settings.')) { // Save skip status to server await saveConfigToServer({ setupComplete: true, skipped: true, timestamp: new Date().toISOString() }); safeSet('dashcaddy-setup', 'skipped'); document.getElementById('setup-wizard').style.display = 'none'; } }; } // Home Lab: TLD Preview const tldInput = document.getElementById('setup-tld'); if (tldInput) { tldInput.oninput = function(e) { const tld = e.target.value || '.home'; const preview1 = document.getElementById('tld-preview'); const preview2 = document.getElementById('tld-preview-2'); if (preview1) preview1.textContent = tld; if (preview2) preview2.textContent = tld; }; } // Home Lab navigation const homelabBack = document.getElementById('setup-homelab-back'); if (homelabBack) { homelabBack.onclick = function(e) { e.preventDefault(); showStep('setup-step-1'); }; } const homelabNext = document.getElementById('setup-homelab-next'); if (homelabNext) { homelabNext.onclick = function(e) { e.preventDefault(); const tld = document.getElementById('setup-tld')?.value?.trim() || ''; const caName = document.getElementById('setup-ca-name')?.value?.trim() || ''; const dnsIP = document.getElementById('setup-dns-ip')?.value?.trim() || ''; if (!tld || !tld.startsWith('.')) { showNotification('Please enter a valid TLD starting with a dot (e.g., .home)', 'warning'); return; } if (!caName) { showNotification('Please enter a Certificate Authority name', 'warning'); return; } if (!dnsIP) { showNotification('Please enter your DNS server IP address', 'warning'); return; } showSummary(); }; } // Simple navigation const simpleBack = document.getElementById('setup-simple-back'); if (simpleBack) { simpleBack.onclick = function(e) { e.preventDefault(); showStep('setup-step-1'); }; } const simpleNext = document.getElementById('setup-simple-next'); if (simpleNext) { simpleNext.onclick = function(e) { e.preventDefault(); showSummary(); }; } // Public navigation const publicBack = document.getElementById('setup-public-back'); if (publicBack) { publicBack.onclick = function(e) { e.preventDefault(); showStep('setup-step-1'); }; } const publicNext = document.getElementById('setup-public-next'); if (publicNext) { publicNext.onclick = function(e) { e.preventDefault(); const domain = document.getElementById('setup-public-domain')?.value?.trim() || ''; const email = document.getElementById('setup-public-email')?.value?.trim() || ''; if (!domain) { showNotification('Please enter your domain name', 'warning'); return; } if (!email || !email.includes('@')) { showNotification('Please enter a valid email address', 'warning'); return; } showSummary(); }; } // Summary navigation const summaryBack = document.getElementById('setup-summary-back'); if (summaryBack) { summaryBack.onclick = function(e) { e.preventDefault(); if (currentConfigType === 'homelab') { showStep('setup-step-homelab'); } else if (currentConfigType === 'simple') { showStep('setup-step-simple'); } else if (currentConfigType === 'public') { showStep('setup-step-public'); } }; } // Finish setup button const finishBtn = document.getElementById('setup-finish'); if (finishBtn) { finishBtn.onclick = function(e) { e.preventDefault(); finishSetup(); }; } // Expose function to get global config (from server or localStorage) window.getGlobalConfig = async function() { // Try server first try { const response = await fetch('/api/v1/config'); if (response.ok) { const config = await response.json(); if (config && config.setupComplete) { return config; } } } catch (e) { console.warn('Could not fetch config from server'); } // Fallback to localStorage const configStr = safeGet('dashcaddy-config'); if (configStr) { return JSON.parse(configStr); } // Return default config if not set return { setupComplete: false, configurationType: 'homelab', tld: '.home', caName: '', defaults: { dnsType: 'private', sslType: 'internal', targetIP: 'localhost' } }; }; // Expose reset function for settings window.resetSetupWizard = async function() { if (confirm('Reset DashCaddy configuration? This will show the setup wizard again.')) { try { await secureFetch('/api/v1/config', { method: 'DELETE' }); } catch (e) { console.warn('Could not delete server config'); } safeRemove('dashcaddy-setup'); safeRemove('dashcaddy-config'); location.reload(); } }; })();