Blood Pressure Chart Analyzer

Blood Pressure Chart Analyzer

Log your readings to visualize trends and understand your numbers.

Add a New Reading

Your Readings

No readings added yet. Use the form above to start.

Analysis

Add at least one reading to see an analysis.

${r.date.toLocaleString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit', hour12: true })}

`; el.querySelector('.remove-item-btn').onclick = () => removeReading(r.id); readingsList.prepend(el); // Add newest to the top }); } } // --- ANALYSIS LOGIC --- function getBPCategory(sys, dia) { if (sys > 180 || dia > 120) return { name: "Hypertensive Crisis", color: "#b91c1c", advice: "Consult your doctor immediately. This is a medical emergency." }; if (sys >= 140 || dia >= 90) return { name: "Hypertension Stage 2", color: "#dc2626", advice: "Your blood pressure is consistently high. It's important to talk to your doctor about a treatment plan." }; if (sys >= 130 || dia >= 80) return { name: "Hypertension Stage 1", color: "#f97316", advice: "Your blood pressure is elevated. Lifestyle changes are recommended and your doctor may consider medication." }; if (sys >= 120) return { name: "Elevated", color: "#facc15", advice: "Your blood pressure is higher than normal. Focus on healthy lifestyle habits to prevent hypertension." }; return { name: "Normal", color: "#16a34a", advice: "Your blood pressure is in the healthy range. Keep up the great work with your lifestyle habits!" }; } function analyzeReadings() { if (bpReadings.length === 0) { analysisPlaceholder.classList.remove('hidden'); analysisContent.classList.add('hidden'); return; } analysisPlaceholder.classList.add('hidden'); analysisContent.classList.remove('hidden'); const latestReading = bpReadings[bpReadings.length - 1]; const category = getBPCategory(latestReading.systolic, latestReading.diastolic); const avgSystolic = bpReadings.reduce((sum, r) => sum + r.systolic, 0) / bpReadings.length; const avgDiastolic = bpReadings.reduce((sum, r) => sum + r.diastolic, 0) / bpReadings.length; const avgCategory = getBPCategory(avgSystolic, avgDiastolic); analysisContent.innerHTML = `

Latest Reading: ${category.name}

${category.advice}

Overall Average: ${avgSystolic.toFixed(0)} / ${avgDiastolic.toFixed(0)} mmHg

Your average reading falls into the ${avgCategory.name} category.

`; } // --- CHARTING LOGIC --- function createChart() { const ctx = document.getElementById('bpChart').getContext('2d'); bpChart = new Chart(ctx, { type: 'line', data: { datasets: [ { label: 'Systolic', data: [], borderColor: '#3b82f6', backgroundColor: '#3b82f6', tension: 0.1, pointRadius: 5 }, { label: 'Diastolic', data: [], borderColor: '#16a34a', backgroundColor: '#16a34a', tension: 0.1, pointRadius: 5 } ] }, options: { responsive: true, plugins: { title: { display: true, text: 'Blood Pressure Trend', font: { size: 18 } }, tooltip: { callbacks: { title: (context) => new Date(context[0].parsed.x).toLocaleDateString(), label: (context) => `${context.dataset.label}: ${context.parsed.y} mmHg` } } }, scales: { x: { type: 'time', time: { unit: 'day' }, title: { display: true, text: 'Date' } }, y: { title: { display: true, text: 'Pressure (mmHg)' }, beginAtZero: false, suggestedMin: 60, suggestedMax: 160 } } } }); updateChart(); } function updateChart() { if (!bpChart) return; bpChart.data.datasets[0].data = bpReadings.map(r => ({ x: r.date.getTime(), y: r.systolic })); bpChart.data.datasets[1].data = bpReadings.map(r => ({ x: r.date.getTime(), y: r.diastolic })); bpChart.update(); } // --- PDF DOWNLOAD LOGIC --- async function downloadPDF() { pdfLoader.classList.remove('hidden'); pdfDownloadBtn.disabled = true; const { jsPDF } = window.jspdf; const pdfExportContent = document.getElementById('pdf-export-area'); // 1. Prepare Chart Image const chartImage = bpChart.toBase64Image('image/png', 1.0); // 2. Prepare Table HTML let readingsHtml = bpReadings.map(r => { const category = getBPCategory(r.systolic, r.diastolic); return ` ${r.date.toLocaleDateString('en-US')} ${r.date.toLocaleTimeString('en-US', {hour: '2-digit', minute:'2-digit'})} ${r.systolic} ${r.diastolic} ${category.name} `; }).join(''); // 3. Populate export area pdfExportContent.innerHTML = `

Blood Pressure Report

Generated on: ${new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })}

Trend Chart

Readings Log

${readingsHtml}
Date & Time Systolic Diastolic Category
`; await new Promise(resolve => setTimeout(resolve, 100)); try { const canvas = await html2canvas(pdfExportContent, { scale: 2 }); const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: "portrait", unit: "pt", format: "a4" }); const pageWidth = pdf.internal.pageSize.getWidth(); const pageHeight = pdf.internal.pageSize.getHeight(); const margin = 40; const imgProps = pdf.getImageProperties(imgData); const pdfImageWidth = pageWidth - (margin * 2); const pdfImageHeight = (imgProps.height * pdfImageWidth) / imgProps.width; let heightLeft = pdfImageHeight; let position = margin; pdf.addImage(imgData, 'PNG', margin, position, pdfImageWidth, pdfImageHeight); heightLeft -= (pageHeight - 2 * margin); while (heightLeft > 0) { position = heightLeft - pdfImageHeight; pdf.addPage(); pdf.addImage(imgData, 'PNG', margin, position, pdfImageWidth, pdfImageHeight); heightLeft -= pageHeight; } pdf.save(`Blood-Pressure-Report-${new Date().toISOString().slice(0,10)}.pdf`); } catch (error) { console.error("Error generating PDF:", error); alert("Sorry, there was an error creating the PDF."); } finally { pdfLoader.classList.add('hidden'); pdfDownloadBtn.disabled = false; pdfExportContent.innerHTML = ''; } } // --- START THE APP --- initialize(); });
Scroll to Top