Online Smart Gratitude Journal & Reminder Tool

Online Smart Gratitude Journal & Reminder Tool

Cultivate positivity by recording your moments of gratitude.

What are you grateful for today?

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

${entry.text}

`; entriesList.appendChild(entryEl); }); } }; // Function to update reminder status display const updateReminderStatus = () => { if (reminderTime) { reminderTimeInput.value = reminderTime; reminderStatus.textContent = `Daily reminder is set for ${reminderTime}.`; reminderStatus.className = 'mt-4 font-medium text-green-600'; } else { reminderTimeInput.value = ''; reminderStatus.textContent = 'No reminder is set.'; reminderStatus.className = 'mt-4 font-medium text-gray-500'; } }; // Function to handle tab switching const switchTab = (tabIndex) => { tabs.forEach(tab => tab.classList.replace('tab-active', 'tab-inactive')); tabPanes.forEach(pane => pane.classList.add('hidden')); const selectedTab = tabs[tabIndex]; const selectedPaneId = selectedTab.getAttribute('data-tab'); const selectedPane = document.getElementById(selectedPaneId); selectedTab.classList.replace('tab-inactive', 'tab-active'); if (selectedPane) { selectedPane.classList.remove('hidden'); } currentTabIndex = tabIndex; updateNavButtons(); }; // Function to update Previous/Next button states const updateNavButtons = () => { prevBtn.disabled = currentTabIndex === 0; nextBtn.disabled = currentTabIndex === tabs.length - 1; prevBtn.classList.toggle('opacity-50', prevBtn.disabled); nextBtn.classList.toggle('opacity-50', nextBtn.disabled); }; // Initial setup calls renderEntries(); updateReminderStatus(); updateNavButtons(); if (reminderTime) { startReminderCheck(); } // --- EVENT LISTENERS --- // Tab navigation tabs.forEach((tab, index) => { tab.addEventListener('click', () => switchTab(index)); }); // Previous/Next button navigation prevBtn.addEventListener('click', () => { if (currentTabIndex > 0) { switchTab(currentTabIndex - 1); } }); nextBtn.addEventListener('click', () => { if (currentTabIndex < tabs.length - 1) { switchTab(currentTabIndex + 1); } }); // Save new entry if (saveEntryBtn) { saveEntryBtn.addEventListener('click', () => { const text = journalInput.value.trim(); if (text) { const newEntry = { id: Date.now(), date: new Date().toISOString(), text: text }; entries.push(newEntry); localStorage.setItem('gratitudeEntries', JSON.stringify(entries)); journalInput.value = ''; renderEntries(); // Show confirmation message saveConfirmation.style.display = 'block'; setTimeout(() => { saveConfirmation.style.display = 'none'; }, 3000); } }); } // Edit and Delete entry buttons (event delegation) if (entriesList) { entriesList.addEventListener('click', (e) => { const target = e.target.closest('button'); if (!target) return; const entryId = parseInt(target.getAttribute('data-id')); if (target.classList.contains('delete-btn')) { // Use a custom confirmation modal in a real app, window.confirm is a placeholder if (confirm('Are you sure you want to delete this entry?')) { entries = entries.filter(entry => entry.id !== entryId); localStorage.setItem('gratitudeEntries', JSON.stringify(entries)); renderEntries(); } } if (target.classList.contains('edit-btn')) { const entryToEdit = entries.find(entry => entry.id === entryId); if (entryToEdit) { const newText = prompt('Edit your entry:', entryToEdit.text); if (newText !== null && newText.trim() !== '') { entryToEdit.text = newText.trim(); localStorage.setItem('gratitudeEntries', JSON.stringify(entries)); renderEntries(); } } } }); } // Set Reminder if (setReminderBtn) { setReminderBtn.addEventListener('click', () => { const time = reminderTimeInput.value; if (time) { // Request notification permission if (Notification.permission === 'granted') { saveAndStartReminder(time); } else if (Notification.permission !== 'denied') { Notification.requestPermission().then(permission => { if (permission === 'granted') { saveAndStartReminder(time); } else { alert('Notification permission was denied. You will not receive reminders.'); } }); } else { alert('Notification permission is denied. Please enable it in your browser settings to receive reminders.'); } } }); } // Clear Reminder if (clearReminderBtn) { clearReminderBtn.addEventListener('click', () => { reminderTime = null; localStorage.removeItem('gratitudeReminderTime'); if (reminderInterval) { clearInterval(reminderInterval); } updateReminderStatus(); }); } // PDF Download if (downloadPdfBtn) { downloadPdfBtn.addEventListener('click', async () => { // Temporarily create a clone for PDF generation const contentToPrint = entriesList.cloneNode(true); contentToPrint.style.maxHeight = 'none'; // Remove scroll limit for PDF contentToPrint.id = 'pdf-content'; // Hide buttons in the clone contentToPrint.querySelectorAll('.pdf-hide').forEach(el => el.classList.add('pdf-hide')); // Append to body to render, but make it invisible document.body.appendChild(contentToPrint); contentToPrint.style.position = 'absolute'; contentToPrint.style.left = '-9999px'; contentToPrint.style.width = '800px'; // Set a fixed width for consistent PDF layout // Add a title to the PDF content const pdfTitle = document.createElement('h1'); pdfTitle.innerText = 'My Gratitude Journal'; pdfTitle.className = 'text-2xl font-bold text-center mb-6'; contentToPrint.insertBefore(pdfTitle, contentToPrint.firstChild); const { jsPDF } = window.jspdf; const canvas = await html2canvas(contentToPrint, { scale: 2 }); const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'portrait', unit: 'px', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = (canvas.height * pdfWidth) / canvas.width; pdf.addImage(imgData, 'PNG', 0, 0, pdfWidth, pdfHeight); pdf.save('gratitude-journal.pdf'); // Clean up the cloned element document.body.removeChild(contentToPrint); }); } // --- HELPER FUNCTIONS --- function saveAndStartReminder(time) { reminderTime = time; localStorage.setItem('gratitudeReminderTime', time); updateReminderStatus(); startReminderCheck(); } function startReminderCheck() { if (reminderInterval) { clearInterval(reminderInterval); } reminderInterval = setInterval(checkTime, 30000); // Check every 30 seconds } function checkTime() { if (!reminderTime) return; const now = new Date(); const [hours, minutes] = reminderTime.split(':'); if (now.getHours() == hours && now.getMinutes() == minutes) { // Check if a notification for today has already been sent const lastNotification = localStorage.getItem('lastGratitudeNotification'); const today = new Date().toDateString(); if (lastNotification !== today) { showNotification(); localStorage.setItem('lastGratitudeNotification', today); } } } function showNotification() { const notification = new Notification('Time for Gratitude!', { body: 'Take a moment to write down what you are grateful for today.', icon: 'https://img.icons8.com/plasticine/100/000000/leaf.png' // A generic, friendly icon }); notification.onclick = () => { window.focus(); switchTab(0); // Switch to the journal tab on click }; } });
Scroll to Top