Progress
${goal.progress}%
`;
goalList.appendChild(goalElement);
});
};
const saveGoalsToLocalStorage = () => {
localStorage.setItem('goalTrackerGoals', JSON.stringify(goals));
};
const loadGoalsFromLocalStorage = () => {
const storedGoals = localStorage.getItem('goalTrackerGoals');
if (storedGoals) {
goals = JSON.parse(storedGoals);
}
};
const resetForm = () => {
goalForm.reset();
goalIdInput.value = '';
progressValueDisplay.textContent = '0%';
goalProgressInput.value = 0;
saveGoalBtn.textContent = 'Save Goal';
cancelEditBtn.classList.add('hidden');
};
const populateFormForEdit = (goalId) => {
const goal = goals.find(g => g.id === goalId);
if (goal) {
goalIdInput.value = goal.id;
goalTitleInput.value = goal.title;
goalDescriptionInput.value = goal.description;
goalDateInput.value = goal.targetDate;
goalProgressInput.value = goal.progress;
progressValueDisplay.textContent = `${goal.progress}%`;
reminderFrequencyInput.value = goal.reminderFrequency;
saveGoalBtn.textContent = 'Update Goal';
cancelEditBtn.classList.remove('hidden');
switchTab('add');
}
};
const showNotification = (message) => {
notificationText.textContent = message;
notificationToast.classList.remove('translate-y-20', 'opacity-0');
setTimeout(() => {
notificationToast.classList.add('translate-y-20', 'opacity-0');
}, 4000);
};
const checkReminders = () => {
goals.forEach(goal => {
if (goal.reminderFrequency !== 'none' && settings.emailNotifications) {
// This is a simulation. In a real app, this would be a server-side check.
// For demo, we'll just show a notification for the first goal with a reminder.
showNotification(`Don't forget to work on: "${goal.title}"`);
return; // Only show one for demo purposes
}
});
};
// --- Event Listeners ---
Object.keys(tabs).forEach(key => {
tabs[key].addEventListener('click', () => switchTab(key));
});
addFirstGoalBtn.addEventListener('click', () => switchTab('add'));
goalProgressInput.addEventListener('input', (e) => {
progressValueDisplay.textContent = `${e.target.value}%`;
});
goalForm.addEventListener('submit', (e) => {
e.preventDefault();
const id = goalIdInput.value;
const newGoal = {
id: id ? id : Date.now().toString(),
title: goalTitleInput.value,
description: goalDescriptionInput.value,
targetDate: goalDateInput.value,
progress: goalProgressInput.value,
reminderFrequency: reminderFrequencyInput.value
};
if (id) { // Editing existing goal
goals = goals.map(goal => goal.id === id ? newGoal : goal);
} else { // Adding new goal
goals.push(newGoal);
}
saveGoalsToLocalStorage();
renderGoals();
resetForm();
switchTab('dashboard');
});
cancelEditBtn.addEventListener('click', () => {
resetForm();
switchTab('dashboard');
});
goalList.addEventListener('click', (e) => {
if (e.target.classList.contains('edit-btn')) {
populateFormForEdit(e.target.dataset.id);
}
if (e.target.classList.contains('delete-btn')) {
goals = goals.filter(goal => goal.id !== e.target.dataset.id);
saveGoalsToLocalStorage();
renderGoals();
}
});
saveSettingsBtn.addEventListener('click', () => {
username = usernameInput.value.trim() || 'User';
settings.emailNotifications = document.getElementById('email-notifications').checked;
localStorage.setItem('goalTrackerSettings', JSON.stringify({username, settings}));
settingsSavedMsg.classList.remove('hidden');
setTimeout(() => settingsSavedMsg.classList.add('hidden'), 2000);
});
pdfDownloadBtn.addEventListener('click', () => {
if (typeof window.jspdf === 'undefined') {
alert('PDF library not loaded.');
return;
}
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
doc.setFontSize(20);
doc.text(`${username}'s Goal Summary`, 105, 20, null, null, 'center');
doc.setFontSize(12);
doc.text(new Date().toLocaleDateString(), 105, 28, null, null, 'center');
const tableColumn = ["Goal", "Target Date", "Progress (%)", "Status"];
const tableRows = [];
goals.forEach(goal => {
const daysLeft = Math.ceil((new Date(goal.targetDate) - new Date()) / (1000 * 60 * 60 * 24));
const status = goal.progress == 100 ? 'Completed' : (daysLeft > 0 ? `${daysLeft} days left` : 'Overdue');
const goalData = [
goal.title,
new Date(goal.targetDate).toLocaleDateString(),
goal.progress,
status
];
tableRows.push(goalData);
});
doc.autoTable(tableColumn, tableRows, { startY: 40 });
doc.save(`${username}_Goal_Summary.pdf`);
});
// --- Initial Load ---
const storedSettings = JSON.parse(localStorage.getItem('goalTrackerSettings'));
if (storedSettings) {
username = storedSettings.username || 'User';
settings = storedSettings.settings || { emailNotifications: false };
usernameInput.value = username;
document.getElementById('email-notifications').checked = settings.emailNotifications;
}
loadGoalsFromLocalStorage();
renderGoals();
// Set min date for date input to today
goalDateInput.min = new Date().toISOString().split("T")[0];
// Simulate checking for reminders shortly after load
setTimeout(checkReminders, 5000);
});