diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/habits.json b/habits.json index b140ee8..1ad57b0 100644 --- a/habits.json +++ b/habits.json @@ -1 +1 @@ -{"_default": {"1": {"name": "Zocken Mega", "completed_dates": ["2025-07-16", "2025-07-14", "2025-08-01", "2025-08-09", "2025-08-17", "2025-07-25", "2025-07-18"]}}} \ No newline at end of file +{"_default": {"1": {"name": "Zocken Mega", "completed_dates": ["2025-07-16", "2025-07-14", "2025-08-01", "2025-08-09", "2025-08-17", "2025-07-15", "2025-07-01", "2025-06-29", "2025-06-19", "2025-06-20"]}}} \ No newline at end of file diff --git a/static/css/style.css b/static/css/style.css index ebb6147..57908a8 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -180,6 +180,47 @@ h1 { margin-bottom: 20px; } +.month-navigation { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 15px; +} + +.month-navigation button { + background-color: #4CAF50; + color: white; + border: none; + border-radius: 5px; + padding: 8px 12px; + cursor: pointer; + font-size: 16px; +} + +.month-navigation button:hover { + background-color: #45a049; +} + +#currentMonthYear { + font-size: 1.2em; + font-weight: bold; + color: #e0e0e0; +} + +.weekdays-header { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 5px; + margin-bottom: 10px; + text-align: center; + font-weight: bold; + color: #4CAF50; +} + +.weekdays-header div { + padding: 5px; +} + .date-grid-modal { display: grid; grid-template-columns: repeat(7, 1fr); /* 7 days a week */ @@ -204,6 +245,11 @@ h1 { border: 2px solid #007bff; /* Highlight today */ } +.date-cell.empty { + background-color: transparent; + cursor: default; +} + .modal-actions { display: flex; justify-content: space-around; diff --git a/static/js/script.js b/static/js/script.js index 4ebc784..6b99540 100644 --- a/static/js/script.js +++ b/static/js/script.js @@ -10,6 +10,8 @@ const modalDeleteBtn = document.getElementById('modalDeleteBtn'); // Neu hinzuge let currentHabitId = null; // Stellt sicher, dass diese globale Variable korrekt ist +let currentModalDate = new Date(); // Aktueller Monat im Modal +let currentHabitCompletedDates = []; // Completed dates für das aktuelle Habit function getCurrentDate() { const today = new Date(); @@ -61,7 +63,7 @@ function renderHabits(habits) { const habitActions = document.createElement('div'); habitActions.className = 'habit-actions'; - + // Haken-Button für heute abhaken/rückgängig machen const todayToggleButton = document.createElement('button'); const today = getCurrentDate(); @@ -70,7 +72,7 @@ function renderHabits(habits) { todayToggleButton.className = isCompletedToday ? 'completed-today' : 'not-completed-today'; todayToggleButton.onclick = () => toggleTodayCompletion(habit.id, today, todayToggleButton); habitActions.appendChild(todayToggleButton); - + // Drei-Punkte-Menü für erweiterte Optionen const menuButton = document.createElement('button'); menuButton.innerHTML = '⋮'; // Vertical ellipsis (drei Punkte) @@ -81,7 +83,7 @@ function renderHabits(habits) { const dateGrid = document.createElement('div'); dateGrid.className = 'date-grid'; - + last30Days.forEach(date => { const dateSquare = document.createElement('div'); dateSquare.className = 'date-square'; @@ -122,41 +124,69 @@ async function addHabit() { } async function openHabitModal(habitId, habitName, completedDates) { - currentHabitId = habitId; // Hier wird die globale Variable gesetzt + currentHabitId = habitId; + currentHabitCompletedDates = completedDates; + currentModalDate = new Date(); // Reset to current month modalHabitName.textContent = habitName; - + // Setzen der habitId auf den Buttons im Modal modalCompleteTodayBtn.dataset.habitId = habitId; - modalEditBtn.dataset.habitId = habitId; // Wichtig - modalDeleteBtn.dataset.habitId = habitId; // Wichtig + modalEditBtn.dataset.habitId = habitId; + modalDeleteBtn.dataset.habitId = habitId; + renderModalCalendar(); + dateModal.style.display = 'flex'; +} +function renderModalCalendar() { modalDateGrid.innerHTML = ''; - const today = getCurrentDate(); - const startOfWeek = new Date(); - startOfWeek.setDate(startOfWeek.getDate() - (startOfWeek.getDay() + 6) % 7); // Go back to Monday - for (let i = 0; i < 35; i++) { // Display 5 weeks (5 * 7 days) - const d = new Date(startOfWeek); - d.setDate(startOfWeek.getDate() + i); - const dateStr = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`; + // Update month/year display + const monthNames = ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', + 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember']; + document.getElementById('currentMonthYear').textContent = + `${monthNames[currentModalDate.getMonth()]} ${currentModalDate.getFullYear()}`; + + const today = getCurrentDate(); + const year = currentModalDate.getFullYear(); + const month = currentModalDate.getMonth(); + + // Get first day of month and calculate starting position + const firstDay = new Date(year, month, 1); + const lastDay = new Date(year, month + 1, 0); + const startingDayOfWeek = (firstDay.getDay() + 6) % 7; // Monday = 0 + + // Add empty cells for days before month starts + for (let i = 0; i < startingDayOfWeek; i++) { + const emptyCell = document.createElement('div'); + emptyCell.className = 'date-cell empty'; + modalDateGrid.appendChild(emptyCell); + } + + // Add days of the month + for (let day = 1; day <= lastDay.getDate(); day++) { + const dateStr = `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`; const dateCell = document.createElement('div'); dateCell.className = 'date-cell'; - dateCell.textContent = d.getDate(); - if (completedDates.includes(dateStr)) { + dateCell.textContent = day; + + if (currentHabitCompletedDates.includes(dateStr)) { dateCell.classList.add('completed'); } if (dateStr === today) { dateCell.classList.add('today'); } + dateCell.dataset.date = dateStr; - // habitId wird hier korrekt an toggleCompletionForDate übergeben - dateCell.onclick = (event) => toggleCompletionForDate(event, habitId, dateStr); + dateCell.onclick = (event) => toggleCompletionForDate(event, currentHabitId, dateStr); modalDateGrid.appendChild(dateCell); } +} - dateModal.style.display = 'flex'; // Show the modal +function changeMonth(direction) { + currentModalDate.setMonth(currentModalDate.getMonth() + direction); + renderModalCalendar(); } function closeModal() { @@ -180,8 +210,11 @@ async function toggleCompletionForDate(event, habitId, date) { data = await response.json(); if (response.ok) { cell.classList.remove('completed'); - // Hier sollte eventuell auch die completed_dates in der Hauptansicht aktualisiert werden - // Aber der fetchHabits() beim Schließen des Modals kümmert sich darum + // Update local completed dates array + const index = currentHabitCompletedDates.indexOf(date); + if (index > -1) { + currentHabitCompletedDates.splice(index, 1); + } } } else { // Mark as completed @@ -193,7 +226,10 @@ async function toggleCompletionForDate(event, habitId, date) { data = await response.json(); if (response.ok) { cell.classList.add('completed'); - // Hier sollte eventuell auch die completed_dates in der Hauptansicht aktualisiert werden + // Update local completed dates array + if (!currentHabitCompletedDates.includes(date)) { + currentHabitCompletedDates.push(date); + } } } } @@ -284,7 +320,7 @@ async function toggleTodayCompletion(habitId, date, buttonElement) { try { const isCurrentlyCompleted = buttonElement.classList.contains('completed-today'); let response; - + if (isCurrentlyCompleted) { // Mark as uncompleted response = await fetch(`/habits/${habitId}/uncomplete`, { @@ -300,7 +336,7 @@ async function toggleTodayCompletion(habitId, date, buttonElement) { body: JSON.stringify({ date: date }) }); } - + const data = await response.json(); if (response.ok) { // Update button appearance diff --git a/templates/index.html b/templates/index.html index 489f261..748e9d2 100644 --- a/templates/index.html +++ b/templates/index.html @@ -21,6 +21,20 @@