import { showToast } from '../components/toast.js';
const STEPS = [
{
title: 'Welcome to ScreenTinker!',
icon: '👋',
content: `
Let's get you set up in under 5 minutes.
This wizard will guide you through:
- Downloading the player app
- Pairing your first display
- Uploading and assigning content
`,
action: null
},
{
title: 'Step 1: Get the Player App',
icon: '📥',
content: `Install the player on your display device.
Open the app on your display and enter this server URL:
${window.location.origin}`,
action: null
},
{
title: 'Step 2: Pair Your Display',
icon: '🔗',
content: `Enter the 6-digit code shown on your display.
`,
action: 'pair'
},
{
title: 'Step 3: Upload Content',
icon: '📤',
content: `Upload a video or image to display.
📁
Click to select a file
MP4, WebM, JPEG, PNG, GIF
`,
action: 'upload'
},
{
title: "You're All Set!",
icon: '🎉',
content: `Your display is paired and content is playing!
What's next?
- Add more content in the Content Library
- Create multi-zone layouts in Layouts
- Set up a schedule in the Schedule calendar
- Add live widgets (clock, weather, ticker) in Widgets
- Create interactive screens in Kiosk
- Design custom content in the Designer
`,
action: null
}
];
export function render(container) {
let currentStep = 0;
let pairedDeviceId = null;
function renderStep() {
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 ? `` : ''}
`;
// Bind buttons
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);
// Step-specific setup
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 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 = 'Enter a valid 6-digit code';
return;
}
try {
if (status) status.textContent = '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 || 'Pairing failed'; return; }
pairedDeviceId = data.id;
showToast('Display paired!', 'success');
currentStep++;
renderStep();
} catch (err) {
if (status) status.textContent = 'Pairing failed: ' + 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 = 'Uploaded! Assigning to display...';
// Auto-assign to paired device
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('Content uploaded and assigned!', 'success');
currentStep++;
renderStep();
} else {
if (text) text.textContent = 'Upload failed';
}
};
xhr.onerror = () => { if (text) text.textContent = 'Upload failed'; };
xhr.send(formData);
} catch (err) {
if (text) text.textContent = 'Error: ' + err.message;
}
}
renderStep();
}
export function cleanup() {}