새 뉴스레터

구독자 추가

구독자 목록

불러오는 중...

발송 완료 뉴스레터

불러오는 중...
'; } /* ── PREVIEW ── */ function previewNewsletter() { var title = document.getElementById('nl-title').value.trim(); var category = document.getElementById('nl-category').value; var content = document.getElementById('nl-content').value.trim(); if (!title || !content) { showToast('제목과 본문을 입력하세요', true); return; } var html = buildEmailHtml(title, category, content); var iframe = document.getElementById('preview-iframe'); var doc = iframe.contentDocument || iframe.contentWindow.document; doc.open(); doc.write(html); doc.close(); document.getElementById('preview-modal').classList.add('show'); } function closeModal() { document.getElementById('preview-modal').classList.remove('show'); } /* ── SAVE NEWSLETTER ── */ function saveNewsletter(callback) { var title = document.getElementById('nl-title').value.trim(); var category = document.getElementById('nl-category').value; var content = document.getElementById('nl-content').value.trim(); if (!title || !content) { showToast('제목과 본문을 입력하세요', true); return; } api('POST', '/api/newsletters', { title: title, category: category, content: content }) .then(function(res) { showToast('뉴스레터가 저장되었습니다'); if (callback && res.length > 0) callback(res[0].id); }) .catch(function(e) { showToast('저장 실패: ' + e.message, true); }); } /* ── SAVE & SEND ── */ function saveAndSend() { if (!confirm('저장 후 모든 구독자에게 발송합니다. 계속하시겠습니까?')) return; saveNewsletter(function(id) { showToast('발송 중...'); var fromEmail = document.getElementById('nl-from').value || '[email protected]'; api('POST', '/api/send-newsletter', { newsletter_id: id, from_email: fromEmail }) .then(function(res) { showToast(res.sent + '/' + res.total + '명에게 발송 완료'); document.getElementById('compose-form').reset(); }) .catch(function(e) { showToast('발송 실패: ' + e.message, true); }); }); } /* ── SUBSCRIBERS ── */ function loadSubscribers() { api('GET', '/api/subscribers') .then(function(subs) { var el = document.getElementById('subscribers-list'); if (!subs.length) { el.innerHTML = '
등록된 구독자가 없습니다
'; return; } var active = subs.filter(function(s) { return s.active; }); var inactive = subs.filter(function(s) { return !s.active; }); var html = '

활성 구독자 ' + active.length + '명

'; html += ''; subs.forEach(function(s) { var date = new Date(s.created_at).toLocaleDateString('ko-KR'); var status = s.active ? '활성' : '비활성'; var action = s.active ? '' : ''; html += ''; }); html += '
이메일이름등록일상태
' + s.email + '' + (s.name || '-') + '' + date + '' + status + '' + action + '
'; el.innerHTML = html; }) .catch(function(e) { document.getElementById('subscribers-list').innerHTML = '
불러오기 실패: ' + e.message + '
'; }); } function addSubscriber() { var email = document.getElementById('sub-email').value.trim(); var name = document.getElementById('sub-name').value.trim(); if (!email) { showToast('이메일을 입력하세요', true); return; } api('POST', '/api/subscribers', { email: email, name: name }) .then(function() { showToast('구독자가 추가되었습니다'); document.getElementById('sub-email').value = ''; document.getElementById('sub-name').value = ''; loadSubscribers(); }) .catch(function(e) { showToast('추가 실패: ' + e.message, true); }); } function deactivateSub(id) { if (!confirm('이 구독자를 비활성화하시겠습니까?')) return; api('DELETE', '/api/subscribers/' + id) .then(function() { showToast('비활성화되었습니다'); loadSubscribers(); }) .catch(function(e) { showToast('실패: ' + e.message, true); }); } /* ── ARCHIVE ── */ function loadArchive() { api('GET', '/api/newsletters') .then(function(nls) { var el = document.getElementById('archive-list'); var sent = nls.filter(function(n) { return n.sent_at; }); if (!sent.length) { el.innerHTML = '
발송된 뉴스레터가 없습니다
'; return; } var html = ''; sent.forEach(function(n) { var date = new Date(n.sent_at).toLocaleDateString('ko-KR'); var cat = n.category ? '' + n.category + '' : '-'; html += '' + '' + '' + '' + ''; }); html += '
발송일제목카테고리수신자
' + date + '' + n.title + '' + cat + '' + (n.recipient_count || 0) + '명
'; el.innerHTML = html; }) .catch(function(e) { document.getElementById('archive-list').innerHTML = '
불러오기 실패: ' + e.message + '
'; }); } /* ── DETAIL MODAL ── */ var _newsletters = []; function showDetail(id) { api('GET', '/api/newsletters') .then(function(nls) { var nl = nls.find(function(n) { return n.id === id; }); if (!nl) return; document.getElementById('detail-title').textContent = nl.title; var meta = '

' + (nl.category ? '' + nl.category + '' : '') + '발송: ' + new Date(nl.sent_at).toLocaleDateString('ko-KR') + ' | 수신: ' + (nl.recipient_count || 0) + '명

'; document.getElementById('detail-body').innerHTML = meta + '
' + nl.content; document.getElementById('detail-modal').classList.add('show'); }); } function closeDetailModal() { document.getElementById('detail-modal').classList.remove('show'); } /* Close modals on overlay click */ document.querySelectorAll('.modal-overlay').forEach(function(overlay) { overlay.addEventListener('click', function(e) { if (e.target === overlay) { overlay.classList.remove('show'); } }); }); /* Close modals on Escape key */ document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { document.querySelectorAll('.modal-overlay.show').forEach(function(m) { m.classList.remove('show'); }); } });