async function renderScheduler() { const content = document.getElementById('pageContent'); content.innerHTML = `
`; try { const jobs = await api.getJobs(); const container = document.getElementById('jobList'); if (jobs.length === 0) { container.innerHTML = '

No scheduled jobs

'; return; } const html = `
${jobs.map(j => ` `).join('')}
NameSkillCronLast RunNext RunStatus
${j.name} ${j.skill} ${j.cron} ${formatDate(j.last_run)} ${formatDate(j.next_run)} ${j.enabled ? 'Active' : 'Paused'}
`; container.innerHTML = html; } catch (err) { document.getElementById('jobList').innerHTML = `

${escapeHtml(err.message)}

`; } } async function showNewJobForm() { document.getElementById('newJobForm').style.display = 'block'; document.getElementById('newJobForm').innerHTML = `
New Scheduled Job
Common: */5 * * * * (5 min), 0 6 * * * (daily 6AM), 0 6 * * 1 (weekly Mon)
`; try { const skills = await api.getSkills(); const select = document.getElementById('jobSkill'); skills.forEach(s => { const opt = document.createElement('option'); opt.value = s.name; opt.textContent = s.name; select.appendChild(opt); }); } catch {} } async function createJob() { const name = document.getElementById('jobName').value.trim(); const skill = document.getElementById('jobSkill').value; const cron = document.getElementById('jobCron').value.trim(); if (!name || !skill || !cron) { showToast('All fields required', 'error'); return; } try { await api.createJob({ name, skill, cron }); showToast('Job created', 'success'); renderScheduler(); } catch (err) { showToast(`Error: ${err.message}`, 'error'); } } function cancelNewJob() { document.getElementById('newJobForm').style.display = 'none'; } async function deleteJob(id) { if (!confirm('Delete this job?')) return; try { await api.deleteJob(id); showToast('Job deleted', 'success'); renderScheduler(); } catch (err) { showToast(`Error: ${err.message}`, 'error'); } }