Caffeine Consumption & Sleep Impact Analyzer

Caffeine Consumption & Sleep Impact Analyzer

Step 1: Log Your Caffeine Intake and Sleep

Caffeine Intake

Sleep Details

Average is 4-6 hours. Adjust if you feel you metabolize caffeine faster or slower.

${advice}

`; } /** * Generates and displays the caffeine decay chart. * @param {number} halfLife - The user's caffeine half-life. * @param {string} bedtime - The user's bedtime. */ function generateChart(halfLife, bedtime) { const chartContainer = document.getElementById('results-chart'); if (!chartContainer) return; chartContainer.style.display = 'block'; const ctx = document.getElementById('caffeineChart').getContext('2d'); const labels = []; const dataPoints = []; const totalHours = 24; const timeStep = 1; // 1 hour interval for (let h = 0; h <= totalHours; h += timeStep) { let totalCaffeineNow = 0; state.userIntake.forEach(intake => { const intakeDate = new Date(`1970-01-01T${intake.time}`); const currentDate = new Date(intakeDate.getTime() + h * 60 * 60 * 1000); const hoursSinceThisIntake = (currentDate - intakeDate) / (1000 * 60 * 60); if (hoursSinceThisIntake >= 0) { totalCaffeineNow += intake.amount * Math.pow(0.5, hoursSinceThisIntake / halfLife); } }); const firstIntakeTime = new Date(`1970-01-01T${state.userIntake[0].time}`); const labelTime = new Date(firstIntakeTime.getTime() + h * 60 * 60 * 1000); labels.push(labelTime.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true })); dataPoints.push(totalCaffeineNow.toFixed(2)); } if (state.chartInstance) { state.chartInstance.destroy(); } state.chartInstance = new Chart(ctx, { type: 'line', data: { labels: labels, datasets: [{ label: 'Caffeine in System (mg)', data: dataPoints, borderColor: '#3B82F6', backgroundColor: 'rgba(59, 130, 246, 0.1)', fill: true, tension: 0.4, }] }, options: { responsive: true, maintainAspectRatio: false, scales: { y: { beginAtZero: true, title: { display: true, text: 'Caffeine (mg)' } }, x: { title: { display: true, text: 'Time' } } }, plugins: { tooltip: { mode: 'index', intersect: false, }, title: { display: true, text: 'Caffeine Decay from First Drink' } } } }); } /** * Generates and triggers the download of a beautifully formatted PDF report. * This function is completely rewritten to handle page breaks correctly. */ window.downloadPDF = async () => { const { jsPDF } = window.jspdf; if (!state.chartInstance || state.userIntake.length === 0) { alert("Please run an analysis first to generate a report."); return; } // 1. Get all necessary data for the report const bedtime = document.getElementById('bedtime').value; const halfLife = document.getElementById('caffeine-half-life').value; const chartImage = state.chartInstance.toBase64Image(); const summaryNode = document.getElementById('results-summary').cloneNode(true); const summaryTitle = summaryNode.querySelector('h3'); if (summaryTitle) summaryTitle.classList.remove('font-bold'); // 2. Generate HTML table rows from intake data const intakeRows = state.userIntake.map(intake => ` ${intake.type} ${intake.amount} mg ${new Date('1970-01-01T' + intake.time).toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true })} `).join(''); // 3. Create a hidden container with the complete report HTML structure const reportContainer = document.createElement('div'); reportContainer.id = 'pdf-report'; reportContainer.className = 'w-[800px] bg-white p-10 text-gray-800'; reportContainer.style.position = 'absolute'; reportContainer.style.left = '-9999px'; reportContainer.innerHTML = `

Caffeine & Sleep Analysis Report

Generated: ${new Date().toLocaleString('en-US', { dateStyle: 'full', timeStyle: 'short' })}

User Parameters

Typical Bedtime: ${new Date('1970-01-01T' + bedtime).toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true })}

Caffeine Half-Life: ${halfLife} hours

Analysis Findings

${summaryNode.innerHTML}

Caffeine Intake Log

${intakeRows}
Drink TypeAmountTime Consumed

Caffeine Decay Visualization

This report is an estimation based on provided data and average metabolic rates. It is not a substitute for professional medical advice.

Report generated by the Caffeine Consumption & Sleep Impact Analyzer.

`; document.body.appendChild(reportContainer); // 4. Use html2canvas to render the hidden container try { const canvas = await html2canvas(reportContainer, { scale: 2, useCORS: true, logging: false }); const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'portrait', unit: 'mm', format: 'a4' }); // Define page dimensions and margins const pageHeight = pdf.internal.pageSize.getHeight(); const pageWidth = pdf.internal.pageSize.getWidth(); const margin = 10; // 10mm margin // Calculate the width and height of the image on the PDF, maintaining aspect ratio const contentWidth = pageWidth - (margin * 2); const imgProps = pdf.getImageProperties(imgData); const contentHeight = (imgProps.height * contentWidth) / imgProps.width; let heightLeft = contentHeight; let position = 0; // Add the first page pdf.addImage(imgData, 'PNG', margin, margin, contentWidth, contentHeight); heightLeft -= (pageHeight - (margin * 2)); // Add new pages if the content is taller than one page while (heightLeft > 0) { position -= (pageHeight - (margin * 2)); pdf.addPage(); // Add the same image, but shift its Y position up to show the next part pdf.addImage(imgData, 'PNG', margin, position + margin, contentWidth, contentHeight); heightLeft -= (pageHeight - (margin * 2)); } pdf.save('Caffeine-Sleep-Analysis-Report.pdf'); } catch (error) { console.error("Error generating PDF:", error); alert("Sorry, there was an error creating the PDF report."); } finally { // 5. Clean up by removing the hidden container from the DOM document.body.removeChild(reportContainer); } }; // --- SCRIPT EXECUTION START --- // Set initial state switchTab(1); populateConfig(); addCaffeineEntry(); // Add one entry by default });
Scroll to Top