Public Health Survey Formatter

Public Health Survey Formatter

1. Add/Edit Question

2. Manage Questions

Use the table to edit, delete, or quickly review your survey questions.

Category Question (Preview) Type Action

Go to the "Question Builder" tab to start adding your survey questions.

'; return; } // Group questions by category const categorizedQuestions = questions.reduce((acc, q) => { acc[q.category] = acc[q.category] || []; acc[q.category].push(q); return acc; }, {}); let questionCounter = 1; for (const category in categorizedQuestions) { const categoryDiv = document.createElement('div'); categoryDiv.className = 'draft-category'; categoryDiv.innerHTML = `

${category}

`; categorizedQuestions[category].forEach(q => { const questionDiv = document.createElement('div'); questionDiv.className = 'draft-question'; questionDiv.innerHTML = ` ${questionCounter++}. ${q.text}
${responseTypeMap[q.type].display}
${getFormattedOptions(q)}
`; categoryDiv.appendChild(questionDiv); }); surveyDraftArea.appendChild(categoryDiv); } } function renderQuestionConfigTable() { questionTableBody.innerHTML = ''; questions.forEach(q => { const row = document.createElement('tr'); row.innerHTML = ` ${q.category} ${q.text.substring(0, 50)}... ${responseTypeMap[q.type].display} `; questionTableBody.appendChild(row); }); // Re-render draft whenever the config changes renderSurveyDraft(); } // --- Config Management Functions --- function updateOptionsVisibility() { const type = questionTypeSelect.value; const needsOptions = responseTypeMap[type]?.options; optionsGroup.style.display = needsOptions ? 'flex' : 'none'; // Populate default options if necessary and options are shown if (type === 'likert' && needsOptions) { if (questionOptionsTextarea.value.trim() === '') { questionOptionsTextarea.value = responseTypeMap['likert'].defaultOptions.join('\n'); } } else if (type === 'binary' && needsOptions) { if (questionOptionsTextarea.value.trim() === '') { questionOptionsTextarea.value = responseTypeMap['binary'].defaultOptions.join('\n'); } } } function resetQuestionForm() { questionForm.reset(); questionIdToEditInput.value = ''; questionSaveBtn.textContent = 'Add Question'; questionSaveBtn.style.backgroundColor = 'var(--success-color)'; questionCategorySelect.value = 'Health Behavior'; questionTypeSelect.value = 'multiple_choice_single'; updateOptionsVisibility(); } window.editQuestion = (id) => { const q = questions.find(item => item.id === id); if (q) { questionIdToEditInput.value = q.id; questionTextInput.value = q.text; questionCategorySelect.value = q.category; questionTypeSelect.value = q.type; questionOptionsTextarea.value = q.options.join('\n'); updateOptionsVisibility(); questionSaveBtn.textContent = 'Update Question'; questionSaveBtn.style.backgroundColor = 'var(--primary-color)'; questionForm.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }; function handleSaveQuestion(e) { e.preventDefault(); const type = questionTypeSelect.value; const needsOptions = responseTypeMap[type]?.options; const questionData = { id: questionIdToEditInput.value || `q_${Date.now()}`, text: questionTextInput.value, category: questionCategorySelect.value, type: type, options: needsOptions ? questionOptionsTextarea.value.split('\n').map(opt => opt.trim()).filter(opt => opt !== '') : [] }; if (questionIdToEditInput.value) { // Update existing const index = questions.findIndex(s => s.id === questionIdToEditInput.value); if (index !== -1) { questions[index] = questionData; } } else { // Add new questions.push(questionData); } renderQuestionConfigTable(); resetQuestionForm(); } window.deleteQuestion = (id) => { if (confirm('Are you sure you want to delete this question?')) { questions = questions.filter(q => q.id !== id); renderQuestionConfigTable(); if (questionIdToEditInput.value === id) { resetQuestionForm(); } } }; // --- PDF Functions --- function downloadPDF() { const { jsPDF } = window.jspdf; const doc = new jsPDF('p', 'pt', 'a4'); const finalY = 40; let currentY = finalY; const margin = 30; doc.setFontSize(20); doc.text("Public Health Survey Draft", margin, currentY); currentY += 10; doc.setFontSize(10); doc.text("Formatted for Data Collection Standardization", margin, currentY); currentY += 20; const checkPageBreak = (spaceNeeded) => { if (currentY + spaceNeeded > doc.internal.pageSize.height - margin) { doc.addPage(); currentY = margin; } }; const categorizedQuestions = questions.reduce((acc, q) => { acc[q.category] = acc[q.category] || []; acc[q.category].push(q); return acc; }, {}); let questionCounter = 1; doc.setFont('helvetica', 'normal'); for (const category in categorizedQuestions) { checkPageBreak(25); doc.setFontSize(14); doc.setFont('helvetica', 'bold'); doc.setTextColor(0, 123, 255); // Primary color doc.text(category.toUpperCase(), margin, currentY); doc.setLineWidth(0.5); doc.setDrawColor(0, 123, 255); doc.line(margin, currentY + 3, doc.internal.pageSize.width - margin, currentY + 3); currentY += 15; doc.setTextColor(51, 51, 51); // Font color categorizedQuestions[category].forEach(q => { const questionText = `${questionCounter++}. ${q.text}`; const typeText = `[Type: ${responseTypeMap[q.type].display}]`; const optionsText = `Options: ${getFormattedOptions(q)}`; // Question Text checkPageBreak(30); doc.setFontSize(11); doc.setFont('helvetica', 'bold'); let lines = doc.splitTextToSize(questionText, doc.internal.pageSize.width - margin * 2 - 10); doc.text(lines, margin + 5, currentY); currentY += (lines.length * 10) + 2; // Type and Options doc.setFontSize(10); doc.setFont('helvetica', 'italic'); doc.setTextColor(100, 100, 100); lines = doc.splitTextToSize(typeText, doc.internal.pageSize.width - margin * 2 - 20); doc.text(lines, margin + 15, currentY); currentY += (lines.length * 8) + 2; doc.setFont('helvetica', 'normal'); lines = doc.splitTextToSize(optionsText, doc.internal.pageSize.width - margin * 2 - 20); doc.text(lines, margin + 15, currentY); currentY += (lines.length * 8) + 8; // Extra padding after question doc.setTextColor(51, 51, 51); }); } doc.save('public-health-survey-draft.pdf'); } // --- Tab Navigation --- function switchTab(tabIndex) { tabs.forEach((tab, index) => { tab.classList.toggle('active', index === tabIndex); contents[index].classList.toggle('active', index === tabIndex); }); currentTab = tabIndex; updateNavButtons(); } function updateNavButtons() { prevBtn.disabled = currentTab === 0; nextBtn.disabled = currentTab === tabs.length - 1; } tabs.forEach((tab, index) => { tab.addEventListener('click', () => { // Re-render draft whenever the config tab is left if (index === 1) renderQuestionConfigTable(); switchTab(index); }); }); nextBtn.addEventListener('click', () => { if (currentTab === 1) renderQuestionConfigTable(); if (currentTab < tabs.length - 1) switchTab(currentTab + 1); }); prevBtn.addEventListener('click', () => { if (currentTab > 0) switchTab(currentTab - 1); }); // --- Event Listeners --- questionTypeSelect.addEventListener('change', updateOptionsVisibility); questionForm.addEventListener('submit', handleSaveQuestion); pdfDownloadBtn.addEventListener('click', downloadPDF); // --- Initial Setup --- populateDefaultData(); renderQuestionConfigTable(); // Renders table and initial draft updateOptionsVisibility(); updateNavButtons(); });
Scroll to Top