/** * Admin Walk Sheet Module * Handles walk sheet configuration, preview generation, QR codes, and printing */ // Walk sheet state let storedQRCodes = {}; // Save walk sheet configuration async function saveWalkSheetConfig() { const config = { walk_sheet_title: document.getElementById('walk-sheet-title')?.value || '', walk_sheet_subtitle: document.getElementById('walk-sheet-subtitle')?.value || '', walk_sheet_footer: document.getElementById('walk-sheet-footer')?.value || '', qr_code_1_url: document.getElementById('qr-code-1-url')?.value || '', qr_code_1_label: document.getElementById('qr-code-1-label')?.value || '', qr_code_2_url: document.getElementById('qr-code-2-url')?.value || '', qr_code_2_label: document.getElementById('qr-code-2-label')?.value || '', qr_code_3_url: document.getElementById('qr-code-3-url')?.value || '', qr_code_3_label: document.getElementById('qr-code-3-label')?.value || '' }; console.log('Saving walk sheet config:', config); // Show loading state const saveButton = document.getElementById('save-walk-sheet'); if (!saveButton) { window.adminCore.showStatus('Save button not found', 'error'); return; } const originalText = saveButton.textContent; saveButton.textContent = 'Saving...'; saveButton.disabled = true; try { const response = await fetch('/api/admin/walk-sheet-config', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(config) }); const data = await response.json(); console.log('Save response:', data); if (data.success) { window.adminCore.showStatus('Walk sheet configuration saved successfully!', 'success'); console.log('Configuration saved successfully'); // Don't reload config here - the form already has the latest values // Just regenerate the preview generateWalkSheetPreview(); } else { throw new Error(data.error || 'Failed to save'); } } catch (error) { console.error('Save error:', error); window.adminCore.showStatus(error.message || 'Failed to save walk sheet configuration', 'error'); } finally { saveButton.textContent = originalText; saveButton.disabled = false; } } // Generate walk sheet preview function generateWalkSheetPreview() { const title = document.getElementById('walk-sheet-title')?.value || 'Campaign Walk Sheet'; const subtitle = document.getElementById('walk-sheet-subtitle')?.value || 'Door-to-Door Canvassing Form'; const footer = document.getElementById('walk-sheet-footer')?.value || 'Thank you for your support!'; let previewHTML = `

${window.adminCore.escapeHtml(title)}

${window.adminCore.escapeHtml(subtitle)}

`; // Add QR codes section const qrCodesHTML = []; for (let i = 1; i <= 3; i++) { const urlInput = document.getElementById(`qr-code-${i}-url`); const labelInput = document.getElementById(`qr-code-${i}-label`); const url = urlInput?.value || ''; const label = labelInput?.value || ''; if (url) { qrCodesHTML.push(`
${window.adminCore.escapeHtml(label || `QR Code ${i}`)}
`); } } if (qrCodesHTML.length > 0) { previewHTML += `
${qrCodesHTML.join('')}
`; } // Add form fields based on the main map form previewHTML += `
1 2 3 4
Y Yes N No
R L U
Notes & Comments
`; // Add footer if (footer) { previewHTML += ` `; } // Update preview const previewContent = document.getElementById('walk-sheet-preview-content'); if (previewContent) { previewContent.innerHTML = previewHTML; // Generate QR codes after DOM is updated setTimeout(() => { generatePreviewQRCodes(); }, 100); } else { console.warn('Walk sheet preview content container not found'); } } // Generate QR codes for preview async function generatePreviewQRCodes() { for (let i = 1; i <= 3; i++) { const urlInput = document.getElementById(`qr-code-${i}-url`); const url = urlInput?.value || ''; const qrContainer = document.getElementById(`preview-qr-${i}`); if (url && qrContainer) { try { // Use our local QR code generation endpoint with size matching display const qrImageUrl = `/api/qr?text=${encodeURIComponent(url)}&size=200`; // Generate at higher res qrContainer.innerHTML = `QR Code ${i}`; // Display smaller } catch (error) { console.error(`Failed to display QR code ${i}:`, error); qrContainer.innerHTML = '
QR Error
'; } } else if (qrContainer) { // Clear empty QR containers qrContainer.innerHTML = ''; } } } // Print walk sheet function printWalkSheet() { // First generate fresh preview to ensure QR codes are generated generateWalkSheetPreview(); // Wait for QR codes to generate, then print setTimeout(() => { const previewContent = document.getElementById('walk-sheet-preview-content'); if (!previewContent) return; const clonedContent = previewContent.cloneNode(true); // Convert canvas elements to images for printing const canvases = previewContent.querySelectorAll('canvas'); const clonedCanvases = clonedContent.querySelectorAll('canvas'); canvases.forEach((canvas, index) => { if (canvas && clonedCanvases[index]) { const img = document.createElement('img'); img.src = canvas.toDataURL('image/png'); img.width = canvas.width; img.height = canvas.height; img.style.width = canvas.style.width || `${canvas.width}px`; img.style.height = canvas.style.height || `${canvas.height}px`; clonedCanvases[index].parentNode.replaceChild(img, clonedCanvases[index]); } }); // Create a print-specific window const printWindow = window.open('', '_blank'); printWindow.document.write(` Walk Sheet - Print
${clonedContent.innerHTML}
`); printWindow.document.close(); printWindow.onload = function() { setTimeout(() => { printWindow.print(); // User can close manually after printing }, 500); }; }, 1000); // Give QR codes time to generate } // Load walk sheet configuration async function loadWalkSheetConfig() { try { console.log('Loading walk sheet config...'); const response = await fetch('/api/admin/walk-sheet-config'); const data = await response.json(); console.log('Loaded walk sheet config:', data); if (data.success) { // The config object contains the actual configuration const config = data.config || {}; console.log('Config object:', config); // Populate form fields - use the exact field names from the backend const titleInput = document.getElementById('walk-sheet-title'); const subtitleInput = document.getElementById('walk-sheet-subtitle'); const footerInput = document.getElementById('walk-sheet-footer'); console.log('Found form elements:', { title: !!titleInput, subtitle: !!subtitleInput, footer: !!footerInput }); if (titleInput) { titleInput.value = config.walk_sheet_title || 'Campaign Walk Sheet'; console.log('Set title to:', titleInput.value); } if (subtitleInput) { subtitleInput.value = config.walk_sheet_subtitle || 'Door-to-Door Canvassing Form'; console.log('Set subtitle to:', subtitleInput.value); } if (footerInput) { footerInput.value = config.walk_sheet_footer || 'Thank you for your support!'; console.log('Set footer to:', footerInput.value); } // Populate QR code fields for (let i = 1; i <= 3; i++) { const urlField = document.getElementById(`qr-code-${i}-url`); const labelField = document.getElementById(`qr-code-${i}-label`); console.log(`QR ${i} fields found:`, { url: !!urlField, label: !!labelField }); if (urlField) { urlField.value = config[`qr_code_${i}_url`] || ''; console.log(`Set QR ${i} URL to:`, urlField.value); } if (labelField) { labelField.value = config[`qr_code_${i}_label`] || ''; console.log(`Set QR ${i} label to:`, labelField.value); } } return true; } else { console.error('Failed to load config:', data.error); window.adminCore.showStatus('Failed to load walk sheet configuration', 'error'); return false; } } catch (error) { console.error('Failed to load walk sheet config:', error); window.adminCore.showStatus('Failed to load walk sheet configuration', 'error'); return false; } } // Check if walk sheet section is visible and load config if needed function checkAndLoadWalkSheetConfig() { const walkSheetSection = document.getElementById('walk-sheet'); if (walkSheetSection && walkSheetSection.style.display !== 'none') { console.log('Walk sheet section is visible, loading config...'); loadWalkSheetConfig().then((success) => { if (success) { generateWalkSheetPreview(); } }); } } // Setup walk sheet event listeners function setupWalkSheetEventListeners() { // Walk Sheet buttons const saveWalkSheetBtn = document.getElementById('save-walk-sheet'); const previewWalkSheetBtn = document.getElementById('preview-walk-sheet'); const printWalkSheetBtn = document.getElementById('print-walk-sheet'); const refreshPreviewBtn = document.getElementById('refresh-preview'); if (saveWalkSheetBtn) saveWalkSheetBtn.addEventListener('click', saveWalkSheetConfig); if (previewWalkSheetBtn) previewWalkSheetBtn.addEventListener('click', generateWalkSheetPreview); if (printWalkSheetBtn) printWalkSheetBtn.addEventListener('click', printWalkSheet); if (refreshPreviewBtn) refreshPreviewBtn.addEventListener('click', generateWalkSheetPreview); // Auto-update preview on input change const walkSheetInputs = document.querySelectorAll( '#walk-sheet-title, #walk-sheet-subtitle, #walk-sheet-footer, ' + '[id^="qr-code-"][id$="-url"], [id^="qr-code-"][id$="-label"]' ); walkSheetInputs.forEach(input => { if (input) { input.addEventListener('input', window.adminCore.debounce(() => { generateWalkSheetPreview(); }, 500)); } }); // Add URL change listeners to detect when QR codes need regeneration for (let i = 1; i <= 3; i++) { const urlInput = document.getElementById(`qr-code-${i}-url`); if (urlInput) { let previousUrl = urlInput.value; urlInput.addEventListener('change', () => { const currentUrl = urlInput.value; if (currentUrl !== previousUrl) { console.log(`QR Code ${i} URL changed from "${previousUrl}" to "${currentUrl}"`); // Remove stored QR code so it gets regenerated delete storedQRCodes[currentUrl]; previousUrl = currentUrl; generateWalkSheetPreview(); } }); } } } // Export walk sheet functions window.adminWalkSheet = { saveWalkSheetConfig, generateWalkSheetPreview, printWalkSheet, loadWalkSheetConfig, checkAndLoadWalkSheetConfig, setupWalkSheetEventListeners };