\n
The Golf DraftEmail Automation
Checking sign in…
Draft League Results Profile Rules Admin Hub Detailed Admin
Premium comms control

Email Automation

Control automated emails, preview the exact campaign feel live, and test safely. Nothing sends unless the relevant toggle is enabled.

Automation settings

Reminder Status
Loading...
Click a placeholder to copy it: use these in subjects, titles and body text.
{name}{username}{team}{team_name}{league}{league_name}{league_code}
Welcome preview
Subject preview
Live
Reminder preview
Subject preview
Live

Test emails

Send safe test copies to confirm layout and Gmail settings.

Recent automation log

Loading...
`; } function updatePreviews(){ ['welcome','reminder'].forEach(kind=>{ const frame = $(kind + 'PreviewFrame'); const subjectEl = $(kind + 'PreviewSubject'); if(subjectEl) subjectEl.textContent = tokenise($(kind + '_subject')?.value || (kind === 'welcome' ? 'Welcome to The Golf Draft' : 'The Golf Draft entries are closing soon')); if(frame) frame.srcdoc = emailHtml(kind); }); } function fill(cfg){ ['welcome_enabled','reminder_enabled','results_enabled','tracking_enabled'].forEach(id=>{ if($(id)) $(id).checked = !!cfg[id]; }); ['welcome_subject','welcome_title','welcome_body','welcome_image_url','welcome_delay_minutes','reminder_subject','reminder_title','reminder_body','reminder_image_url','reminder_hours_before_lock','results_subject','results_send_mode'].forEach(id=>{ if($(id)) $(id).value = cfg[id] ?? ''; }); updatePreviews(); } function gather(){ return { welcome_enabled:$('welcome_enabled')?.checked || false, welcome_subject:$('welcome_subject')?.value || '', welcome_title:$('welcome_title')?.value || '', welcome_body:$('welcome_body')?.value || '', welcome_image_url:$('welcome_image_url')?.value || '', welcome_delay_minutes:$('welcome_delay_minutes')?.value || 0, reminder_enabled:$('reminder_enabled')?.checked || false, reminder_subject:$('reminder_subject')?.value || '', reminder_title:$('reminder_title')?.value || '', reminder_body:$('reminder_body')?.value || '', reminder_image_url:$('reminder_image_url')?.value || '', reminder_hours_before_lock:$('reminder_hours_before_lock')?.value || 0, results_enabled:$('results_enabled')?.checked || false, results_subject:$('results_subject')?.value || '', results_send_mode:$('results_send_mode')?.value || 'manual', tracking_enabled:$('tracking_enabled')?.checked || false }; } function renderLog(log){ const box = $('log'); if(!box) return; if(!log || !log.length){ box.textContent = 'No automation events yet.'; return; } box.innerHTML = log.slice().reverse().map(item => `
${escapeHtml(item.event_type || 'event')}
${escapeHtml(item.created_at || '')}
${escapeHtml(JSON.stringify(item.details || {}))}
`).join(''); } async function loadImagesForAutomation(){ try{ const d = await getJson('/api/email-builder/images'); const imgs = d.images || []; ['welcome_image_url','reminder_image_url'].forEach(id=>{ const sel = $(id); if(!sel) return; const current = sel.value; sel.innerHTML = ''; imgs.forEach(img=>{ const o = document.createElement('option'); o.value = img.absolute_url || img.url; o.textContent = img.filename; sel.appendChild(o); }); if(current) sel.value = current; }); }catch(e){} } async function loadReminderStatus(){ const el = $('reminderStatusText'); if(!el) return; try{ const d = await getJson('/api/email-automation/reminder-status'); const lock = d.lock_at_utc || d.lock_utc || d.lock || ''; const dueFrom = d.due_from_utc || d.due_from || ''; const dueNow = (typeof d.due !== 'undefined') ? d.due : d.due_now; const recipients = d.recipient_count || d.recipients || 0; el.textContent = `Enabled: ${d.enabled ? 'Yes' : 'No'}\nLock UTC: ${lock || 'Not found'}\nDue from UTC: ${dueFrom || 'Not found'}\nDue now: ${dueNow ? 'Yes' : 'No'}\nAlready sent: ${d.already_sent ? 'Yes' : 'No'}\nRecipients: ${recipients}`; }catch(e){ el.textContent = 'Error loading status: ' + (e.message || 'Request failed'); } } async function load(){ try{ await loadImagesForAutomation(); await loadReminderStatus(); const d = await getJson('/api/email-automation/settings'); fill(d.settings || {}); renderLog(d.log || []); }catch(e){ show(e.message, true); updatePreviews(); } } async function save(){ const btn = $('saveBtn'); const old = btn ? btn.textContent : ''; if(btn){ btn.disabled = true; btn.textContent = 'Saving...'; } try{ const d = await postJson('/api/email-automation/settings', gather()); fill(d.settings || {}); show('Settings saved.'); await load(); }catch(e){ show(e.message, true); } finally{ if(btn){ btn.disabled = false; btn.textContent = old; } } } async function test(kind){ try{ const d = await postJson('/api/email-automation/test', {kind,to:$('testTo')?.value || ''}); show(`Test sent to ${d.sent_to}`); await load(); }catch(e){ show(e.message, true); } } function bindLivePreview(){ ['welcome_subject','welcome_title','welcome_body','welcome_image_url','reminder_subject','reminder_title','reminder_body','reminder_image_url'].forEach(id=>{ const el = $(id); if(el){ el.addEventListener('input', updatePreviews); el.addEventListener('change', updatePreviews); } }); document.querySelectorAll('[data-copy]').forEach(chip=>{ chip.addEventListener('click', async ()=>{ const text = chip.getAttribute('data-copy') || ''; try{ await navigator.clipboard.writeText(text); show(`Copied ${text}`); }catch(e){ show(text); } }); }); } document.addEventListener('DOMContentLoaded', ()=>{ bindLivePreview(); updatePreviews(); load(); $('saveBtn')?.addEventListener('click', save); $('testWelcomeBtn')?.addEventListener('click', ()=>test('welcome')); $('testReminderBtn')?.addEventListener('click', ()=>test('reminder')); }); \n \n