diff --git a/public/app.js b/public/app.js index b445f63..78a7979 100644 --- a/public/app.js +++ b/public/app.js @@ -15,6 +15,7 @@ const uploadModal = document.getElementById('uploadModal'); const projectModal = document.getElementById('projectModal'); const importModal = document.getElementById('importModal'); const settingsModal = document.getElementById('settingsModal'); +const setupModal = document.getElementById('setupModal'); const editModal = document.getElementById('editModal'); const fileDetailModal = document.getElementById('fileDetailModal'); @@ -39,6 +40,11 @@ async function loadData() { renderModels(); updateCounts(); generateMissingThumbnails(); // fire-and-forget; updates cards as they finish + + // First-run onboarding: prompt for import sources once. + if (config.setupComplete === false && !setupModal.classList.contains('active')) { + setupModal.classList.add('active'); + } } catch (error) { console.error('Error loading data:', error); } @@ -170,9 +176,13 @@ function setupEventListeners() { btn.addEventListener('click', (e) => closeModal(e.target.closest('.modal'))); }); document.querySelectorAll('.modal').forEach((modal) => { + if (modal.id === 'setupModal') return; // must be finished or skipped, not backdrop-dismissed modal.addEventListener('click', (e) => { if (e.target === modal) closeModal(modal); }); }); + document.getElementById('setupForm').addEventListener('submit', handleFinishSetup); + document.getElementById('skipSetup').addEventListener('click', handleSkipSetup); + document.getElementById('uploadForm').addEventListener('submit', handleUpload); document.getElementById('cancelUpload').addEventListener('click', () => closeModal(uploadModal)); document.getElementById('projectForm').addEventListener('submit', handleCreateProject); @@ -259,6 +269,42 @@ function openProjectModal() { projectModal.classList.add('active'); } +async function markSetupComplete() { + try { + await fetch('/api/setup/complete', { method: 'POST' }); + config.setupComplete = true; + } catch { /* non-fatal */ } +} + +async function handleFinishSetup(e) { + e.preventDefault(); + const status = document.getElementById('setupStatus'); + const payload = {}; + document.querySelectorAll('#setupForm [data-setting]').forEach((input) => { + if (input.value.trim()) payload[input.dataset.setting] = input.value.trim(); + }); + try { + if (Object.keys(payload).length) { + const res = await fetch('/api/settings', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + if (!res.ok) throw new Error((await res.json()).error); + } + await markSetupComplete(); + closeModal(setupModal); + await loadData(); + } catch (err) { + status.textContent = 'Could not save: ' + err.message; + } +} + +async function handleSkipSetup() { + await markSetupComplete(); + closeModal(setupModal); +} + async function openSettingsModal() { document.getElementById('settingsForm').reset(); document.getElementById('settingsStatus').textContent = ''; diff --git a/public/index.html b/public/index.html index ab2e8ba..26b347e 100644 --- a/public/index.html +++ b/public/index.html @@ -69,6 +69,50 @@ + + +