324 lines
11 KiB
HTML
324 lines
11 KiB
HTML
{% extends 'layouts/main.html' %}
|
|
|
|
{% block content %}
|
|
<h1>{{ title }}</h1>
|
|
<h3>{{ utc_dt }}</h3>
|
|
|
|
|
|
<style>
|
|
#heatmap {
|
|
display: grid;
|
|
grid-template-columns: repeat(7, 0fr); /* 7 Tage in einer Woche */
|
|
gap: 5px;
|
|
}
|
|
|
|
.day {
|
|
width: 50px;
|
|
height: 50px;
|
|
border: 1px solid #ccc;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
</style>
|
|
|
|
<div class="row">
|
|
|
|
<div class="col-md-5 col-12">
|
|
<div id="heatmap"></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));
|
|
}
|
|
|
|
// 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];
|
|
|
|
// 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']
|
|
|
|
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
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Erstelle die Heatmap mit den simulierten Daten
|
|
createHeatmap(activityData);
|
|
|
|
|
|
</script>
|
|
|
|
<div class="col-md-7 col-12">
|
|
<div class="row mb-3">
|
|
<h2 class="col-10">Task List</h2>
|
|
<a class="col-2 btn btn-primary" role="button" href="/habit">
|
|
Task erstellen
|
|
</a>
|
|
</div>
|
|
|
|
<ul class="task-list row draggable-list" id="draggable-list">
|
|
{% for habit in habits %}
|
|
<li class="row d-flex align-items-center mb-2 draggable" id="habit-{{habit.id}}" draggable="true">
|
|
<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-8" style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">
|
|
{{ habit.note }}
|
|
</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>
|
|
</div>
|
|
|
|
<script>
|
|
var selectedHabitId = null;
|
|
|
|
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>
|
|
</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;
|
|
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>
|
|
<script>
|
|
const draggable_list = document.getElementById('draggable-list');
|
|
const check = document.getElementById('check');
|
|
|
|
const richestPeople = [
|
|
'Jeff Bezos',
|
|
'Bill Gates',
|
|
'Warren Buffett',
|
|
'Bernard Arnault',
|
|
'Carlos Slim Helu',
|
|
'Amancio Ortega',
|
|
'Larry Ellison',
|
|
'Mark Zuckerberg',
|
|
'Michael Bloomberg',
|
|
'Larry Page'
|
|
];
|
|
|
|
// Store listitems
|
|
const listItems =
|
|
|
|
let dragStartIndex;
|
|
|
|
createList();
|
|
|
|
// Insert list items into DOM
|
|
function createList() {
|
|
[...richestPeople]
|
|
.map(a => ({ value: a, sort: Math.random() }))
|
|
.sort((a, b) => a.sort - b.sort)
|
|
.map(a => a.value)
|
|
.forEach((person, index) => {
|
|
const listItem = document.createElement('li');
|
|
|
|
listItem.setAttribute('data-index', index);
|
|
|
|
listItem.innerHTML = `
|
|
<span class="number">${index + 1}</span>
|
|
<div class="draggable" draggable="true">
|
|
<p class="person-name">${person}</p>
|
|
<i class="fas fa-grip-lines"></i>
|
|
</div>
|
|
`;
|
|
|
|
listItems.push(listItem);
|
|
|
|
draggable_list.appendChild(listItem);
|
|
});
|
|
|
|
addEventListeners();
|
|
}
|
|
|
|
function dragStart() {
|
|
// console.log('Event: ', 'dragstart');
|
|
dragStartIndex = +this.closest('li').getAttribute('data-index');
|
|
}
|
|
|
|
function dragEnter() {
|
|
// console.log('Event: ', 'dragenter');
|
|
this.classList.add('over');
|
|
}
|
|
|
|
function dragLeave() {
|
|
// console.log('Event: ', 'dragleave');
|
|
this.classList.remove('over');
|
|
}
|
|
|
|
function dragOver(e) {
|
|
// console.log('Event: ', 'dragover');
|
|
e.preventDefault();
|
|
}
|
|
|
|
function dragDrop() {
|
|
// console.log('Event: ', 'drop');
|
|
const dragEndIndex = +this.getAttribute('data-index');
|
|
swapItems(dragStartIndex, dragEndIndex);
|
|
|
|
this.classList.remove('over');
|
|
}
|
|
|
|
// Swap list items that are drag and drop
|
|
function swapItems(fromIndex, toIndex) {
|
|
const itemOne = listItems[fromIndex].querySelector('.draggable');
|
|
const itemTwo = listItems[toIndex].querySelector('.draggable');
|
|
|
|
listItems[fromIndex].appendChild(itemTwo);
|
|
listItems[toIndex].appendChild(itemOne);
|
|
}
|
|
|
|
function addEventListeners() {
|
|
const draggables = document.querySelectorAll('.draggable');
|
|
const dragListItems = document.querySelectorAll('.draggable-list li');
|
|
|
|
draggables.forEach(draggable => {
|
|
draggable.addEventListener('dragstart', dragStart);
|
|
});
|
|
|
|
dragListItems.forEach(item => {
|
|
item.addEventListener('dragover', dragOver);
|
|
item.addEventListener('drop', dragDrop);
|
|
item.addEventListener('dragenter', dragEnter);
|
|
item.addEventListener('dragleave', dragLeave);
|
|
});
|
|
}
|
|
|
|
check.addEventListener('click', checkOrder);
|
|
</script>
|
|
{% endblock %} |