/** * Scheduling Poll Block Hydration for MkDocs * * Scans for .scheduling-poll-block elements, fetches poll data from the API, * and renders a read-only poll summary with a "Vote Now" link to the full * interactive voting page on the app. * * Follows the gancio-events.js hydration pattern. */ (function () { 'use strict'; function getApiUrl() { // env-config.js injects these globals if (window.PAYMENT_API_URL) return window.PAYMENT_API_URL; if (window.API_URL) return window.API_URL; var host = window.location.hostname; if (host !== 'localhost' && host.indexOf('.') !== -1) { var parts = host.split('.'); var base = parts.slice(-2).join('.'); return window.location.protocol + '//api.' + base; } return 'http://localhost:4000'; } function getAppUrl() { if (window.APP_URL) return window.APP_URL; var host = window.location.hostname; if (host !== 'localhost' && host.indexOf('.') !== -1) { var parts = host.split('.'); var base = parts.slice(-2).join('.'); return window.location.protocol + '//app.' + base; } return 'http://localhost:3000'; } var STATUS_COLORS = { OPEN: '#52c41a', CLOSED: '#fa8c16', FINALIZED: '#1890ff', CANCELLED: '#ff4d4f', }; var STATUS_LABELS = { OPEN: 'Open for Voting', CLOSED: 'Closed', FINALIZED: 'Date Confirmed', CANCELLED: 'Cancelled', }; function formatDate(dateStr) { var d = new Date(dateStr + 'T00:00:00'); var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; return days[d.getDay()] + ', ' + months[d.getMonth()] + ' ' + d.getDate(); } function hydrateBlocks() { var blocks = document.querySelectorAll('.scheduling-poll-block'); if (blocks.length === 0) return; var apiUrl = getApiUrl(); var appUrl = getAppUrl(); blocks.forEach(function (block) { // Skip if already hydrated if (block.getAttribute('data-hydrated') === 'true') return; var slug = block.getAttribute('data-poll-slug'); if (!slug) return; var showComments = block.getAttribute('data-show-comments') !== 'false'; var title = block.getAttribute('data-title') || ''; block.setAttribute('data-hydrated', 'true'); block.innerHTML = '
Loading poll...
'; fetch(apiUrl + '/api/meeting-planner/public/' + encodeURIComponent(slug)) .then(function (res) { if (!res.ok) throw new Error('Poll not found'); return res.json(); }) .then(function (poll) { var statusColor = STATUS_COLORS[poll.status] || '#666'; var statusLabel = STATUS_LABELS[poll.status] || poll.status; var isFinalized = poll.status === 'FINALIZED'; var options = poll.options || []; var bestScore = 0; options.forEach(function (o) { if ((o.score || 0) > bestScore) bestScore = o.score || 0; }); var html = ''; // Title if (title) { html += '

' + title + '

'; } // Poll title + status html += '

' + poll.title + '

'; if (poll.description) { html += '

' + poll.description + '

'; } html += '
'; html += '' + statusLabel + ''; if (poll.location) { html += ' ' + poll.location + ''; } html += '
'; // Finalized banner if (isFinalized && poll.finalizedOption) { html += '
'; html += 'Confirmed: ' + formatDate(poll.finalizedOption.date) + ' — ' + poll.finalizedOption.startTime + '–' + poll.finalizedOption.endTime; html += '
'; } // Options table if (options.length > 0) { html += '
'; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; options.forEach(function (opt) { var isBest = bestScore > 0 && (opt.score || 0) === bestScore; var isConfirmed = isFinalized && poll.finalizedOptionId === opt.id; var rowBg = isConfirmed ? 'rgba(82,196,26,0.08)' : isBest ? 'rgba(82,196,26,0.04)' : ''; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; }); html += '
Date / TimeYesIf Need BeNoScore
'; html += '' + formatDate(opt.date) + '
' + opt.startTime + '–' + opt.endTime + ''; if (isConfirmed) html += ' '; html += '
' + (opt.yesCount || 0) + '' + (opt.ifNeedBeCount || 0) + '' + (opt.noCount || 0) + '' + (opt.score || 0) + '
'; } // Comments count if (showComments && poll.comments && poll.comments.length > 0) { html += '

' + poll.comments.length + ' comment' + (poll.comments.length !== 1 ? 's' : '') + '

'; } // Vote Now CTA if (poll.status === 'OPEN') { html += '
'; html += ''; }) .catch(function () { block.innerHTML = '
' + '

Poll unavailable

' + '
View poll →' + '
'; }); }); } // Initial hydration if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', hydrateBlocks); } else { hydrateBlocks(); } // Re-hydrate on MkDocs SPA navigation if (typeof document$ !== 'undefined') { document$.subscribe(function () { setTimeout(hydrateBlocks, 100); }); } })();