Personalized Dental Hygiene Routine Planner

Personalized Dental Hygiene Routine

My Dental Goals

Morning Routine

Evening Routine

No logs yet. Go to the "Routine Planner" to start.

`; return; } let tableHTML = ``; routineData.logs.forEach((log, index) => { const visibleTasks = Object.keys(ROUTINE_TASKS).filter(key => routineData.goals.some(goal => ROUTINE_TASKS[key].goals.includes(goal))); const totalTasks = visibleTasks.length * 2; // Morning and evening const completedCount = log.completed.length; const consistency = totalTasks > 0 ? Math.round((completedCount / totalTasks) * 100) : 0; tableHTML += ` `; }); tableHTML += `
Date Consistency Actions
${new Date(log.date + 'T00:00:00').toLocaleDateString()} ${consistency}%
`; historyTableContainer.innerHTML = tableHTML; }; const renderConsistencyChart = () => { if (consistencyChart) consistencyChart.destroy(); if (routineData.logs.length === 0) { chartCanvas.style.display = 'none'; return; } chartCanvas.style.display = 'block'; const chartData = [...routineData.logs].reverse().slice(-30); const labels = chartData.map(d => new Date(d.date + 'T00:00:00').toLocaleDateString()); const scores = chartData.map(log => { const visibleTasks = Object.keys(ROUTINE_TASKS).filter(key => routineData.goals.some(goal => ROUTINE_TASKS[key].goals.includes(goal))); const totalTasks = visibleTasks.length * 2; return totalTasks > 0 ? Math.round((log.completed.length / totalTasks) * 100) : 0; }); consistencyChart = new Chart(chartCanvas, { type: 'line', data: { labels: labels, datasets: [{ label: 'Consistency Score (%)', data: scores, borderColor: '#0ea5e9', backgroundColor: 'rgba(14, 165, 233, 0.1)', fill: true, tension: 0.2 }] }, options: { responsive: true, scales: { y: { beginAtZero: true, max: 100 } } } }); }; // IV. Event Listeners & Tab Logic tabs.forEach(tab => { tab.addEventListener('click', () => { tabs.forEach(t => t.classList.replace('active', 'inactive')); tab.classList.replace('inactive', 'active'); tabContents.forEach(c => c.classList.add('hidden')); document.getElementById(tab.dataset.tab).classList.remove('hidden'); }); }); goalsContainer.addEventListener('change', () => { routineData.goals = Array.from(document.querySelectorAll('input[name="goal"]:checked')).map(cb => cb.value); updateVisibleTasks(); }); logDateInput.addEventListener('change', () => { populateRoutineChecklists(); }); saveEntryBtn.addEventListener('click', saveAndNotify); historyTableContainer.addEventListener('click', (e) => { if (e.target.classList.contains('delete-btn')) { const dateToDelete = e.target.dataset.date; if (confirm(`Are you sure you want to delete the log for ${new Date(dateToDelete + 'T00:00:00').toLocaleDateString()}?`)) { routineData.logs = routineData.logs.filter(log => log.date !== dateToDelete); localStorage.setItem('dentalPlannerData', JSON.stringify(routineData)); renderDashboard(); } } }); // V. PDF Generation pdfDownloadBtn.addEventListener('click', () => { if (routineData.logs.length === 0) return alert('No data to generate a report.'); saveCurrentState(); // Ensure latest data is used const { jsPDF } = jspdf; const doc = new jsPDF(); const pageW = doc.internal.pageSize.getWidth(); const margin = 15; doc.setFillColor(14, 165, 233); doc.rect(0, 0, pageW, 25, 'F'); doc.setFontSize(16); doc.setFont('helvetica', 'bold'); doc.setTextColor(255, 255, 255); doc.text('Dental Hygiene Progress Report', margin, 16); doc.setFontSize(12); doc.setFont('helvetica', 'bold'); doc.setTextColor(30, 41, 59); doc.text('Your Goals:', margin, 40); doc.setFontSize(10); doc.setFont('helvetica', 'normal'); doc.text(routineData.goals.map(g => GOALS[g].label).join(', '), margin, 48); if (consistencyChart && chartCanvas.style.display !== 'none') { const chartImage = chartCanvas.toDataURL('image/png', 1.0); doc.setFontSize(12); doc.setFont('helvetica', 'bold'); doc.text('Consistency Chart', margin, 60); doc.addImage(chartImage, 'PNG', margin, 65, pageW - (margin * 2), (pageW - (margin * 2)) * 0.5); } const tableStartY = 140; doc.setFontSize(12); doc.setFont('helvetica', 'bold'); doc.text('Detailed Log', margin, tableStartY); const tableData = routineData.logs.map(log => { const visibleTasks = Object.keys(ROUTINE_TASKS).filter(key => routineData.goals.some(goal => ROUTINE_TASKS[key].goals.includes(goal))); const totalTasks = visibleTasks.length * 2; const score = totalTasks > 0 ? `${log.completed.length}/${totalTasks}` : 'N/A'; return [new Date(log.date + 'T00:00:00').toLocaleDateString(), score]; }); doc.autoTable({ startY: tableStartY + 5, head: [['Date', 'Tasks Completed']], body: tableData, headStyles: { fillColor: [71, 85, 105] }, theme: 'grid' }); doc.save('Dental_Hygiene_Report.pdf'); }); // Initial Load logDateInput.valueAsDate = new Date(); populateGoals(); populateRoutineChecklists(); updateVisibleTasks(); renderDashboard(); });
Scroll to Top