var WriteKit = (function() { 'use strict'; let config = {}; let user = null; async function init(opts) { config = opts; try { const res = await fetch('/api/reader/me'); const data = await res.json(); if (data.logged_in) { user = data.user; } } catch (e) {} if (config.reactions) initReactions(); if (config.comments) initComments(); } async function initReactions() { const container = document.querySelector('.reactions-container'); if (!container) return; const res = await fetch(`/api/reader/posts/${config.slug}/reactions`); const data = await res.json(); const counts = data.counts || {}; const userReactions = data.user || []; if (config.reactionMode === 'upvote') { const emoji = config.reactionEmojis[0] || '👍'; const count = counts[emoji] || 0; const active = userReactions.includes(emoji); container.innerHTML = ` `; } else { container.innerHTML = config.reactionEmojis.map(emoji => { const count = counts[emoji] || 0; const active = userReactions.includes(emoji); return ` `; }).join(''); } container.querySelectorAll('.reaction-btn').forEach(btn => { btn.addEventListener('click', () => toggleReaction(btn)); }); } async function toggleReaction(btn) { if (config.requireAuth && !user) { showAuthPrompt('reactions'); return; } const emoji = btn.dataset.emoji; try { const res = await fetch(`/api/reader/posts/${config.slug}/reactions`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ emoji }) }); if (res.status === 401) { showAuthPrompt('reactions'); return; } const data = await res.json(); const countEl = btn.querySelector('.count'); const current = parseInt(countEl.textContent) || 0; if (data.added) { btn.classList.add('active'); countEl.textContent = current + 1; } else { btn.classList.remove('active'); countEl.textContent = Math.max(0, current - 1); } } catch (e) { console.error('Failed to toggle reaction', e); } } async function initComments() { const section = document.querySelector('.comments'); if (!section) return; const list = section.querySelector('.comments-list'); const formContainer = section.querySelector('.comment-form-container'); const res = await fetch(`/api/reader/posts/${config.slug}/comments`); const comments = await res.json(); if (comments && comments.length > 0) { list.innerHTML = comments.map(renderComment).join(''); } else { list.innerHTML = '

No comments yet. Be the first!

'; } if (user) { formContainer.innerHTML = `
`; formContainer.querySelector('form').addEventListener('submit', submitComment); } else { formContainer.innerHTML = `
Sign in to leave a comment
`; } } function renderComment(comment) { const date = new Date(comment.created_at).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' }); return `
${comment.avatar_url ? `` : ''} ${escapeHtml(comment.name || 'Anonymous')} ${date}
${comment.content_html || escapeHtml(comment.content)}
`; } async function submitComment(e) { e.preventDefault(); const form = e.target; const textarea = form.querySelector('textarea'); const content = textarea.value.trim(); if (!content) return; const btn = form.querySelector('button'); btn.disabled = true; btn.textContent = 'Posting...'; try { const res = await fetch(`/api/reader/posts/${config.slug}/comments`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ content }) }); if (res.status === 401) { showAuthPrompt('comments'); return; } const comment = await res.json(); const list = document.querySelector('.comments-list'); const noComments = list.querySelector('.no-comments'); if (noComments) noComments.remove(); list.insertAdjacentHTML('beforeend', renderComment(comment)); textarea.value = ''; } catch (e) { console.error('Failed to post comment', e); } finally { btn.disabled = false; btn.textContent = 'Post Comment'; } } function showAuthPrompt(feature) { alert(`Please sign in to use ${feature}`); } function escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } return { init }; })();