import { showToast } from '../components/toast.js'; import { t } from '../i18n.js'; // Steps are computed lazily so translated strings refresh on language change. function getSteps() { return [ { title: t('onboarding.step.welcome.title'), icon: '👋', content: `

${t('onboarding.step.welcome.intro')}

${t('onboarding.step.welcome.guide_through')}

`, action: null }, { title: t('onboarding.step.player.title'), icon: '📥', content: `

${t('onboarding.step.player.intro')}

🤖
${t('onboarding.step.player.android_label')}
${t('onboarding.step.player.android_desc')}
🌐
${t('onboarding.step.player.web_label')}
${t('onboarding.step.player.web_desc')}

${t('onboarding.step.player.url_hint')}

${window.location.origin}`, action: null }, { title: t('onboarding.step.pair.title'), icon: '🔗', content: `

${t('onboarding.step.pair.intro')}

`, action: 'pair' }, { title: t('onboarding.step.upload.title'), icon: '📤', content: `

${t('onboarding.step.upload.intro')}

📁

${t('onboarding.step.upload.click_to_select')}

${t('onboarding.step.upload.formats')}

`, action: 'upload' }, { title: t('onboarding.step.done.title'), icon: '🎉', content: `

${t('onboarding.step.done.intro')}

${t('onboarding.step.done.whats_next')}

`, action: null } ]; } export function render(container) { let currentStep = 0; let pairedDeviceId = null; function renderStep() { const STEPS = getSteps(); const step = STEPS[currentStep]; const isFirst = currentStep === 0; const isLast = currentStep === STEPS.length - 1; container.innerHTML = `
${STEPS.map((_, i) => `
`).join('')}
${step.icon}

${step.title}

${step.content}
${isFirst ? '
' : ``}
${!isLast ? `` : ''}
`; document.getElementById('prevBtn')?.addEventListener('click', () => { currentStep--; renderStep(); }); document.getElementById('skipBtn')?.addEventListener('click', () => { localStorage.setItem('rd_onboarded', 'true'); window.location.hash = '#/'; window.location.reload(); }); document.getElementById('nextBtn')?.addEventListener('click', handleNext); if (step.action === 'upload') { const area = document.getElementById('onboardUploadArea'); const input = document.getElementById('onboardFileInput'); area?.addEventListener('click', () => input.click()); input?.addEventListener('change', handleUpload); } } async function handleNext() { const STEPS = getSteps(); const step = STEPS[currentStep]; if (step.action === 'pair') { const code = document.getElementById('onboardPairingCode')?.value.trim(); const name = document.getElementById('onboardDeviceName')?.value.trim(); const status = document.getElementById('onboardPairStatus'); if (!code || code.length !== 6) { if (status) status.textContent = t('onboarding.toast.invalid_code'); return; } try { if (status) status.textContent = t('onboarding.toast.pairing'); const token = localStorage.getItem('token'); const res = await fetch('/api/provision/pair', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` }, body: JSON.stringify({ pairing_code: code, name: name || undefined }) }); const data = await res.json(); if (!res.ok) { if (status) status.textContent = data.error || t('onboarding.toast.pair_failed'); return; } pairedDeviceId = data.id; showToast(t('onboarding.toast.paired'), 'success'); currentStep++; renderStep(); } catch (err) { if (status) status.textContent = t('onboarding.toast.pair_failed_with_error', { error: err.message }); } return; } if (currentStep === STEPS.length - 1) { localStorage.setItem('rd_onboarded', 'true'); window.location.hash = '#/'; window.location.reload(); return; } currentStep++; renderStep(); } async function handleUpload() { const file = document.getElementById('onboardFileInput')?.files[0]; if (!file) return; const progress = document.getElementById('onboardUploadProgress'); const bar = document.getElementById('onboardProgressBar'); const text = document.getElementById('onboardUploadText'); if (progress) progress.style.display = 'block'; try { const token = localStorage.getItem('token'); const formData = new FormData(); formData.append('file', file); const xhr = new XMLHttpRequest(); xhr.open('POST', '/api/content'); xhr.setRequestHeader('Authorization', `Bearer ${token}`); xhr.upload.onprogress = (e) => { if (e.lengthComputable && bar) bar.style.width = Math.round((e.loaded / e.total) * 100) + '%'; }; xhr.onload = async () => { if (xhr.status >= 200 && xhr.status < 300) { const content = JSON.parse(xhr.responseText); if (text) text.textContent = t('onboarding.toast.uploaded_assigning'); if (pairedDeviceId) { try { await fetch(`/api/assignments/device/${pairedDeviceId}`, { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` }, body: JSON.stringify({ content_id: content.id, duration_sec: 10 }) }); } catch {} } showToast(t('onboarding.toast.content_assigned'), 'success'); currentStep++; renderStep(); } else { if (text) text.textContent = t('onboarding.toast.upload_failed'); } }; xhr.onerror = () => { if (text) text.textContent = t('onboarding.toast.upload_failed'); }; xhr.send(formData); } catch (err) { if (text) text.textContent = t('onboarding.toast.error_with_error', { error: err.message }); } } renderStep(); } export function cleanup() {}