Create Edit Form with first functions && Edit JS Libarys && Show Yearly infos

sortierung
Samuel Zielke 1 year ago
parent b7755949c8
commit e0109b09ff

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

@ -3,6 +3,13 @@ const dbName = 'myDB';
const dbVersion = 1; const dbVersion = 1;
let db; let db;
//
// GRUND FUNKTIONEN FÜR DIE DATENBANK
//
// IndexedDB initialisieren // IndexedDB initialisieren
function initDB() { function initDB() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -121,36 +128,6 @@ function getAllEntries() {
}); });
} }
// Einträge nach Monat und/oder Jahr filtern
function filterEntriesByMonthYear(month, year) {
return new Promise((resolve, reject) => {
const transaction = db.transaction(['hours'], 'readonly');
const store = transaction.objectStore('hours');
const request = store.getAll();
request.onsuccess = function () {
const allEntries = request.result;
// Filter nach Monat und Jahr
const filteredEntries = allEntries.filter(entry => {
const entryDate = new Date(entry.date); // Konvertiere das date-Feld in ein Date-Objekt
const matchesMonth = month ? entryDate.getMonth() + 1 === month : true; // +1 da getMonth() 0-basiert ist
const matchesYear = year ? entryDate.getFullYear() === year : true;
return matchesMonth && matchesYear;
});
resolve(filteredEntries);
};
request.onerror = function (event) {
reject('Fehler beim Abrufen der Einträge:', event.target.error);
};
});
}
// Neuen Eintrag verschlüsselt speichern // Neuen Eintrag verschlüsselt speichern
async function addEncryptedEntry(data) { async function addEncryptedEntry(data) {
const key = await generateKey(); const key = await generateKey();
@ -200,5 +177,179 @@ async function getDecryptedEntry(id) {
request.onerror = function (event) { request.onerror = function (event) {
reject('Fehler beim Abrufen des verschlüsselten Eintrags:', event.target.error); reject('Fehler beim Abrufen des verschlüsselten Eintrags:', event.target.error);
}; };
}); });
}
function durationDBtoForm(durationInMin) {
const hours = Math.floor(durationInMin / 60); // Ganze Stunden berechnen
const mins = durationInMin % 60; // Verbleibende Minuten berechnen
return [hours, mins]
}
//
// KOMBI FUNKTIONEN
// SIND VOR ALLEM HIER DAMIT SIE ZEITGLEICH GERENDERT WERDEN
//
// Die abgefragte Dauer in Minuten umrechnen und in hh:mm formatieren
function formatDuration(minutes, shortOutput = false) {
const hours = Math.floor(minutes / 60); // Ganze Stunden berechnen
const mins = minutes % 60; // Verbleibende Minuten berechnen
if (!shortOutput){
return `${String(hours).padStart(2, '0')}:${String(mins).padStart(2, '0')}`; // Stunden und Minuten formatieren
} else {
return `${String(hours)}:${String(mins)}`.replace(':30', ',5').replace(':0', ''); // Stunden und Minuten formatieren
}
}
// Datum für die gewünschte Ansicht formatieren
function formatDate(dateString) {
const date = new Date(dateString); // Konvertiere in ein Date-Objekt
const day = String(date.getDate()).padStart(2, '0'); // Tag
const month = String(date.getMonth() + 1).padStart(2, '0'); // Monat (getMonth() ist 0-basiert)
const year = String(date.getFullYear()).slice(-2); // Die letzten 2 Ziffern des Jahres
return `${day}.${month}.${year}`; // Format tt.mm.yy
}
// Einträge nach Monat und/oder Jahr filtern
function filterEntriesByMonthYear(month, year) {
return new Promise((resolve, reject) => {
const transaction = db.transaction(['hours'], 'readonly');
const store = transaction.objectStore('hours');
const request = store.getAll();
request.onsuccess = function () {
const allEntries = request.result;
// Filter nach Monat und Jahr
const filteredEntries = allEntries.filter(entry => {
const entryDate = new Date(entry.date); // Konvertiere das date-Feld in ein Date-Objekt
const matchesMonth = month ? entryDate.getMonth() + 1 === month : true; // +1 da getMonth() 0-basiert ist
const matchesYear = year ? entryDate.getFullYear() === year : true;
return matchesMonth && matchesYear;
});
resolve(filteredEntries);
};
request.onerror = function (event) {
reject('Fehler beim Abrufen der Einträge:', event.target.error);
};
});
}
// Tabelle auf dem Dashboard mit Infos füllen
function fillTableWithEntries(entries) {
const tableBody = document.getElementById('entriesTableBody');
// Zuerst den Inhalt der Tabelle löschen (falls schon Daten da sind)
tableBody.innerHTML = '';
// Iteriere durch die Einträge und füge Zeilen hinzu
entries.forEach(entry => {
const row = document.createElement('tr');
//EVENTUELL MAL IN DER ZUKUNFT - UM EINTRÄGE ZU SEITE WISCHEN
// let startX = 0;
// let currentRow;
// row.addEventListener('touchstart', (e) => {
// startX = e.touches[0].clientX;
// currentRow = e.currentTarget;
// });
// row.addEventListener('touchmove', (e) => {
// const moveX = e.touches[0].clientX;
// if (startX - moveX > 50) {
// currentRow.classList.add('swipe-left');
// }
// });
// // Am Ende des Swipe, zeige den Löschen-Button
// row.addEventListener('touchend', () => {
// if (currentRow.classList.contains('swipe-left')) {
// currentRow.querySelector('.editCell').classList.remove('d-none')
// currentRow.querySelector('.delCell').classList.remove('d-none')
// currentRow.querySelector('.duration').classList.add('d-none')
// currentRow.querySelector('.date').classList.add('d-none')
// }
// });
// Spalte für die Dauer (duration)
const durationCell = document.createElement('td');
durationCell.classList.add('duration')
durationCell.textContent = formatDuration(entry.duration); // Dauer im hh:mm-Format
row.appendChild(durationCell);
// Spalte für das Datum (date)
const dateCell = document.createElement('td');
const entryDate = new Date(entry.date); // Konvertiere in ein Date-Objekt
dateCell.classList.add('date')
dateCell.textContent = formatDate(entry.date); // Datum im tt.mm.yy-Format
row.appendChild(dateCell);
// Spalte für den Typ (type) - wenn 3, dann zeige "Beschreibung" an
const typeCell = document.createElement('td');
if (entry.type === 3) {
typeCell.textContent = entry.sondertext; // Bei Type 3 zeige "Beschreibung" an
} else if (entry.type === 2) {
typeCell.textContent = 'LDC'; // Ansonsten zeige den Type-Wert
} else if (entry.type === 1) {
typeCell.textContent = 'Dienst'; // Ansonsten zeige den Type-Wert
}
row.appendChild(typeCell);
const editCell = document.createElement('td');
// editCell.classList.add('editCell')
// editCell.style = 'background-color: rgb(120,170,86); color: white;'
editCell.addEventListener('click', ()=>{
document.getElementById('editEntryID').value = entry.id;
document.getElementById('editStunden').value = durationDBtoForm(entry.duration)[0];
document.getElementById('editMinuten').value = durationDBtoForm(entry.duration)[1];
document.getElementById('editDatum').value = entry.date;
if (entry.type === 2) {
document.getElementById('editldcCheck').checked = true;
} else if (entry.type === 3) {
document.getElementById('editsonstigesCheck').checked = true;
document.getElementById('editsonstigesInput').value = entry.sondertext;
document.getElementById('edit-sonstiges-text').style.display = 'block';
}
console.log(entry.id)
})
editCell.innerHTML = '<span class="btn btn-sm btn-secondary" data-bs-toggle="modal" data-bs-target="#editEntryModel" style="width: 40px; border-radius: 1rem;">✐</span>';
row.appendChild(editCell)
// const delCell = document.createElement('td');
// delCell.classList.add('d-none')
// delCell.classList.add('delCell')
// delCell.style = 'background-color: red; color: white;'
// delCell.innerHTML = '<p style="margin: 0; padding: 0;">Delete</p>'
// row.appendChild(delCell)
// Füge die erstellte Zeile dem Tabellenkörper hinzu
tableBody.appendChild(row);
});
}
// Abgefragte Daten Zeiten summieren und filtern können
function sumDurations(data, type = null, roundToHalfHour = false) {
// Optionaler Filter nach dem Typ, falls ein Typ angegeben wurde
const filteredData = type !== null ? data.filter(item => item.type === type) : data;
// Berechnung der Summe der "duration"-Werte
let totalDuration = filteredData.reduce((sum, item) => sum + item.duration, 0);
// Optionales Runden auf halbe Stunden
if (roundToHalfHour) {
totalDuration = Math.round(totalDuration / 30) * 30;
}
return totalDuration;
} }

@ -0,0 +1,198 @@
// Absende Formular Verwalten
const hours = document.getElementById('stunden');
const mins = document.getElementById('minuten');
const NewEntryButton = document.getElementById('newEntrySubmitButton')
var allowToSend = false;
//
// Trigger
//
// Wenn das Dokument komplett geladen ist
document.addEventListener('DOMContentLoaded', (event) => {
initDB().then(() => {
console.log('IndexedDB erfolgreich initialisiert.');
// Hier kannst du die App weiter initialisieren, z.B. Daten laden oder die UI aufbauen
// Bildschirm mit dem Inhalt für den aktuellen Tag füllen
getActualDataAndFillView();
//loadInitialData();
}).catch((error) => {
console.error('Fehler bei der Initialisierung der IndexedDB:', error);
});
});
// Änderungen überwachen damit die das Formular nicht zu früh abgesendet wird
hours.addEventListener('input', () => {
checkInput();
})
mins.addEventListener('input', () => {
checkInput();
})
document.getElementById('sonstigesInput').addEventListener('input', () => {
checkInput();
})
// Einstellungen wenn Neuer Eintrag erstellt wird
NewEntryButton.addEventListener('click', () => {
if (allowToSend === true) {
var type = 1
// Abfragen der Checkboxen
const ldcCheck = document.getElementById('ldcCheck').checked
if (ldcCheck) {
type = 2
document.getElementById('ldcCheck').checked = false
} else if (document.getElementById('sonstigesCheck').checked) {
type = 3;
document.getElementById('sonstigesCheck').checked = false;
sonstigesText.style.display = 'none';
}
// Berechnen der Duration
const duration = (parseInt(hours.value)*60) + parseInt(mins.value)
const newEntryData = {
date: document.getElementById('datum').value,
duration: duration,
type: type,
status: 1,
sondertext: document.getElementById('sonstigesInput').value,
}
addEntry(newEntryData).then((id) => {
console.log('Eintrag hinzugefügt mit ID:', id);
});
hours.value = null
mins.value = null
document.getElementById('sonstigesInput').value = null
checkInput()
}
})
async function getActualDataAndFillView() {
try {
// Aktuelles Datum
const currentDate = new Date();
// Filter funktion aufrufen und entsprechend mit dem aktuellen Datum füllen
const filteredEntries = await filterEntriesByMonthYear(currentDate.getMonth() + 1, currentDate.getFullYear());
// Tabelle mit den aktuellen informationen füllen (funktion triggern und Daten übergeben)
fillTableWithEntries(filteredEntries)
// Ausgabe der Daten in den Log für DEV möglich
// console.log('Gefilterte Einträge für September 2024:', filteredEntries);
// MonatsCard füllen
// Aktueller Monatsstand an Stunden
const GesamtStundenMonat = formatDuration(sumDurations(filteredEntries,null,true), true)
document.getElementById('monthHours').innerText = GesamtStundenMonat
document.getElementById('prBarMonth').style.width = `${(100/50)*parseInt(GesamtStundenMonat)}%`
// Aktueller Rest an Stunden
const rest = 50 - parseInt(GesamtStundenMonat)
if (rest > 0) {
document.getElementById('monthRest').innerText = rest
} else {
document.getElementById('monthRest').innerText = 0
}
// Aufteilunge Stunden nach Dienst und LDC
document.getElementById('monthHourService').innerText = formatDuration(sumDurations(filteredEntries,1,true), true)
document.getElementById('monthHourLDC').innerText = formatDuration(sumDurations(filteredEntries,2,true), true)
document.getElementById('monthHourOther').innerText = formatDuration(sumDurations(filteredEntries,3,true), true)
// Jahres Ansicht füllen
var yearData = await filterEntriesByMonthYear(null, currentDate.getFullYear());
yearData = formatDuration(sumDurations(yearData, null, true), true)
document.getElementById('yearHours').innerText = yearData
document.getElementById('yearRest').innerText = 600 - parseInt(yearData)
document.getElementById('prBarYear').style.width = `${Math.round((100/600)*parseInt(yearData))}%`
} catch (error) {
console.error('Fehler bei der Initialisierung oder Filterung:', error);
}
}
//
// NEUES EINTRAG FORMULAR
//
// Checkboxen-Verhalten: Nur eine Checkbox kann ausgewählt werden
var ldcCheck = document.getElementById('ldcCheck');
var sonstigesCheck = document.getElementById('sonstigesCheck');
var sonstigesText = document.getElementById('sonstiges-text');
var sonstigesInput = document.getElementById('sonstigesInput');
ldcCheck.addEventListener('change', function() {
if (ldcCheck.checked) {
sonstigesCheck.checked = false;
sonstigesText.style.display = 'none';
sonstigesInput.removeAttribute('required'); // Entferne required, wenn "Sonstiges" abgewählt ist
}
});
sonstigesCheck.addEventListener('change', function() {
checkInput();
if (sonstigesCheck.checked) {
ldcCheck.checked = false;
sonstigesText.style.display = 'block';
sonstigesInput.setAttribute('required', 'required'); // Setze required, wenn "Sonstiges" ausgewählt ist
} else {
sonstigesText.style.display = 'none';
sonstigesInput.removeAttribute('required'); // Entferne required, wenn "Sonstiges" abgewählt ist
}
});
//
// FUNKTIONEN LIBARY
//
function checkInput() {
// Eingabe feld für Beschreibung leeren wenn sonstiges abgewählt wird
if (!sonstigesCheck.checked) {
sonstigesInput.value = null;
}
// Debug ausgabe er Werte
// console.log(`Check: ${sonstigesCheck.checked} - Input: ${sonstigesInput.value} - Stunden: ${hours.value} - Min: ${mins.value}`)
// Berechtigungen durch gehen damit Button verfügbar und Form abgesendet werden kann
if ((sonstigesCheck.checked && sonstigesInput.value !== "") || !(sonstigesCheck.checked)) {
// Debug Ausgabe für Bedingungsstufen
// console.log("Erste Bedingung: TRUE")
if (hours.value && mins.value) {
// Debug Ausgabe für Bedingungsstufen
// console.log("Zweite Bedingung: TRUE")
if (!allowToSend) {
// Debug Ausgabe für Bedingungsstufen
// console.log("Dritte Bedingung: TRUE")
allowToSend = true;
NewEntryButton.classList.remove('disabled');
NewEntryButton.classList.replace('btn-light', 'btn-primary');
}
} else if (allowToSend) {
allowToSend = false;
NewEntryButton.classList.add('disabled');
NewEntryButton.classList.replace('btn-primary', 'btn-light');
}
} else if (allowToSend) {
allowToSend = false;
NewEntryButton.classList.add('disabled');
NewEntryButton.classList.replace('btn-primary', 'btn-light');
}
}

@ -28,15 +28,15 @@ self.addEventListener('activate', event => {
); );
}); });
// Serve from Cache // // Serve from Cache
self.addEventListener("fetch", event => { // self.addEventListener("fetch", event => {
event.respondWith( // event.respondWith(
caches.match(event.request) // caches.match(event.request)
.then(response => { // .then(response => {
return response || fetch(event.request); // return response || fetch(event.request);
}) // })
.catch(() => { // .catch(() => {
return caches.match('app/home'); // return caches.match('app/home');
}) // })
) // )
}); // });

@ -0,0 +1,16 @@
/* ALLES RUND UM DIE WILLKOMMENSMELDUNG */
function setAllOk() {
document.getElementById('welcome_content').style.display = 'none';
document.getElementById('dashboard').classList.remove('d-none');
document.getElementById('refresh_icon').classList.remove('d-none')
document.getElementById('settings_icon').classList.remove('d-none')
}
document.getElementById("allOk").addEventListener('click', function(){
setAllOk();
localStorage.setItem('infoReadAllRead', "true");
})
const ReadingState = localStorage.getItem('infoReadAllRead');
if (ReadingState === "true") {setAllOk();}

@ -24,13 +24,15 @@
<h3 id="HeaderText" class="pt-2" style="display: none;"><b>PIO</b><b style="color: rgb(120,170,86);">MINT</b></h3> <h3 id="HeaderText" class="pt-2" style="display: none;"><b>PIO</b><b style="color: rgb(120,170,86);">MINT</b></h3>
<span class="col-3 d-none" id="settings_icon"><img src="{% static 'app/images/settings.png' %}" alt="Settings" class="img-fluid" id="image" style="width: 40%; opacity: 0.75; padding-top: 0.65rem;"></span> <div class="col-3"></div>
<!-- <span class="col-3 d-none" id="settings_icon"><img src="{% static 'app/images/settings.png' %}" alt="Settings" class="img-fluid" id="image" style="width: 40%; opacity: 0.75; padding-top: 0.65rem;"></span>
<span class="col-3 d-none" id="settings_close_icon"><img src="{% static 'app/images/close.png' %}" alt="SettingsClose" class="img-fluid" id="image" style="width: 40%; opacity: 0.75; padding-top: 0.65rem;"></span> <span class="col-3 d-none" id="settings_close_icon"><img src="{% static 'app/images/close.png' %}" alt="SettingsClose" class="img-fluid" id="image" style="width: 40%; opacity: 0.75; padding-top: 0.65rem;"></span>
-->
</div> </div>
<div class="settings text-left"> <div class="settings text-left">
<div class="settings-card container"> <div class="settings-card container">
<h5 class="pt-3">Allgemein</h5> <!-- <h5 class="pt-3">Allgemein</h5>
<ul class="list-group" style="color: black;"> <ul class="list-group" style="color: black;">
<li class="list-group-item d-flex justify-content-between align-items-center"> <li class="list-group-item d-flex justify-content-between align-items-center">
LDC-Tätigkeiten LDC-Tätigkeiten
@ -40,8 +42,8 @@
Dauer-Hippi Dauer-Hippi
<button class="badge btn btn-secondary">Off</button> <button class="badge btn btn-secondary">Off</button>
</li> </li>
</ul> </ul> -->
<h5 class="pt-4">Account</h5> <!--<h5 class="pt-4">Account</h5>
<ul class="list-group" style="color: black;"> <ul class="list-group" style="color: black;">
<li class="list-group-item d-flex justify-content-between align-items-center"> <li class="list-group-item d-flex justify-content-between align-items-center">
Username: <b>maxmüller</b> Username: <b>maxmüller</b>
@ -51,17 +53,17 @@
Passwort Passwort
<button class="badge btn btn-primary">ändern</button> <button class="badge btn btn-primary">ändern</button>
</li> </li>
</ul> </ul> -->
<h5 class="pt-4">Bericht</h5> <h5 class="pt-4">Bericht</h5>
<ul class="list-group" style="color: black;"> <ul class="list-group" style="color: black;">
<li class="list-group-item d-flex justify-content-between align-items-center"> <li class="list-group-item d-flex justify-content-between align-items-center">
Bibelstudien: Bibelstudien:
<button class="badge btn btn-disabled" style="min-width: 50px;">1</button> <button class="badge btn btn-disabled" style="min-width: 50px;">1</button>
</li> </li>
<li class="list-group-item d-flex justify-content-between align-items-center"> <!-- <li class="list-group-item d-flex justify-content-between align-items-center">
Erinnerung: Erinnerung:
<button class="badge btn btn-success">On</button> <button class="badge btn btn-success">On</button>
</li> </li> -->
</ul> </ul>
</div> </div>
</div> </div>

@ -2,6 +2,7 @@
{% load static %} {% load static %}
{% block content %} {% block content %}
<script> <script>
document.getElementById('body').classList.replace('bg-white-color','bg-blue-color'); document.getElementById('body').classList.replace('bg-white-color','bg-blue-color');
document.getElementById('header-color-block').classList.replace('bg-white-color','bg-blue-color'); document.getElementById('header-color-block').classList.replace('bg-white-color','bg-blue-color');
@ -9,27 +10,25 @@
document.getElementById('maincontainer').classList.replace('align-items-center', 'align-items-top') document.getElementById('maincontainer').classList.replace('align-items-center', 'align-items-top')
</script> </script>
<script>
document.addEventListener('DOMContentLoaded', (event) => {
initDB().then(() => {
console.log('IndexedDB erfolgreich initialisiert.');
// Hier kannst du die App weiter initialisieren, z.B. Daten laden oder die UI aufbauen
//loadInitialData();
}).catch((error) => {
console.error('Fehler bei der Initialisierung der IndexedDB:', error);
});
});
</script>
<div class="container" id="welcome_content"> <!-- d-none muss entfernt werden für richtige Funktion --> <div class="container" id="welcome_content"> <!-- d-none muss entfernt werden für richtige Funktion -->
<h1>Wilkommen!</h1> <h1>Wilkommen!</h1>
<p>Schön das du hier bist! <p>
Schön das du hier bist!
<br>Ich wünsche dir viel Freude mit der App. <br>Ich wünsche dir viel Freude mit der App.
<br>Sollten Fragen oder Probleme auftauchen, fühl dich frei in der Community <a href="http://piomint.de/feedback"><u>piomint.de/feedback</u></a> einen Eintrag da zu lassen. <br>Diese ist noch ganz neu und wächst immer weiter!
<br>Ein paar kurze punkte zu dieser App:
<br> <br>
<br><b>Hinweis:</b> <br><b>Hinweis:</b>
<br>Diese App ist für Pioniere optimiert und deshalb für den normalen Dienst oder Hilfspionierdienst nicht so gut geeignet. <br>Diese App ist für Pioniere und soll das Stundenmanagemant vereinfachen.
<br>Eine Ausnahme ist der "Dauer-Hippi" - Dieser ist in den Einstellung auswählbar. <br>Wenn du "Dauer-Hippi" machst kannst du das in den Einstellungen aktivieren.
<br>
<br><b>Verwendung:</b>
<br>Diese Daten liegen erstmal lokal auf deinem Handy. In Zukunft wird es so sein,
<br>das du dir einen Account anlegen kannst und die Daten gesichert werden und du auch über andere Geräte darauf zugreifen kannst.
<br><i style="color: red">Wenn du <u>aktuell</u> die App löscht, sind <u>alle</u> Daten weg!</i>
<br>
<br><b>Datenschutz</b>
<br>Sowohl jetzt, als auch mit einem Account werden keine Personen bezogenen Daten gesammelt oder gesichert.
</p> </p>
<br> <br>
<button class="btn btn-primary" id="allOk">Alles klar</button> <button class="btn btn-primary" id="allOk">Alles klar</button>
@ -39,24 +38,25 @@
<div class="row justify-content-around mt-3" style="width: 100vw; color: black;"> <div class="row justify-content-around mt-3" style="width: 100vw; color: black;">
<div class="col-11" style="height: 5vh; padding: 1rem; border-radius:1rem; box-shadow: 0 0 0.5rem gray"> <div class="col-11" style="height: 5vh; padding: 1rem; border-radius:1rem; box-shadow: 0 0 0.5rem gray">
<div class="row justify-content-between"> <div class="row justify-content-between">
<p class="col-6" style="font-size: 1rem; margin-top: -0.75rem;"><b>Jahr:</b> 450h/600h</p> <p class="col-6" style="font-size: 1rem; margin-top: -0.75rem;"><b>Jahr:</b> <span id="yearHours"></span>h/600h</p>
<p class="offset-1 col-5" style="font-size: 1rem; margin-top: -0.75rem;"><b>Offen:</b> 150h</p> <p class="offset-1 col-5" style="font-size: 1rem; margin-top: -0.75rem;"><b>Offen:</b> <span id="yearRest"></span>h</p>
</div> </div>
<div class="progress" style="height: 5px; width: 100%; border-radius: 2rem; background-color: lightgray; margin-top: -1rem;"> <div class="progress" style="height: 5px; width: 100%; border-radius: 2rem; background-color: lightgray; margin-top: -1rem;">
<div class="progress-bar" role="progressbar" style="background-color:rgb(120,170,86); width: 90%; height: 5px;" aria-valuenow="10" aria-valuemin="0" aria-valuemax="50"></div> <div class="progress-bar" role="progressbar" style="background-color:rgb(120,170,86); width: 0.5%; height: 5px;" aria-valuenow="10" aria-valuemin="0" aria-valuemax="50" id="prBarYear"></div>
</div> </div>
</div> </div>
<div class="col-11 mt-4" style="height: 15vh; padding: 1rem; border-radius:1rem; box-shadow: 0 0 0.5rem gray"> <div class="col-11 mt-4" style="height: 15vh; padding: 1rem; border-radius:1rem; box-shadow: 0 0 0.5rem gray">
<div class="row justify-content-between"> <div class="row justify-content-between">
<p class="col-7" style="font-size: 1.25rem;"><b>Monat:</b> 25h/50h</p> <p class="col-7" style="font-size: 1.25rem;"><b>Monat:</b> <span id="monthHours"></span>h/50h</p>
<p class="col-5" style="font-size: 1.25rem;"><b>Offen:</b> 25h</p> <p class="col-5" style="font-size: 1.25rem;"><b>Offen:</b> <span id="monthRest"></span>h</p>
</div> </div>
<div class="progress" style="height: 5px; width: 100%; border-radius: 2rem; background-color: lightgray; margin-top: -0.75rem"> <div class="progress" style="height: 5px; width: 100%; border-radius: 2rem; background-color: lightgray; margin-top: -0.75rem">
<div class="progress-bar" role="progressbar" style="background-color:rgb(120,170,86); width: 50%; height: 5px;" aria-valuenow="10" aria-valuemin="0" aria-valuemax="50"></div> <div class="progress-bar" role="progressbar" style="background-color:rgb(120,170,86); height: 5px; width: 1%;" aria-valuenow="10" aria-valuemin="0" aria-valuemax="50" id="prBarMonth"></div>
</div> </div>
<div class="row justify-content-center"> <div class="row justify-content-around">
<button class="col-3 mt-3 badge badge-primary" style="height: 25px; border: none;">Dienst: 10h</button> <button class="col-3 mt-3 badge badge-primary" style="height: 25px; border: none;">Dienst: <span id="monthHourService"></span>h</button>
<button class="offset-1 col-3 mt-3 badge badge-primary" style="height: 25px; border: none;">LDC: 10h</button> <button class="col-3 mt-3 badge badge-primary" style="height: 25px; border: none;">LDC: <span id="monthHourLDC"></span>h</button>
<button class="col-3 mt-3 badge badge-primary" style="height: 25px; border: none;">Übrig: <span id="monthHourOther"></span>h</button>
</div> </div>
</div> </div>
</div> </div>
@ -64,7 +64,7 @@
<div class="col-11" style="height: 15vh; padding: 1rem; border-radius:1rem; box-shadow: 0 0 0.5rem gray"> <div class="col-11" style="height: 15vh; padding: 1rem; border-radius:1rem; box-shadow: 0 0 0.5rem gray">
<p style="font-size: 1.2rem;"><b>Timer</b></p> <p style="font-size: 1.2rem;"><b>Timer</b></p>
<div class="row justify-content-between" style="margin-top: -1rem;"> <div class="row justify-content-between" style="margin-top: -1rem;">
<p class="col-5"><b id="timerDisplay" style="font-size: 2.5rem;">00:00</b><i id="secondsDisplay" style="font-size: 1rem;"></i></p> <p class="col-5"><b id="timerDisplay" style="font-size: 2.5rem;">00:00</b><i id="secondsDisplay" style="font-size: 1rem;">:00</i></p>
<div class="col-7 row justify-content-center"> <div class="col-7 row justify-content-center">
<img id="startTimer" src="{% static 'app/images/play.png' %}" alt="play" class="img-fluid col-6" style="height: 55px;"> <img id="startTimer" src="{% static 'app/images/play.png' %}" alt="play" class="img-fluid col-6" style="height: 55px;">
<img id="pauseTimer" src="{% static 'app/images/pause.png' %}" alt="play" class="img-fluid col-6 d-none" style="height: 55px;"> <img id="pauseTimer" src="{% static 'app/images/pause.png' %}" alt="play" class="img-fluid col-6 d-none" style="height: 55px;">
@ -76,34 +76,51 @@
</div> </div>
<div class="row justify-content-around" style="width: 95vw; color: black; padding-top: 2rem;"></div> <div class="row justify-content-around" style="width: 95vw; color: black; padding-top: 2rem;"></div>
<div class="col-12" style="height: 40vh; padding: 0rem 1rem 1rem 1rem; border-radius:1rem; box-shadow: 0 0 0.5rem gray; overflow-y: auto;"> <div class="col-12" style="height: 40vh; padding: 0rem 1rem 1rem 1rem; border-radius:1rem; box-shadow: 0 0 0.5rem gray; overflow-y: auto;">
<div class="row justify-content-between align-items-center m-0" style="width: 100%;position: sticky; top: 0; background-color: white; padding-top: 1rem;"> <div class="row justify-content-between align-items-center m-0" style="width: 100%;position: sticky; top: 0; background-color: white; padding-top: 1rem; z-index: 100;">
<p class="col-5" style="font-size: 1.2rem; margin: 0 1rem 0 -1rem;" ><b>Aktivitäten</b></p> <p class="col-5" style="font-size: 1.2rem; margin: 0 1rem 0 -1rem;" ><b>Aktivitäten</b></p>
<!-- <span class="col-2" style="margin-left: 32%; padding: 0;"><img id="resetTimer" src="{% static 'app/images/addcircle.png' %}" alt="add" class="img-fluid" style="height: 35px"></span> --> <!-- <span class="col-2" style="margin-left: 32%; padding: 0;"><img id="resetTimer" src="{% static 'app/images/addcircle.png' %}" alt="add" class="img-fluid" style="height: 35px"></span> -->
<button type="button" class="offset-2 col-2 btn btn-light" data-bs-toggle="modal" data-bs-target="#newEntryModal"><img id="resetTimer" src="{% static 'app/images/addcircle.png' %}" alt="add" class="img-fluid"></button> <button type="button" class="offset-2 col-2 btn btn-light" data-bs-toggle="modal" data-bs-target="#newEntryModal"><img id="resetTimer" src="{% static 'app/images/addcircle.png' %}" alt="add" class="img-fluid"></button>
<button type="button" class="offset-1 col-2 btn btn-light"><img id="resetTimer" src="{% static 'app/images/open.png' %}" alt="open" class="img-fluid"></button> <button type="button" class="offset-1 col-2 btn btn-light d-none"><img id="resetTimer" src="{% static 'app/images/open.png' %}" alt="open" class="img-fluid"></button>
</div> </div>
<table class="table table-striped"> <table class="table table-striped" style="z-index: 1;">
<thead style="position: sticky; top: 3.5rem; background-color: white;"> <tbody id="entriesTableBody" style="overflow-y: auto; max-height: 70%;"></tbody>
<tr>
<th scope="col">Dauer</th>
<th scope="col">Datum</th>
<th scope="col">Beschreibung</th>
</tr>
</thead>
<tbody id="entriesTableBody" style="overflow-y: auto; max-height: 70%;">
</tbody>
</table> </table>
</div> </div>
</div> </div>
</div> </div>
<!-- Modal --> <style>
table {
width: 100%;
}
.table td {
text-overflow:initial;
max-width: 100px;
}
tbody tr {
position: relative;
transition: transform 0.3s ease-in-out;
}
tbody tr.swipe-left {
transform: translateX(0%);
}
tbody tr.swipe-left .delete-btn {
display: block;
}
</style>
<!-- NEUER EINTRAGModal -->
<div class="modal fade" id="newEntryModal" tabindex="-1" aria-labelledby="newEntryModalLabel" aria-hidden="true"> <div class="modal fade" id="newEntryModal" tabindex="-1" aria-labelledby="newEntryModalLabel" aria-hidden="true">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title" id="newEntryModalLabel">Eingabeformular</h5> <h5 class="modal-title" id="newEntryModalLabel">Neuer Eintrag</h5>
<button type="button" class="btn btn-sm btn-danger" data-bs-dismiss="modal" aria-label="Schließen">X</button> <button type="button" class="btn btn-sm btn-danger" data-bs-dismiss="modal" aria-label="Schließen">X</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
@ -118,7 +135,7 @@
<div class="input-group-append"> <div class="input-group-append">
<span class="input-group-text">h</span> <span class="input-group-text">h</span>
</div> </div>
<input type="number" class="form-control" id="minuten" placeholder="00" min="0" max="59" maxlength="2" required> <input type="number" class="form-control" id="minuten" placeholder="00" min="0" max="59" maxlength="2" value="0" required>
<div class="input-group-append"> <div class="input-group-append">
<span class="input-group-text">min</span> <span class="input-group-text">min</span>
</div> </div>
@ -152,7 +169,7 @@
<!-- <!--
<label for="sonstigesInput">Beschreibung:</label> <label for="sonstigesInput">Beschreibung:</label>
--> -->
<input type="text" class="form-control" id="sonstigesInput" placeholder="Beschreibung"> <input type="text" class="form-control" id="sonstigesInput" placeholder="max. 10 Zeichen" maxlength="10">
</div> </div>
<button type="button" class="btn btn-light disabled" id="newEntrySubmitButton" data-bs-dismiss="modal">Hinzufügen</button> <button type="button" class="btn btn-light disabled" id="newEntrySubmitButton" data-bs-dismiss="modal">Hinzufügen</button>
</form> </form>
@ -161,213 +178,81 @@
</div> </div>
</div> </div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
<script>
function formatDuration(minutes) {
const hours = Math.floor(minutes / 60); // Ganze Stunden berechnen
const mins = minutes % 60; // Verbleibende Minuten berechnen
return `${String(hours).padStart(2, '0')}:${String(mins).padStart(2, '0')}`; // Stunden und Minuten formatieren
}
function formatDate(dateString) {
const date = new Date(dateString); // Konvertiere in ein Date-Objekt
const day = String(date.getDate()).padStart(2, '0'); // Tag
const month = String(date.getMonth() + 1).padStart(2, '0'); // Monat (getMonth() ist 0-basiert)
const year = String(date.getFullYear()).slice(-2); // Die letzten 2 Ziffern des Jahres
return `${day}.${month}.${year}`; // Format tt.mm.yy
}
function fillTableWithEntries(entries) {
const tableBody = document.getElementById('entriesTableBody');
// Zuerst den Inhalt der Tabelle löschen (falls schon Daten da sind)
tableBody.innerHTML = '';
// Iteriere durch die Einträge und füge Zeilen hinzu
entries.forEach(entry => {
const row = document.createElement('tr');
// Spalte für die Dauer (duration)
const durationCell = document.createElement('td');
durationCell.textContent = formatDuration(entry.duration); // Dauer im hh:mm-Format
row.appendChild(durationCell);
// Spalte für das Datum (date)
const dateCell = document.createElement('td');
const entryDate = new Date(entry.date); // Konvertiere in ein Date-Objekt
dateCell.textContent = formatDate(entry.date); // Datum im tt.mm.yy-Format
row.appendChild(dateCell);
// Spalte für den Typ (type) - wenn 3, dann zeige "Beschreibung" an
const typeCell = document.createElement('td');
if (entry.type === 3) {
typeCell.textContent = 'Beschreibung'; // Bei Type 3 zeige "Beschreibung" an
} else if (entry.type === 2) {
typeCell.textContent = 'LDC'; // Ansonsten zeige den Type-Wert
} else if (entry.type === 1) {
typeCell.textContent = 'Dienst'; // Ansonsten zeige den Type-Wert
}
row.appendChild(typeCell);
// Füge die erstellte Zeile dem Tabellenkörper hinzu <!-- EINTRAG BEARBEITEN -->
tableBody.appendChild(row); <div class="modal fade" id="editEntryModel" tabindex="-1" aria-labelledby="editEntryModel" aria-hidden="true">
}); <div class="modal-dialog">
} <div class="modal-content">
async function initAndTestFilter() { <div class="modal-header">
try { <h5 class="modal-title" id="newEntryModalLabel">Eintrag bearbeiten</h5>
// IndexedDB initialisieren <button type="button" class="btn btn-sm btn-danger" data-bs-dismiss="modal" aria-label="Schließen">X</button>
await initDB(); </div>
console.log('IndexedDB erfolgreich initialisiert.'); <div class="modal-body">
<form method="POST" action="">
// Filterfunktion aufrufen {% csrf_token %}
const filteredEntries = await filterEntriesByMonthYear(9, 2024); <input type="text" name="editEntryID" id="editEntryID" class="d-none">
fillTableWithEntries(filteredEntries) <!-- Dauer in Stunden und Minuten -->
console.log('Gefilterte Einträge für September 2024:', filteredEntries); <div class="form-row">
} catch (error) { <div class="form-group col-7">
console.error('Fehler bei der Initialisierung oder Filterung:', error); <label for="stunden"><b>Dauer</b></label>
} <div class="input-group">
} <input type="number" class="form-control" id="editStunden" placeholder="00" min="0" max="99" maxlength="2" required>
<div class="input-group-append">
// Initialisierungsfunktion nach dem DOM laden aufrufen <span class="input-group-text">h</span>
document.addEventListener('DOMContentLoaded', (event) => { </div>
initAndTestFilter(); <input type="number" class="form-control" id="editMinuten" placeholder="00" min="0" max="59" maxlength="2" value="0" required>
}); <div class="input-group-append">
<span class="input-group-text">min</span>
// Absende Formular Verwalten </div>
const hours = document.getElementById('stunden'); </div>
const mins = document.getElementById('minuten'); </div>
const NewEntryButton = document.getElementById('newEntrySubmitButton') </div>
var allowToSend = false;
function checkInput() {
if (hours.value && mins.value) {
if (!allowToSend) {
allowToSend = true;
NewEntryButton.classList.remove('disabled');
NewEntryButton.classList.replace('btn-light', 'btn-primary');
}
} else {
if (allowToSend) {
allowToSend = false;
NewEntryButton.classList.add('disabled');
NewEntryButton.classList.replace('btn-primary', 'btn-light');
}
}
if(sonstigesCheck.checked){
if(sonstigesInput.value) {
if (!allowToSend) {
allowToSend = true;
NewEntryButton.classList.remove('disabled');
NewEntryButton.classList.replace('btn-light', 'btn-primary');
}
} else {
if (allowToSend) {
allowToSend = false;
NewEntryButton.classList.add('disabled');
NewEntryButton.classList.replace('btn-primary', 'btn-light');
}
}
}
}
// Änderungen überwachen damit die das Formular nicht zu früh abgesendet wird
hours.addEventListener('input', () => {
checkInput();
})
mins.addEventListener('input', () => {
checkInput();
})
document.getElementById('sonstigesInput').addEventListener('input', () => {
checkInput();
})
// Einstellungen wenn Neuer Eintrag erstellt wird
NewEntryButton.addEventListener('click', () => {
if (allowToSend === true) {
var type = 1
// Abfragen der Checkboxen
const ldcCheck = document.getElementById('ldcCheck').checked
if (ldcCheck) {
type = 2
document.getElementById('ldcCheck').checked = false
} else if (document.getElementById('sonstigesCheck').checked) {
type = 3;
document.getElementById('sonstigesCheck').checked = false;
sonstigesText.style.display = 'none';
}
// Berechnen der Duration <!-- Datum -->
const duration = (parseInt(hours.value)*60) + parseInt(mins.value) <div class="form-group">
<label for="datum"><b>Datum</b></label>
<input type="date" class="form-control" id="editDatum" required>
</div>
const newEntryData = { <!-- Auswahl LDC oder Sonstiges (Checkboxen) -->
date: document.getElementById('datum').value, <div class="form-group">
duration: duration, <label for="optionen"><b>Optionen:</b></label>
type: type, <div>
status: 1, <div class="form-check form-check-inline">
sondertext: document.getElementById('sonstigesInput').value, <input class="form-check-input" type="checkbox" id="editldcCheck" name="optionen" value="LDC">
} <label class="form-check-label" for="ldcCheck">LDC</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="editsonstigesCheck" name="optionen" value="Sonstiges">
<label class="form-check-label" for="sonstigesCheck">Sonstiges</label>
</div>
</div>
</div>
addEntry(newEntryData).then((id) => { <!-- Textfeld für Sonstiges (versteckt, wenn Sonstiges nicht gewählt ist) -->
console.log('Eintrag hinzugefügt mit ID:', id); <div class="form-group" id="edit-sonstiges-text" style="display:none;">
}); <!--
<label for="sonstigesInput">Beschreibung:</label>
-->
<input type="text" class="form-control" id="editsonstigesInput" placeholder="max. 10 Zeichen" maxlength="10">
</div>
<button type="button" class="btn btn-primary" id="editEntrySubmitButton" data-bs-dismiss="modal">Speichern</button>
<button type="button" class="btn btn-danger" id="DeleteEntryButton" data-bs-dismiss="modal">Löschen</button>
</form>
</div>
</div>
</div>
</div>
hours.value = null <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
mins.value = null
document.getElementById('sonstigesInput').value = null
checkInput()
}
})
<script>
// Setze das heutige Datum als Standardwert // Setze das heutige Datum als Standardwert
document.getElementById('datum').value = new Date().toISOString().split('T')[0]; document.getElementById('datum').value = new Date().toISOString().split('T')[0];
// Checkboxen-Verhalten: Nur eine Checkbox kann ausgewählt werden
var ldcCheck = document.getElementById('ldcCheck');
var sonstigesCheck = document.getElementById('sonstigesCheck');
var sonstigesText = document.getElementById('sonstiges-text');
var sonstigesInput = document.getElementById('sonstigesInput');
ldcCheck.addEventListener('change', function() {
if (ldcCheck.checked) {
sonstigesCheck.checked = false;
sonstigesText.style.display = 'none';
sonstigesInput.removeAttribute('required'); // Entferne required, wenn "Sonstiges" abgewählt ist
}
});
sonstigesCheck.addEventListener('change', function() {
checkInput();
if (sonstigesCheck.checked) {
ldcCheck.checked = false;
sonstigesText.style.display = 'block';
sonstigesInput.setAttribute('required', 'required'); // Setze required, wenn "Sonstiges" ausgewählt ist
} else {
sonstigesText.style.display = 'none';
sonstigesInput.removeAttribute('required'); // Entferne required, wenn "Sonstiges" abgewählt ist
}
});
/* ALLES RUND UM DIE WILLKOMMENSMELDUNG */
function setAllOk() {
document.getElementById('welcome_content').style.display = 'none';
document.getElementById('dashboard').classList.remove('d-none');
document.getElementById('refresh_icon').classList.remove('d-none')
document.getElementById('settings_icon').classList.remove('d-none')
}
document.getElementById("allOk").addEventListener('click', function(){
setAllOk();
localStorage.setItem('infoReadAllRead', "true");
})
const ReadingState = localStorage.getItem('infoReadAllRead');
if (ReadingState === "true") {setAllOk();}
/* Verarbeitung der Einstellungen */ /* Verarbeitung der Einstellungen */
const settingsIcon = document.getElementById('settings_icon') const settingsIcon = document.getElementById('settings_icon')
@ -389,4 +274,6 @@
}) })
</script> </script>
<script src="{% static 'app/js/home.js' %}"></script>
<script src="{% static 'app/js/welcomeControl.js' %}"></script>
{% endblock %} {% endblock %}

Loading…
Cancel
Save

Powered by TurnKey Linux.