Study Motivation & Habit Tracker
Build productive habits and stay motivated on your learning journey.
"The secret to getting ahead is getting started."
- Mark Twain
Weekly Habit Tracker
No habits added yet. Add one below to get started!
'; } habits.forEach((habit, habitIndex) => { const habitEl = document.createElement('div'); habitEl.className = 'habit-item'; let daysHTML = ''; daysOfWeek.forEach((day, dayIndex) => { daysHTML += `${day}
`;
});
const streak = calculateStreak(habit.completedDays);
habitEl.innerHTML = `
${habit.name}
🔥 ${streak} Day Streak
${daysHTML}
`;
habitList.appendChild(habitEl);
});
addEventListenersToHabits();
};
const addEventListenersToHabits = () => {
document.querySelectorAll('.day-check').forEach(el => {
el.addEventListener('click', toggleDayCompletion);
});
document.querySelectorAll('.remove-habit-btn').forEach(el => {
el.addEventListener('click', removeHabit);
});
};
const addNewHabit = () => {
const habitName = newHabitInput.value.trim();
if (!habitName) {
showMessage('Please enter a habit name.', 'error');
return;
}
const today = new Date();
habits.push({
name: habitName,
completedDays: [false, false, false, false, false, false, false],
weekStartDate: getStartOfWeek(today).toISOString().split('T')[0]
});
newHabitInput.value = '';
saveData();
renderHabits();
};
const removeHabit = (event) => {
const habitIndex = parseInt(event.target.dataset.habitIndex, 10);
habits.splice(habitIndex, 1);
saveData();
renderHabits();
};
const toggleDayCompletion = (event) => {
const habitIndex = parseInt(event.target.dataset.habitIndex, 10);
const dayIndex = parseInt(event.target.dataset.dayIndex, 10);
habits[habitIndex].completedDays[dayIndex] = !habits[habitIndex].completedDays[dayIndex];
saveData();
renderHabits();
};
const calculateStreak = (completedDays) => {
let currentStreak = 0;
let todayIndex = new Date().getDay(); // Sunday is 0
// Check today
if (completedDays[todayIndex]) {
currentStreak = 1;
// Check backwards from yesterday
for (let i = 1; i < 7; i++) {
let checkIndex = (todayIndex - i + 7) % 7;
if (completedDays[checkIndex]) {
currentStreak++;
} else {
break; // Streak is broken
}
}
}
return currentStreak;
};
// --- PDF Export ---
pdfBtn.addEventListener('click', () => {
if (habits.length === 0) {
showMessage('No habits to report.', 'error');
return;
}
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
doc.setFontSize(18);
doc.text('Weekly Habit Progress Report', 105, 20, { align: 'center' });
doc.setFontSize(12);
doc.text(`Week of: ${getStartOfWeek(new Date()).toLocaleDateString()}`, 105, 30, { align: 'center' });
const tableData = habits.map(habit => {
const completionCount = habit.completedDays.filter(Boolean).length;
const streak = calculateStreak(habit.completedDays);
return [
habit.name,
`${completionCount} / 7`,
`${streak} days`
];
});
doc.autoTable({
startY: 40,
head: [['Habit', 'Weekly Completion', 'Current Streak']],
body: tableData,
headStyles: { fillColor: [79, 70, 229] }
});
doc.save('habit-progress-report.pdf');
});
// --- Utility Functions ---
const getStartOfWeek = (date) => {
const d = new Date(date);
const day = d.getDay(); // 0 for Sunday
const diff = d.getDate() - day;
return new Date(d.setDate(diff));
};
const showMessage = (message, type = 'success') => {
messageBox.textContent = message;
messageBox.className = `message-box ${type} show`;
setTimeout(() => { messageBox.classList.remove('show'); }, 3000);
};
// --- Initial Load ---
addHabitBtn.addEventListener('click', addNewHabit);
newHabitInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') addNewHabit();
});
loadData();
renderHabits();
showNewQuote();
});
