Compare commits
5 Commits
454ce33846
...
ce0a6b588b
| Author | SHA1 | Date | |
|---|---|---|---|
| ce0a6b588b | |||
| 6143f44442 | |||
|
|
aaeb04d4ab | ||
|
|
0f060e81a4 | ||
|
|
1180893dd1 |
1
app.py
1
app.py
@ -136,6 +136,7 @@ def index():
|
||||
title=name,
|
||||
utc_dt=datetime.datetime.now().strftime("%d.%m.%Y %H:%M %A"),
|
||||
habit_lists=habit_lists,
|
||||
heatmap_values=current_user.get_heatmap(),
|
||||
errors={},
|
||||
)
|
||||
|
||||
|
||||
@ -80,6 +80,9 @@ class Habit:
|
||||
count = 0
|
||||
self.checked = False
|
||||
for tracking in self.get_habitTrackings():
|
||||
if tracking.created_at.date() == datetime.today().date():
|
||||
self.checked = True
|
||||
|
||||
# day
|
||||
if self.unit == 0:
|
||||
if tracking.created_at.date() == datetime.today().date():
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
from datetime import datetime
|
||||
|
||||
from flask_login import UserMixin
|
||||
from db.SQLiteClient import create_user, get_user, get_user_by_email, get_habits, delete_user, update_user, \
|
||||
get_habitLists
|
||||
from db.SQLiteClient import create_user, get_user, get_user_by_email, delete_user, update_user, \
|
||||
get_habitLists, get_heatmap_value
|
||||
|
||||
|
||||
class User(UserMixin):
|
||||
@ -43,3 +43,10 @@ class User(UserMixin):
|
||||
habitLists.append(habitList)
|
||||
|
||||
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
|
||||
@ -21,228 +21,226 @@
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-4 col-12 card bg-light mb-6">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Heatmap</h5>
|
||||
<div id="heatmap"></div>
|
||||
<div class="d-flex flex-column gap-5">
|
||||
<div class="d-flex gap-3">
|
||||
<div class="flex-fill col-5 card bg-light mb-6">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Heatmap</h5>
|
||||
<div id="heatmap"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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));
|
||||
}
|
||||
<script>
|
||||
|
||||
// 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];
|
||||
// Simulierte Aktivitätsdaten (ersetze dies durch deine echten Daten)
|
||||
const activityData = {{heatmap_values}};
|
||||
|
||||
// Funktion zum Erstellen der Heatmap
|
||||
function createHeatmap(data) {
|
||||
const heatmapContainer = document.getElementById('heatmap');
|
||||
// Funktion zum Erstellen der Heatmap
|
||||
function createHeatmap(data) {
|
||||
const heatmapContainer = document.getElementById('heatmap');
|
||||
|
||||
// Aktuelles Datum des Montags
|
||||
const days = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']
|
||||
// Aktuelles Datum des Montags
|
||||
const days = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']
|
||||
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const dayElement = document.createElement('div');
|
||||
dayElement.classList.add('day');
|
||||
dayElement.textContent = days[i];
|
||||
heatmapContainer.appendChild(dayElement);
|
||||
// currentDate.setDate(currentDate.getDate() + 1);
|
||||
}
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const dayElement = document.createElement('div');
|
||||
dayElement.classList.add('day');
|
||||
dayElement.textContent = days[i];
|
||||
heatmapContainer.appendChild(dayElement);
|
||||
// currentDate.setDate(currentDate.getDate() + 1);
|
||||
}
|
||||
|
||||
// Aktuelles Datum des Montags in der neuen linken Spalte
|
||||
for (let i = 0; i < 7; i++) {
|
||||
for (let j = 0; j < 7; j++) {
|
||||
// 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
|
||||
// Aktuelles Datum des Montags in der neuen linken Spalte
|
||||
for (let i = 0; i < 7; i++) {
|
||||
for (let j = 0; j < 4; j++) {
|
||||
// console.log(i * 7 + j, data[i * 7 + j], Math.max(...data));
|
||||
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]) {
|
||||
const dayElement = document.createElement('div');
|
||||
dayElement.classList.add('day');
|
||||
dayElement.style.backgroundColor = `rgba(0, 255, 0, ${opacity})`;
|
||||
heatmapContainer.appendChild(dayElement);
|
||||
} else {
|
||||
const dayElement = document.createElement('div');
|
||||
// dayElement.classList.add('day');
|
||||
// dayElement.style.backgroundColor = `rgba(0, 255, 0, ${opacity})`;
|
||||
heatmapContainer.appendChild(dayElement);
|
||||
if (data[i * 7 + j]) {
|
||||
const dayElement = document.createElement('div');
|
||||
dayElement.classList.add('day');
|
||||
dayElement.style.backgroundColor = `rgba(0, 255, 0, ${opacity})`;
|
||||
heatmapContainer.appendChild(dayElement);
|
||||
} else {
|
||||
const dayElement = document.createElement('div');
|
||||
dayElement.classList.add('day');
|
||||
dayElement.style.backgroundColor = `rgba(0, 255, 0, ${opacity})`;
|
||||
heatmapContainer.appendChild(dayElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var left = 7 - (new Date()).getDay();
|
||||
}
|
||||
}
|
||||
|
||||
// Erstelle die Heatmap mit den simulierten Daten
|
||||
createHeatmap(activityData);
|
||||
// Erstelle die Heatmap mit den simulierten Daten
|
||||
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="row mb-3 ">
|
||||
<h2 class="col-9">Gewohnheiten</h2>
|
||||
<a class="col-3 btn btn-primary p" role="button" href="/habit-list">Neue Liste erstellen</a>
|
||||
</div>
|
||||
<div class="flex-fill col-7 card bg-light p-6 mb-6">
|
||||
<div class="row mb-3 ">
|
||||
<h2 class="col-9">Gewohnheiten</h2>
|
||||
<a class="col-3 btn btn-primary p" role="button" href="/habit-list">Neue Liste erstellen</a>
|
||||
</div>
|
||||
|
||||
{% for habit_list in habit_lists %}
|
||||
{% for habit_list in habit_lists %}
|
||||
|
||||
<div class="row mb-3">
|
||||
<h2 class="col-9">{{ habit_list.name }}</h2>
|
||||
<a class="col-3 btn btn-primary" role="button" href="/habit?list={{ habit_list.id }}">Gewohnheit
|
||||
erstellen</a>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<h2 class="col-9">{{ habit_list.name }}</h2>
|
||||
<a class="col-3 btn btn-primary" role="button" href="/habit?list={{ habit_list.id }}">Gewohnheit
|
||||
erstellen</a>
|
||||
</div>
|
||||
|
||||
<ul class="task-list row">
|
||||
{% for habit in habit_list.habits %}
|
||||
<li class="row d-flex align-items-center mb-2" id="habit-{{ habit.id }}">
|
||||
<div class="col-auto drag-handle" style="cursor: grab;">
|
||||
<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>
|
||||
<ul class="task-list row">
|
||||
{% for habit in habit_list.habits %}
|
||||
<li class="row d-flex align-items-center mb-2" id="habit-{{ habit.id }}">
|
||||
<div class="col-auto drag-handle" style="cursor: grab;">
|
||||
<i class="bi bi-grip-vertical"></i>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<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>
|
||||
</li>
|
||||
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
<script>
|
||||
var selectedHabitId = null;
|
||||
|
||||
<script>
|
||||
var selectedHabitId = null;
|
||||
function setSelectedHabitId(habitId) {
|
||||
selectedHabitId = habitId;
|
||||
}
|
||||
</script>
|
||||
|
||||
function setSelectedHabitId(habitId) {
|
||||
selectedHabitId = habitId;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="exampleModalLabel">Bestätige</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
Möchtest du dieses Habit wirklich löschen?
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<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 class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="exampleModalLabel">Bestätige</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
Möchtest du dieses Habit wirklich löschen?
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<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>
|
||||
|
||||
|
||||
<script>
|
||||
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;
|
||||
<script>
|
||||
function checkCompletionAndAnimate(habitId, 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);
|
||||
});
|
||||
}
|
||||
var habitBlock = document.getElementById("habit-" + habitId);
|
||||
|
||||
function deleteHabit(habitId) {
|
||||
// Make a POST request to /delete with the habit id
|
||||
|
||||
axios.post('/delete', {habitId: habitId}, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
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");
|
||||
}
|
||||
}).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>
|
||||
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);
|
||||
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>
|
||||
|
||||
<script>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user