Habit-tracking Calendar JavaScript, HTML, CSS

👤 Sharing: AI
```javascript
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Habit Tracker</title>
    <style>
        body {
            font-family: sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            background-color: #f0f0f0;
        }

        .container {
            background-color: white;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
            padding: 20px;
            width: 80%;
            max-width: 800px;
        }

        .calendar {
            display: grid;
            grid-template-columns: repeat(7, 1fr);
            gap: 5px;
            margin-top: 20px;
        }

        .day {
            padding: 10px;
            border: 1px solid #ddd;
            text-align: center;
            cursor: pointer;
        }

        .day.current {
            background-color: #e0f7fa; /* Light teal */
        }

        .day.completed {
            background-color: #a5d6a7; /* Light green */
        }

        .controls {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 10px;
        }

        .controls button {
            padding: 8px 16px;
            background-color: #4caf50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }

        .controls button:hover {
            background-color: #388e3c;
        }

        #habit-name {
            font-size: 24px;
            margin-bottom: 15px;
        }

        .day.incomplete {
            background-color: #ffcdd2; /* light red */
        }
    </style>
</head>
<body>

    <div class="container">
        <h1 id="habit-name">Track Your Habit</h1>

        <div class="controls">
            <button id="prev-month">Previous Month</button>
            <h2 id="current-month-year"></h2>
            <button id="next-month">Next Month</button>
        </div>

        <div class="calendar" id="calendar"></div>

        <script>
            const habitNameElement = document.getElementById('habit-name');
            const calendarElement = document.getElementById('calendar');
            const currentMonthYearElement = document.getElementById('current-month-year');
            const prevMonthButton = document.getElementById('prev-month');
            const nextMonthButton = document.getElementById('next-month');

            let currentDate = new Date();
            let habitName = "Exercise"; // Default habit name
            let completedDays = {}; // Store completion status for each day (YYYY-MM-DD: true/false)


            // Function to update the habit name (you can connect this to a form later)
            function updateHabitName(newHabitName) {
                habitName = newHabitName;
                habitNameElement.textContent = `Track Your ${habitName}`;
            }



            function generateCalendar(year, month) {
                calendarElement.innerHTML = ''; // Clear existing calendar

                const firstDayOfMonth = new Date(year, month, 1);
                const lastDayOfMonth = new Date(year, month + 1, 0);
                const daysInMonth = lastDayOfMonth.getDate();
                const startingDayOfWeek = firstDayOfMonth.getDay(); // 0 (Sunday) to 6 (Saturday)

                currentMonthYearElement.textContent = `${new Intl.DateTimeFormat('en-US', { month: 'long', year: 'numeric' }).format(firstDayOfMonth)}`;

                // Create day names (Sunday to Saturday)
                const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
                dayNames.forEach(dayName => {
                    const dayNameElement = document.createElement('div');
                    dayNameElement.textContent = dayName;
                    dayNameElement.classList.add('day'); // Use class 'day' for styling
                    calendarElement.appendChild(dayNameElement);
                });


                // Add empty days for the days before the first day of the month
                for (let i = 0; i < startingDayOfWeek; i++) {
                    const emptyDay = document.createElement('div');
                    emptyDay.classList.add('day');
                    calendarElement.appendChild(emptyDay);
                }

                // Add the days of the month
                for (let day = 1; day <= daysInMonth; day++) {
                    const dayElement = document.createElement('div');
                    dayElement.textContent = day;
                    dayElement.classList.add('day');

                    const fullDateString = `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`;

                    if (year === currentDate.getFullYear() && month === currentDate.getMonth() && day === currentDate.getDate()) {
                        dayElement.classList.add('current');
                    }


                    if (completedDays[fullDateString] === true) {
                        dayElement.classList.add('completed');
                    } else if (completedDays[fullDateString] === false) {
                        dayElement.classList.add('incomplete');
                    }


                    dayElement.addEventListener('click', () => {
                         if(completedDays[fullDateString] === true) {
                            completedDays[fullDateString] = false;
                            dayElement.classList.remove('completed');
                            dayElement.classList.add('incomplete');
                         } else if (completedDays[fullDateString] === false){
                             completedDays[fullDateString] = null; //reset to neutral state
                             dayElement.classList.remove('incomplete');
                         }
                        else {
                            completedDays[fullDateString] = true;
                            dayElement.classList.add('completed');
                        }
                        saveHabitData();
                    });

                    calendarElement.appendChild(dayElement);
                }
            }



            prevMonthButton.addEventListener('click', () => {
                currentDate.setMonth(currentDate.getMonth() - 1);
                generateCalendar(currentDate.getFullYear(), currentDate.getMonth());
            });

            nextMonthButton.addEventListener('click', () => {
                currentDate.setMonth(currentDate.getMonth() + 1);
                generateCalendar(currentDate.getFullYear(), currentDate.getMonth());
            });

            // Local Storage Functions
            function saveHabitData() {
                const data = {
                    habitName: habitName,
                    completedDays: completedDays
                };
                localStorage.setItem('habitData', JSON.stringify(data));
            }

            function loadHabitData() {
                const storedData = localStorage.getItem('habitData');
                if (storedData) {
                    const data = JSON.parse(storedData);
                    habitName = data.habitName;
                    completedDays = data.completedDays;
                    updateHabitName(habitName);
                }
            }

            // Initial Calendar Generation and Data Loading
            loadHabitData();
            generateCalendar(currentDate.getFullYear(), currentDate.getMonth());
        </script>
    </div>

</body>
</html>
```
👁️ Viewed: 9

Comments