`;
});
questionsContainer.innerHTML = html;
}
// --- Calculation & Results ---
function calculateStress() {
let totalScore = 0;
const stressorScores = {};
let allAnswered = true;
questions.forEach((q, qIndex) => {
const checked = document.querySelector(`input[name="q${qIndex}"]:checked`);
if (checked) {
const value = parseInt(checked.value);
totalScore += value;
stressorScores[q.id] = value;
} else {
allAnswered = false;
}
});
if (!allAnswered) {
errorMessageDiv.textContent = 'Please answer all questions before calculating.';
errorMessageDiv.style.display = 'block';
return;
}
errorMessageDiv.style.display = 'none';
displayResults(totalScore, stressorScores);
}
function displayResults(score, stressorScores) {
const scoreValueEl = document.getElementById('score-value');
const scoreLevelEl = document.getElementById('score-level');
const scoreInterpretationEl = document.getElementById('score-interpretation');
const gaugeFillEl = document.getElementById('score-gauge-fill');
let level, interpretation, color;
if (score <= 9) {
level = 'Low';
interpretation = 'Your stress levels appear to be low. You seem to have a healthy work environment and good coping mechanisms.';
color = '#22c55e'; // green-500
} else if (score <= 15) {
level = 'Moderate';
interpretation = 'You are experiencing a moderate level of workplace stress. It may be beneficial to identify key stressors and explore coping strategies.';
color = '#f59e0b'; // amber-500
} else if (score <= 20) {
level = 'High';
interpretation = 'Your stress levels are high. It is important to address the sources of your stress and consider seeking support from management, HR, or a mental health professional.';
color = '#ef4444'; // red-500
} else {
level = 'Very High';
interpretation = 'Your stress levels are very high, which can significantly impact your well-being. Proactive steps and seeking professional support are strongly recommended.';
color = '#b91c1c'; // red-700
}
scoreValueEl.textContent = score;
scoreLevelEl.textContent = level;
scoreLevelEl.style.color = color;
scoreInterpretationEl.textContent = interpretation;
const circumference = 549.78; // 2 * pi * 87.5
const percentage = (score - questions.length) / (questions.length * 3); // Normalize score to 0-1
const offset = circumference * (1 - percentage);
gaugeFillEl.style.strokeDashoffset = offset;
gaugeFillEl.style.stroke = color;
renderStressorChart(stressorScores);
resultsSection.style.display = 'block';
resultsSection.scrollIntoView({ behavior: 'smooth' });
}
function renderStressorChart(stressorScores) {
if (state.stressorChart) {
state.stressorChart.destroy();
}
const ctx = document.getElementById('stressor-chart').getContext('2d');
const labels = {
workload: 'Workload',
control: 'Lack of Control',
support: 'Lack of Support',
clarity: 'Unclear Roles',
balance: 'Poor Work-Life Balance',
environment: 'Work Environment'
};
state.stressorChart = new Chart(ctx, {
type: 'radar',
data: {
labels: Object.keys(stressorScores).map(key => labels[key]),
datasets: [{
label: 'Stressor Level',
data: Object.values(stressorScores),
backgroundColor: 'rgba(59, 130, 246, 0.2)',
borderColor: 'rgba(59, 130, 246, 1)',
borderWidth: 2,
pointBackgroundColor: 'rgba(59, 130, 246, 1)',
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
r: {
beginAtZero: true,
min: 0,
max: 4,
stepSize: 1,
angleLines: { color: '#d1d5db' },
grid: { color: '#e5e7eb' },
pointLabels: { font: { size: 12 } }
}
},
plugins: {
legend: { display: false }
}
}
});
}
// --- PDF Generation ---
async function generatePDF() {
const resultsClone = resultsSection.cloneNode(true);
// Style and append clone to be rendered off-screen
resultsClone.style.position = 'absolute';
resultsClone.style.left = '-9999px';
resultsClone.style.top = '0';
resultsClone.style.display = 'block'; // Ensure it's not hidden
document.body.appendChild(resultsClone);
// Re-render chart on the temporary canvas inside the clone for PDF
const tempCanvas = resultsClone.querySelector('canvas');
if (state.stressorChart) {
// Temporarily disable responsiveness for fixed PDF rendering
const originalOptions = Chart.helpers.clone(state.stressorChart.options);
state.stressorChart.options.responsive = false;
state.stressorChart.options.animation = false;
state.stressorChart.update();
// Draw chart to the new canvas
tempCanvas.getContext('2d').drawImage(state.stressorChart.canvas, 0, 0);
// Restore original options
state.stressorChart.options.responsive = originalOptions.responsive;
state.stressorChart.options.animation = originalOptions.animation;
state.stressorChart.update();
}
resultsClone.querySelector('#download-pdf-btn').parentElement.remove();
const { jsPDF } = window.jspdf;
const originalButtonText = downloadPdfBtn.textContent;
downloadPdfBtn.textContent = 'Generating...';
downloadPdfBtn.disabled = true;
try {
const canvas = await html2canvas(resultsClone, { scale: 2, useCORS: true, logging: false });
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF({ orientation: 'portrait', unit: 'px', format: 'a4' });
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = pdf.internal.pageSize.getHeight();
const imgWidth = canvas.width;
const imgHeight = canvas.height;
const ratio = imgWidth / imgHeight;
let finalImgWidth = pdfWidth;
let finalImgHeight = pdfWidth / ratio;
if (finalImgHeight > pdfHeight) {
finalImgHeight = pdfHeight;
finalImgWidth = pdfHeight * ratio;
}
pdf.addImage(imgData, 'PNG', 0, 0, finalImgWidth, finalImgHeight);
pdf.save('Workplace-Stress-Assessment.pdf');
} catch (error) {
console.error("PDF Generation Error:", error);
} finally {
document.body.removeChild(resultsClone); // Clean up the clone
downloadPdfBtn.textContent = 'Download PDF Report';
downloadPdfBtn.disabled = false;
}
}
// --- Event Listeners ---
calculateBtn.addEventListener('click', calculateStress);
downloadPdfBtn.addEventListener('click', generatePDF);
// --- Initial Call ---
renderQuestions();
});
