Meditation & Breathwork Progress Tracker

Meditation & Breathwork Progress Tracker

Log a New Session

Record your practice to track your progress.

Log a session to see your dashboard!

'; return; } chartCanvas.style.display = 'block'; const labels = sessionData.map(d => d.date); if (progressChart) { progressChart.destroy(); } const meditationData = sessionData.map(d => d.type === 'Meditation' ? { x: d.date, y: d.duration } : { x: d.date, y: null }); const breathworkData = sessionData.map(d => d.type === 'Breathwork' ? { x: d.date, y: d.duration } : { x: d.date, y: null }); const ctx = chartCanvas.getContext('2d'); progressChart = new Chart(ctx, { type: 'line', data: { labels: labels, datasets: [ { label: 'Meditation (mins)', data: meditationData, borderColor: '#38bdf8', backgroundColor: 'rgba(56, 189, 248, 0.1)', tension: 0.1, fill: true }, { label: 'Breathwork (mins)', data: breathworkData, borderColor: '#34d399', backgroundColor: 'rgba(52, 211, 153, 0.1)', tension: 0.1, fill: true } ] }, options: { responsive: true, maintainAspectRatio: false, scales: { x: { type: 'time', time: { unit: 'day', tooltipFormat: 'MMM d, yyyy' } }, y: { beginAtZero: true, title: { display: true, text: 'Duration (minutes)' } } } } }); renderSummaryStats(); }; const renderSummaryStats = () => { const totalMinutes = sessionData.reduce((acc, d) => acc + d.duration, 0); const totalSessions = sessionData.length; const avgDuration = totalSessions > 0 ? totalMinutes / totalSessions : 0; const meditationMinutes = sessionData.filter(d => d.type === 'Meditation').reduce((acc, d) => acc + d.duration, 0); const breathworkMinutes = sessionData.filter(d => d.type === 'Breathwork').reduce((acc, d) => acc + d.duration, 0); summaryStatsContainer.innerHTML = `

Total Minutes

${totalMinutes}

Total Sessions

${totalSessions}

Meditation Mins

${meditationMinutes}

Breathwork Mins

${breathworkMinutes}

`; }; const downloadPDF = () => { if (sessionData.length === 0) { alert('No data to generate a report.'); return; } const dashboardContent = document.getElementById('dashboard-content'); window.html2canvas(dashboardContent, { scale: 2, backgroundColor: '#ffffff' }).then(canvas => { const imgData = canvas.toDataURL('image/png'); const { jsPDF } = window.jspdf; const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfMargin = 40; const contentWidth = pdfWidth - (pdfMargin * 2); const imgHeight = canvas.height * contentWidth / canvas.width; pdf.setFontSize(22).setFont('helvetica', 'bold'); pdf.text('Meditation & Breathwork Progress Report', pdfWidth / 2, pdfMargin, { align: 'center' }); pdf.setFontSize(12).setFont('helvetica', 'normal'); pdf.text(`Report Generated: ${new Date().toLocaleDateString('en-US')}`, pdfWidth / 2, pdfMargin + 20, { align: 'center' }); pdf.addImage(imgData, 'PNG', pdfMargin, pdfMargin + 40, contentWidth, imgHeight); pdf.save('Meditation_Progress_Report.pdf'); }); }; const initialize = () => { loadData(); renderDashboard(); logForm.addEventListener('submit', addLogEntry); downloadPdfBtn.addEventListener('click', downloadPDF); logDateInput.valueAsDate = new Date(); }; initialize(); }); function switchTab(tabId) { document.getElementById('log-tab').style.display = (tabId === 'log') ? 'block' : 'none'; document.getElementById('dashboard-tab').style.display = (tabId === 'dashboard') ? 'block' : 'none'; document.getElementById('tab-log-btn').classList.toggle('active', tabId === 'log'); document.getElementById('tab-dashboard-btn').classList.toggle('active', tabId === 'dashboard'); }
Scroll to Top