From c78e825f2fbf241c51723fb3d8f5459ba2de2624 Mon Sep 17 00:00:00 2001 From: jafreli Date: Wed, 16 Jul 2025 18:43:11 +0200 Subject: [PATCH] Erste funktionierende Version --- app.py | 23 +++++++--- habits.json | 2 +- static/css/style.css | 17 +++++++ static/js/script.js | 105 ++++++++++++++++++++++++++++++++++++------- templates/index.html | 2 +- 5 files changed, 126 insertions(+), 23 deletions(-) diff --git a/app.py b/app.py index cb2692e..8fd2a7e 100644 --- a/app.py +++ b/app.py @@ -24,14 +24,25 @@ def index(): @app.route('/habits', methods=['GET']) def get_habits(): - habits_data = db.all() - # Add completion status for the last 30 days + raw_habits = db.all() + formatted_habits = [] last_30_days = get_last_30_days() - for habit in habits_data: - habit['completion_history'] = {} + + for habit_doc in raw_habits: + current_habit_data = { + 'id': habit_doc.doc_id, + 'name': habit_doc.get('name'), + 'completed_dates': habit_doc.get('completed_dates', []) + } + + completion_history = {} for date_str in last_30_days: - habit['completion_history'][date_str] = date_str in habit.get('completed_dates', []) - return jsonify(habits_data) + completion_history[date_str] = date_str in current_habit_data['completed_dates'] + + current_habit_data['completion_history'] = completion_history + formatted_habits.append(current_habit_data) + + return jsonify(formatted_habits) @app.route('/habits', methods=['POST']) def add_habit(): diff --git a/habits.json b/habits.json index a373537..b140ee8 100644 --- a/habits.json +++ b/habits.json @@ -1 +1 @@ -{"_default": {"1": {"name": "Zocken", "completed_dates": []}, "2": {"name": "Gehen", "completed_dates": []}}} \ 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-25", "2025-07-18"]}}} \ No newline at end of file diff --git a/static/css/style.css b/static/css/style.css index a0d1e18..ebb6147 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -81,12 +81,29 @@ h1 { color: #e0e0e0; font-size: 1.5em; cursor: pointer; + margin-left: 5px; } .habit-actions button:hover { color: #666; } +.habit-actions button.completed-today { + color: #4CAF50; +} + +.habit-actions button.not-completed-today { + color: #888; +} + +.habit-actions button.completed-today:hover { + color: #45a049; +} + +.habit-actions button.not-completed-today:hover { + color: #4CAF50; +} + .date-grid { display: grid; grid-template-columns: repeat(30, 1fr); /* Adjust based on your date range */ diff --git a/static/js/script.js b/static/js/script.js index 4051518..4ebc784 100644 --- a/static/js/script.js +++ b/static/js/script.js @@ -5,8 +5,11 @@ const dateModal = document.getElementById('dateModal'); const modalHabitName = document.getElementById('modalHabitName'); const modalDateGrid = document.getElementById('modalDateGrid'); const modalCompleteTodayBtn = document.getElementById('modalCompleteTodayBtn'); +const modalEditBtn = document.getElementById('modalEditBtn'); // Neu hinzugefügt +const modalDeleteBtn = document.getElementById('modalDeleteBtn'); // Neu hinzugefügt -let currentHabitId = null; + +let currentHabitId = null; // Stellt sicher, dass diese globale Variable korrekt ist function getCurrentDate() { const today = new Date(); @@ -58,10 +61,21 @@ function renderHabits(habits) { const habitActions = document.createElement('div'); habitActions.className = 'habit-actions'; - const openModalButton = document.createElement('button'); - openModalButton.innerHTML = '✔'; // Checkmark symbol - openModalButton.onclick = () => openHabitModal(habit.id, habit.name, habit.completed_dates); - habitActions.appendChild(openModalButton); + + // Haken-Button für heute abhaken/rückgängig machen + const todayToggleButton = document.createElement('button'); + const today = getCurrentDate(); + const isCompletedToday = habit.completed_dates && habit.completed_dates.includes(today); + todayToggleButton.innerHTML = isCompletedToday ? '✓' : '✓'; // Checkmark symbol + 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) + menuButton.onclick = () => openHabitModal(habit.id, habit.name, habit.completed_dates); + habitActions.appendChild(menuButton); habitHeader.appendChild(habitActions); habitItem.appendChild(habitHeader); @@ -108,9 +122,14 @@ async function addHabit() { } async function openHabitModal(habitId, habitName, completedDates) { - currentHabitId = habitId; + currentHabitId = habitId; // Hier wird die globale Variable gesetzt modalHabitName.textContent = habitName; - modalCompleteTodayBtn.dataset.habitId = habitId; // Store habit ID for button + + // Setzen der habitId auf den Buttons im Modal + modalCompleteTodayBtn.dataset.habitId = habitId; + modalEditBtn.dataset.habitId = habitId; // Wichtig + modalDeleteBtn.dataset.habitId = habitId; // Wichtig + modalDateGrid.innerHTML = ''; const today = getCurrentDate(); @@ -132,6 +151,7 @@ async function openHabitModal(habitId, habitName, completedDates) { dateCell.classList.add('today'); } dateCell.dataset.date = dateStr; + // habitId wird hier korrekt an toggleCompletionForDate übergeben dateCell.onclick = (event) => toggleCompletionForDate(event, habitId, dateStr); modalDateGrid.appendChild(dateCell); } @@ -141,7 +161,7 @@ async function openHabitModal(habitId, habitName, completedDates) { function closeModal() { dateModal.style.display = 'none'; - currentHabitId = null; + currentHabitId = null; // Zurücksetzen, wenn das Modal geschlossen wird fetchHabits(); // Refresh habits after closing modal } @@ -160,8 +180,8 @@ async function toggleCompletionForDate(event, habitId, date) { data = await response.json(); if (response.ok) { cell.classList.remove('completed'); - // Update the completion_history in the rendered habits - // (You might need to re-fetch or update the local habit data for the main view) + // Hier sollte eventuell auch die completed_dates in der Hauptansicht aktualisiert werden + // Aber der fetchHabits() beim Schließen des Modals kümmert sich darum } } else { // Mark as completed @@ -173,13 +193,19 @@ async function toggleCompletionForDate(event, habitId, date) { data = await response.json(); if (response.ok) { cell.classList.add('completed'); - // Update the completion_history + // Hier sollte eventuell auch die completed_dates in der Hauptansicht aktualisiert werden } } } async function completeHabitForDate(event, habitId, date) { + // Der habitId kommt jetzt direkt vom dataset des Buttons oder der Funktion, die ihn aufruft + // Sicherstellen, dass habitId gültig ist + if (!habitId) { + console.error('Habit ID is undefined for completion.'); + return; + } try { const response = await fetch(`/habits/${habitId}/complete`, { method: 'POST', @@ -195,8 +221,6 @@ async function completeHabitForDate(event, habitId, date) { cell.classList.add('completed'); } }); - // Optionally, disable the "Today erledigen" button if already completed - // modalCompleteTodayBtn.disabled = true; } else { console.error('Failed to complete habit:', data.error); } @@ -206,10 +230,15 @@ async function completeHabitForDate(event, habitId, date) { } async function editHabitName() { + // Sicherstellen, dass currentHabitId gesetzt ist + if (!currentHabitId) { + console.error('No habit selected for editing.'); + return; + } const newName = prompt("Neuen Namen für die Gewohnheit eingeben:", modalHabitName.textContent); if (newName && newName.trim() !== "") { try { - const response = await fetch(`/habits/${currentHabitId}`, { + const response = await fetch(`/habits/${currentHabitId}`, { // Verwendet currentHabitId method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: newName.trim() }) @@ -228,9 +257,14 @@ async function editHabitName() { } async function deleteHabitFromModal() { + // Sicherstellen, dass currentHabitId gesetzt ist + if (!currentHabitId) { + console.error('No habit selected for deletion.'); + return; + } if (confirm("Bist du sicher, dass du diese Gewohnheit löschen möchtest?")) { try { - const response = await fetch(`/habits/${currentHabitId}`, { + const response = await fetch(`/habits/${currentHabitId}`, { // Verwendet currentHabitId method: 'DELETE' }); const data = await response.json(); @@ -244,4 +278,45 @@ async function deleteHabitFromModal() { console.error('Error deleting habit:', error); } } +} + +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`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ date: date }) + }); + } else { + // Mark as completed + response = await fetch(`/habits/${habitId}/complete`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ date: date }) + }); + } + + const data = await response.json(); + if (response.ok) { + // Update button appearance + if (isCurrentlyCompleted) { + buttonElement.classList.remove('completed-today'); + buttonElement.classList.add('not-completed-today'); + } else { + buttonElement.classList.remove('not-completed-today'); + buttonElement.classList.add('completed-today'); + } + // Refresh the date grid to show updated completion status + fetchHabits(); + } else { + console.error('Failed to toggle habit completion:', data.error); + } + } catch (error) { + console.error('Error toggling habit completion:', error); + } } \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index 9e82fd1..489f261 100644 --- a/templates/index.html +++ b/templates/index.html @@ -23,7 +23,7 @@