Compare commits

..

5 Commits

Author SHA1 Message Date
ce0a6b588b gap for spacing and heatmap but unfinished 2024-02-14 11:15:37 +01:00
6143f44442 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	templates/index.html
2024-02-14 10:59:24 +01:00
Yapollon
aaeb04d4ab Heatmap done?
yes
2024-02-14 10:52:25 +01:00
Verox001
0f060e81a4 Fixed animation and color change of habit progress bar 2024-02-14 10:50:23 +01:00
Verox001
1180893dd1 Fixed Yassins code removal 2024-02-14 10:41:03 +01:00
4 changed files with 199 additions and 190 deletions

1
app.py
View File

@ -136,6 +136,7 @@ def index():
title=name, title=name,
utc_dt=datetime.datetime.now().strftime("%d.%m.%Y %H:%M %A"), utc_dt=datetime.datetime.now().strftime("%d.%m.%Y %H:%M %A"),
habit_lists=habit_lists, habit_lists=habit_lists,
heatmap_values=current_user.get_heatmap(),
errors={}, errors={},
) )

View File

@ -80,6 +80,9 @@ class Habit:
count = 0 count = 0
self.checked = False self.checked = False
for tracking in self.get_habitTrackings(): for tracking in self.get_habitTrackings():
if tracking.created_at.date() == datetime.today().date():
self.checked = True
# day # day
if self.unit == 0: if self.unit == 0:
if tracking.created_at.date() == datetime.today().date(): if tracking.created_at.date() == datetime.today().date():

View File

@ -1,8 +1,8 @@
from datetime import datetime from datetime import datetime
from flask_login import UserMixin from flask_login import UserMixin
from db.SQLiteClient import create_user, get_user, get_user_by_email, get_habits, delete_user, update_user, \ from db.SQLiteClient import create_user, get_user, get_user_by_email, delete_user, update_user, \
get_habitLists get_habitLists, get_heatmap_value
class User(UserMixin): class User(UserMixin):
@ -43,3 +43,10 @@ class User(UserMixin):
habitLists.append(habitList) habitLists.append(habitList)
return habitLists return habitLists
def get_heatmap(self):
heatmap = []
for day in range(0, 28):
value = get_heatmap_value(self.id, day)
heatmap.append(value)
return heatmap

View File

@ -21,228 +21,226 @@
justify-content: center; justify-content: center;
} }
</style> </style>
<div class="row">
<div class="col-md-4 col-12 card bg-light mb-6"> <div class="d-flex flex-column gap-5">
<div class="card-body"> <div class="d-flex gap-3">
<h5 class="card-title">Heatmap</h5> <div class="flex-fill col-5 card bg-light mb-6">
<div id="heatmap"></div> <div class="card-body">
<h5 class="card-title">Heatmap</h5>
<div id="heatmap"></div>
</div>
</div> </div>
</div>
<script> <script>
// Funktion zur Rückgabe des Montagsdatums
function getMonday(date) {
const day = date.getDay();
const diff = date.getDate() - day + (day === 0 ? -6 : 1); // Anpassung für Sonntag
return new Date(date.setDate(diff));
}
// Simulierte Aktivitätsdaten (ersetze dies durch deine echten Daten) // Simulierte Aktivitätsdaten (ersetze dies durch deine echten Daten)
const activityData = [5, 3, 10, 5, 24, 2, 10, 47, 32, 45, 9, 5, 11, 39, 24, 2, 10, 47, 32, 45]; const activityData = {{heatmap_values}};
// Funktion zum Erstellen der Heatmap // Funktion zum Erstellen der Heatmap
function createHeatmap(data) { function createHeatmap(data) {
const heatmapContainer = document.getElementById('heatmap'); const heatmapContainer = document.getElementById('heatmap');
// Aktuelles Datum des Montags // Aktuelles Datum des Montags
const days = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'] const days = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']
for (let i = 0; i < 7; i++) { for (let i = 0; i < 7; i++) {
const dayElement = document.createElement('div'); const dayElement = document.createElement('div');
dayElement.classList.add('day'); dayElement.classList.add('day');
dayElement.textContent = days[i]; dayElement.textContent = days[i];
heatmapContainer.appendChild(dayElement); heatmapContainer.appendChild(dayElement);
// currentDate.setDate(currentDate.getDate() + 1); // currentDate.setDate(currentDate.getDate() + 1);
} }
// Aktuelles Datum des Montags in der neuen linken Spalte // Aktuelles Datum des Montags in der neuen linken Spalte
for (let i = 0; i < 7; i++) { for (let i = 0; i < 7; i++) {
for (let j = 0; j < 7; j++) { for (let j = 0; j < 4; j++) {
// console.log(i * 7 + j, data[i * 7 + j], Math.max(...data)); // console.log(i * 7 + j, data[i * 7 + j], Math.max(...data));
const opacity = data[i * 7 + j] / Math.max(...data); // Berechne die Opazität basierend auf Aktivitätsanzahl const opacity = data[i * 7 + j] / (Math.max(...data) <= 0 ? 1 : Math.max(...data)); // Berechne die Opazität basierend auf Aktivitätsanzahl
if (data[i * 7 + j]) { if (data[i * 7 + j]) {
const dayElement = document.createElement('div'); const dayElement = document.createElement('div');
dayElement.classList.add('day'); dayElement.classList.add('day');
dayElement.style.backgroundColor = `rgba(0, 255, 0, ${opacity})`; dayElement.style.backgroundColor = `rgba(0, 255, 0, ${opacity})`;
heatmapContainer.appendChild(dayElement); heatmapContainer.appendChild(dayElement);
} else { } else {
const dayElement = document.createElement('div'); const dayElement = document.createElement('div');
// dayElement.classList.add('day'); dayElement.classList.add('day');
// dayElement.style.backgroundColor = `rgba(0, 255, 0, ${opacity})`; dayElement.style.backgroundColor = `rgba(0, 255, 0, ${opacity})`;
heatmapContainer.appendChild(dayElement); heatmapContainer.appendChild(dayElement);
}
} }
} }
var left = 7 - (new Date()).getDay();
} }
}
// Erstelle die Heatmap mit den simulierten Daten // Erstelle die Heatmap mit den simulierten Daten
createHeatmap(activityData); createHeatmap(activityData);
</script> </script>
<div class="col-md-7 col-12 card gap-3 bg-light p-6 offset-md-1 mb-6"> <div class="flex-fill col-7 card bg-light p-6 mb-6">
<div class="row mb-3 "> <div class="row mb-3 ">
<h2 class="col-9">Gewohnheiten</h2> <h2 class="col-9">Gewohnheiten</h2>
<a class="col-3 btn btn-primary p" role="button" href="/habit-list">Neue Liste erstellen</a> <a class="col-3 btn btn-primary p" role="button" href="/habit-list">Neue Liste erstellen</a>
</div> </div>
{% for habit_list in habit_lists %} {% for habit_list in habit_lists %}
<div class="row mb-3"> <div class="row mb-3">
<h2 class="col-9">{{ habit_list.name }}</h2> <h2 class="col-9">{{ habit_list.name }}</h2>
<a class="col-3 btn btn-primary" role="button" href="/habit?list={{ habit_list.id }}">Gewohnheit <a class="col-3 btn btn-primary" role="button" href="/habit?list={{ habit_list.id }}">Gewohnheit
erstellen</a> erstellen</a>
</div> </div>
<ul class="task-list row"> <ul class="task-list row">
{% for habit in habit_list.habits %} {% for habit in habit_list.habits %}
<li class="row d-flex align-items-center mb-2" id="habit-{{ habit.id }}"> <li class="row d-flex align-items-center mb-2" id="habit-{{ habit.id }}">
<div class="col-auto drag-handle" style="cursor: grab;"> <div class="col-auto drag-handle" style="cursor: grab;">
<i class="bi bi-grip-vertical"></i> <i class="bi bi-grip-vertical"></i>
</div>
<div class="col-auto">
<input {% if habit.checked %} checked {% endif %} type="checkbox" class="task-checkbox"
id="{{ habit.id }}"
onclick="sendPostRequest('{{ habit.id }}')">
</div>
<div class="col" style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">
{{ habit.name }}
</div>
<div class="col-5 text-black text-opacity-50" style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">
{{ habit.note }}
</div>
<div class="col-2" style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">
{% if habit %}
{% else %}
5 🔥
{% endif %}
</div>
<button type="button" class="btn btn-xs btn-danger rounded-circle" data-bs-toggle="modal"
data-bs-target="#exampleModal" style="width: 40px; height: 40px"
onclick="setSelectedHabitId({{ habit.id }})">
<i class="bi bi-trash3"></i>
</button>
<div class="col-12">
<div class="progress" style="height: 2px; width: 90%">
<div class="progress-bar" id="progress-bar-{{ habit.id }}" role="progressbar"
style="width: {{ habit.percentage }}%; background-color: {% if habit.percentage >= 100 %} green {% else %} primary {% endif %}"
aria-valuenow="{{ habit.percentage }}" aria-valuemin="0"
aria-valuemax="100"></div>
</div> </div>
</div> <div class="col-auto">
</li> <input {% if habit.checked %} checked {% endif %} type="checkbox" class="task-checkbox"
id="{{ habit.id }}"
onclick="sendPostRequest('{{ habit.id }}')">
</div>
<div class="col" style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">
{{ habit.name }}
</div>
<div class="col-5 text-black text-opacity-50"
style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">
{{ habit.note }}
</div>
<div class="col-2" style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">
{% if habit %}
{% else %}
5 🔥
{% endif %}
</div>
<button type="button" class="btn btn-xs btn-danger rounded-circle" data-bs-toggle="modal"
data-bs-target="#exampleModal" style="width: 40px; height: 40px"
onclick="setSelectedHabitId({{ habit.id }})">
<i class="bi bi-trash3"></i>
</button>
<div class="col-12">
<div class="progress" style="height: 2px; width: 90%">
<div class="progress-bar" id="progress-bar-{{ habit.id }}" role="progressbar"
style="width: {{ habit.percentage }}%; background-color: {% if habit.percentage >= 100 %} green {% else %} primary {% endif %}"
aria-valuenow="{{ habit.percentage }}" aria-valuemin="0"
aria-valuemax="100"></div>
</div>
</div>
</li>
{% endfor %}
</ul>
{% endfor %} {% endfor %}
</ul> </div>
{% endfor %} <script>
</div> var selectedHabitId = null;
<script> function setSelectedHabitId(habitId) {
var selectedHabitId = null; selectedHabitId = habitId;
}
</script>
function setSelectedHabitId(habitId) { <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
selectedHabitId = habitId; <div class="modal-dialog">
} <div class="modal-content">
</script> <div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">Bestätige</h1>
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true"> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<div class="modal-dialog"> </div>
<div class="modal-content"> <div class="modal-body">
<div class="modal-header"> Möchtest du dieses Habit wirklich löschen?
<h1 class="modal-title fs-5" id="exampleModalLabel">Bestätige</h1> </div>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <div class="modal-footer">
</div> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<div class="modal-body"> <button type="button" class="btn btn-primary btn-danger" data-bs-dismiss="modal"
Möchtest du dieses Habit wirklich löschen? onclick="deleteHabit(selectedHabitId)">Löschen
</div> </button>
<div class="modal-footer"> </div>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary btn-danger" data-bs-dismiss="modal"
onclick="deleteHabit(selectedHabitId)">Löschen
</button>
</div> </div>
</div> </div>
</div> </div>
</div>
<script> <script>
function checkCompletionAndAnimate(habitId, percentage) { function checkCompletionAndAnimate(habitId, percentage) {
var progressBar = document.getElementById("progress-bar-" + habitId);
var habitBlock = document.getElementById("habit-" + habitId);
if (percentage == 100) {
progressBar.style.backgroundColor = "green";
habitBlock.classList.add("animate-bounce");
setTimeout(function () {
habitBlock.classList.remove("animate-bounce");
}, 2000);
} else {
progressBar.style.backgroundColor = "";
habitBlock.classList.remove("animate-bounce");
}
}
function sendPostRequest(checkboxId) {
// Get the checkbox element using the provided ID
var checkbox = document.getElementById(checkboxId);
// console.log(checkbox);
// Get the habit id from the checkbox id attribute
var habitId = checkboxId;
// Make a POST request to /check with the habit id
axios.post('/check', {habitId: habitId}, {
headers: {
'Content-Type': 'application/json'
}
}).then(function (response) {
// Handle the success response if needed
console.log(response.data);
// Set the percentage of the habit. percentage received as integer
var percentage = response.data.percentage;
var progressBar = document.getElementById("progress-bar-" + habitId); var progressBar = document.getElementById("progress-bar-" + habitId);
progressBar.style.width = percentage + "%"; var habitBlock = document.getElementById("habit-" + habitId);
checkCompletionAndAnimate(habitId, percentage);
}).catch(function (error) {
// Handle the error if needed
console.error('Error:', error);
});
}
function deleteHabit(habitId) { if (percentage == 100) {
// Make a POST request to /delete with the habit id progressBar.style.backgroundColor = "green";
habitBlock.classList.add("animate-bounce");
axios.post('/delete', {habitId: habitId}, { setTimeout(function () {
headers: { habitBlock.classList.remove("animate-bounce");
'Content-Type': 'application/json' }, 2000);
} else {
progressBar.style.backgroundColor = "";
habitBlock.classList.remove("animate-bounce");
} }
}).then(function (response) { }
// Handle the success response if needed
console.log(response.data);
// Remove the habit from the DOM function sendPostRequest(checkboxId) {
var habitElement = document.getElementById("habit-" + habitId); // Get the checkbox element using the provided ID
habitElement.remove(); var checkbox = document.getElementById(checkboxId);
}).catch(function (error) { // console.log(checkbox);
// Handle the error if needed
console.error('Error:', error); // Get the habit id from the checkbox id attribute
}); var habitId = checkboxId;
}
</script> // Make a POST request to /check with the habit id
axios.post('/check', {habitId: habitId}, {
headers: {
'Content-Type': 'application/json'
}
}).then(function (response) {
// Handle the success response if needed
console.log(response.data);
// Set the percentage of the habit. percentage received as integer
var percentage = response.data.percentage;
var progressBar = document.getElementById("progress-bar-" + habitId);
progressBar.style.width = percentage + "%";
checkCompletionAndAnimate(habitId, percentage);
}).catch(function (error) {
// Handle the error if needed
console.error('Error:', error);
});
}
function deleteHabit(habitId) {
// Make a POST request to /delete with the habit id
axios.post('/delete', {habitId: habitId}, {
headers: {
'Content-Type': 'application/json'
}
}).then(function (response) {
// Handle the success response if needed
console.log(response.data);
// Remove the habit from the DOM
var habitElement = document.getElementById("habit-" + habitId);
habitElement.remove();
}).catch(function (error) {
// Handle the error if needed
console.error('Error:', error);
});
}
</script>
</div>
</div> </div>
<script> <script>