Deep Sleep Duration Tracker

Deep Sleep Duration Tracker

Your Sleep Dashboard

Avg. Deep Sleep

0%

Avg. Deep Sleep Time

0h 0m

Total Nights Logged

0

Recent Deep Sleep (minutes)

Log sleep data to see your chart.

Sleep Log Details

Date Total Sleep Deep Sleep Deep Sleep %
No sleep logged.

Log sleep data to see your chart.

'; resultsTableBody.innerHTML = 'No sleep logged.'; return; } // Calculations const totalNights = sleepLog.length; const totalDeepSleepMins = sleepLog.reduce((sum, log) => sum + log.deepSleepMins, 0); const totalPercent = sleepLog.reduce((sum, log) => sum + log.deepSleepPercent, 0); const avgDeepMins = Math.round(totalDeepSleepMins / totalNights); const avgPercent = Math.round(totalPercent / totalNights); // Update summary cards avgPercentEl.innerHTML = `${avgPercent}%`; avgDurationEl.innerHTML = `${Math.floor(avgDeepMins / 60)}h ${avgDeepMins % 60}m`; totalNightsEl.textContent = totalNights; // Sort by date for chart and table const sortedLog = [...sleepLog].sort((a, b) => new Date(a.date) - new Date(b.date)); // Update table resultsTableBody.innerHTML = ''; [...sortedLog].reverse().forEach(log => { // Show most recent first in table const row = resultsTableBody.insertRow(); const formattedDate = new Date(log.date).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: '2-digit' }); row.innerHTML = ` ${formattedDate} ${formatMins(log.totalSleepMins)} ${formatMins(log.deepSleepMins)} ${log.deepSleepPercent}% `; }); // Update chart (last 7 entries) const chartData = sortedLog.slice(-7); const maxDuration = Math.max(...chartData.map(d => d.deepSleepMins), 1); sleepChart.innerHTML = ''; chartData.forEach(log => { const barHeight = (log.deepSleepMins / maxDuration) * 100; const formattedDate = new Date(log.date).toLocaleDateString('en-US', { month: 'short', day: 'numeric' }); const barWrapper = document.createElement('div'); barWrapper.className = 'chart-bar-wrapper'; barWrapper.innerHTML = `
${formatMinsForChart(log.deepSleepMins)}
${formattedDate}
`; sleepChart.appendChild(barWrapper); }); } // --- TAB NAVIGATION --- window.changeTab = function(tabNumber) { if (tabNumber === currentTab) return; if (tabNumber === 1) { calculateAndDisplayDashboard(); } document.getElementById(`tab-panel-${currentTab}`).classList.add('hidden'); document.getElementById(`tab-btn-${currentTab}`).classList.remove('active'); document.getElementById(`tab-btn-${currentTab}`).classList.add('inactive'); document.getElementById(`tab-panel-${tabNumber}`).classList.remove('hidden'); document.getElementById(`tab-btn-${tabNumber}`).classList.add('active'); document.getElementById(`tab-btn-${tabNumber}`).classList.remove('inactive'); currentTab = tabNumber; updateNavButtons(); }; window.navigateTabs = function(direction) { const newTab = direction === 'next' ? currentTab + 1 : currentTab - 1; if (newTab >= 1 && newTab <= 2) { changeTab(newTab); } }; function updateNavButtons() { prevBtn.disabled = (currentTab === 1); nextBtn.disabled = (currentTab === 2); } // --- PDF GENERATION --- function generatePdf() { const contentToPrint = document.getElementById('pdf-content-container'); const pdfButtonWrapper = document.getElementById('pdf-button-wrapper'); if (sleepLog.length === 0) { alert("Dashboard is empty. There is nothing to download."); return; } if (pdfButtonWrapper) pdfButtonWrapper.style.display = 'none'; html2canvas(contentToPrint, { scale: 2, useCORS: true, logging: false }) .then(canvas => { if (pdfButtonWrapper) pdfButtonWrapper.style.display = 'block'; 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 pdfHeight = pdf.internal.pageSize.getHeight(); const canvasAspectRatio = canvas.width / canvas.height; let imgWidth = pdfWidth - 80; // 40pt margins let imgHeight = imgWidth / canvasAspectRatio; if (imgHeight > pdfHeight - 80) { imgHeight = pdfHeight - 80; imgWidth = imgHeight * canvasAspectRatio; } const x = (pdfWidth - imgWidth) / 2; const y = 40; pdf.addImage(imgData, 'PNG', x, y, imgWidth, imgHeight); pdf.save('Deep-Sleep-Dashboard.pdf'); }).catch(err => { if (pdfButtonWrapper) pdfButtonWrapper.style.display = 'block'; console.error("Error generating PDF:", err); alert("Sorry, an error occurred while creating the PDF."); }); } // --- START THE APP --- initialize(); });
Scroll to Top