You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
piomint/app/static/app/js/home01.js

839 lines
34 KiB

// Absende Formular Verwalten
const hours = document.getElementById('stunden');
const mins = document.getElementById('minuten');
const NewEntryButton = document.getElementById('newEntrySubmitButton')
const SETStudySaveButton = document.getElementById('SETStudySaveButton')
const SETMonthGoalSaveButton = document.getElementById('SETMonthGoalSaveButton')
const SETLdcNameSaveButton = document.getElementById('SETLdcNameSaveButton')
const rule55hCheck = document.getElementById('rule55hCheck')
const openViewOfEntry = document.getElementById('openViewOfEntry')
const openViewOfEntryIcon = document.getElementById('openViewOfEntryIcon')
const ActivitysTable = document.getElementById('ActivitysTable')
const timerCard = document.getElementById('timerCard')
const toggleSortOptions = document.getElementById('toggleSortOptions')
const sortOptionsRow = document.getElementById('sortOptionsRow')
const sortFieldButton = document.getElementById('sortFieldButton')
const sortFieldLabel = document.getElementById('sortFieldLabel')
const sortFieldMenu = document.getElementById('sortFieldMenu')
const sortFieldOptions = document.querySelectorAll('.sortFieldOption')
const sortDirectionToggle = document.getElementById('sortDirectionToggle')
const sortDirectionIcon = document.getElementById('sortDirectionIcon')
const shareIcon = document.getElementById('share_icon')
const shareReportModalEl = document.getElementById('shareReportModal')
const shareReportStatus = document.getElementById('shareReportStatus')
const shareReportPreview = document.getElementById('shareReportPreview')
var allowToSend = false;
const monate = ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"];
const currentDate = new Date();
// 55h-Regel (Jahresansicht): wird beim Start aus den Settings geladen und beim Umschalten
// live aktualisiert, damit getActualDataAndFillView() sie synchron verwenden kann.
var rule55Active = false;
// Individuell vergebbarer Name für "LDC" (SettingsID 4), überall im UI verwendet statt fest "LDC".
var ldcLabel = 'LDC';
// Sortierung der Aktivitäten-Tabelle: wird aus dem Cache (localStorage) geladen/gespeichert.
var sortField = 'date';
var sortDirection = 'asc';
// Ob die Filter/Sortier-Optionen gerade sichtbar sind (wird ebenfalls im Cache gespeichert).
var isFilterVisible = true;
// Ob die Aktivitäten-Tabelle gerade maximiert ist (Timer-Karte ist dann ausgeblendet).
var isTableMaximized = false;
// Einträge des gerade angezeigten Monats, für den WhatsApp-Bericht (share_icon) wiederverwendet.
var currentMonthEntries = [];
//
// Trigger
//
// Wenn das Dokument komplett geladen ist
document.addEventListener('DOMContentLoaded', (event) => {
initDB().then(async () => {
console.log('IndexedDB erfolgreich initialisiert.');
// Hier kannst du die App weiter initialisieren, z.B. Daten laden oder die UI aufbauen
// 55h-Regel Einstellung laden, bevor die erste Jahresansicht berechnet wird
await loadRule55Setting();
// LDC-Bezeichnung laden, bevor die Tabelle erstmalig gefüllt wird
await loadLdcLabel();
// Gespeicherte Sortierung der Aktivitäten-Tabelle aus dem Cache laden
loadSortPreference();
// Gespeicherte Sichtbarkeit der Filter/Sortier-Optionen aus dem Cache laden
loadFilterVisibility();
// Bildschirm mit dem Inhalt für den aktuellen Tag füllen
getActualDataAndFillView();
//loadInitialData();
}).catch((error) => {
console.error('Fehler bei der Initialisierung der IndexedDB:', error);
});
});
// Behebt die Bootstrap-Konsolenwarnung "Blocked aria-hidden on an element because its
// descendant retained focus": beim Schließen eines Modals (z.B. per "X"-Button) setzt
// Bootstrap aria-hidden="true", obwohl der geklickte Button noch fokussiert ist. Fix: Fokus
// vor dem Ausblenden gezielt vom Modal wegnehmen. Gilt für alle Modals der Seite.
document.querySelectorAll('.modal').forEach(modalEl => {
modalEl.addEventListener('hide.bs.modal', () => {
if (document.activeElement && modalEl.contains(document.activeElement)) {
document.activeElement.blur()
}
})
})
// Lädt die 55h-Regel Einstellung (SettingsID 3) aus der DB, setzt rule55Active
// und synchronisiert die Checkbox sowie den Badge in der Jahres-Card.
async function loadRule55Setting() {
const result = await getAllEntries('settings')
const setting = result.find(element => element.SettingsID === 3)
rule55Active = (setting == undefined) ? false : !!parseInt(setting.SettingsValue)
rule55hCheck.checked = rule55Active
updateRule55Badge()
}
// Zeigt/versteckt den "55h-Regel aktiv"-Hinweis an der Jahres-Card
function updateRule55Badge() {
document.getElementById('rule55Badge').classList.toggle('d-none', !rule55Active)
}
// Einstellungen wenn die 55h-Regel umgeschaltet wird
rule55hCheck.addEventListener('change', () => {
rule55Active = rule55hCheck.checked
updateRule55Badge()
const Rule55SettingsData = {
SettingsID: 3,
SettingsValue: rule55Active ? 1 : 0,
}
getAllEntries('settings')
.then(function(result) {
const SETDBData = result.find(element => element.SettingsID === 3)
if (SETDBData != undefined) {
updateEntry(SETDBData.id, 'settings', Rule55SettingsData)
} else {
addEntry(Rule55SettingsData, 'settings')
}
// Jahresansicht mit/ohne Deckel neu berechnen
getActualDataAndFillView(cursorMonth, cursorYear)
})
})
//
// TABELLE MAXIMIEREN
//
// Aktivitäten-Tabelle vergrößern/verkleinern: Timer-Karte klappt beim Maximieren
// animiert weg, um Platz zu schaffen; die Tabelle wächst gleichzeitig.
openViewOfEntry.addEventListener('click', () => {
isTableMaximized = !isTableMaximized
ActivitysTable.classList.toggle('ActivitysTableMaximized', isTableMaximized)
timerCard.classList.toggle('timerCollapsed', isTableMaximized)
openViewOfEntryIcon.src = isTableMaximized
? openViewOfEntryIcon.src.replace('open.png', 'close.png')
: openViewOfEntryIcon.src.replace('close.png', 'open.png')
openViewOfEntry.title = isTableMaximized ? 'Tabelle minimieren' : 'Tabelle maximieren'
})
//
// SORTIERUNG DER AKTIVITÄTEN-TABELLE
//
// Lädt die gespeicherte Sortierung aus dem Cache (localStorage) und synchronisiert die Steuerelemente
function loadSortPreference() {
try {
const saved = JSON.parse(localStorage.getItem('piomintTableSort'))
if (saved && saved.field) {
sortField = saved.field
sortDirection = (saved.direction === 'desc') ? 'desc' : 'asc'
}
} catch (error) {
console.error('Sortierung konnte nicht aus dem Cache geladen werden:', error)
}
const selectedOption = Array.from(sortFieldOptions).find(option => option.dataset.value === sortField)
sortFieldLabel.innerText = selectedOption ? selectedOption.dataset.label : 'Datum'
sortDirectionIcon.innerText = (sortDirection === 'asc') ? 'A → Z' : 'Z → A'
}
// Speichert die aktuelle Sortierung im Cache (localStorage)
function saveSortPreference() {
try {
localStorage.setItem('piomintTableSort', JSON.stringify({ field: sortField, direction: sortDirection }))
} catch (error) {
console.error('Sortierung konnte nicht im Cache gespeichert werden:', error)
}
}
// Eigener Dropdown für die Sortier-Eigenschaft (statt <select>) öffnen/schließen
sortFieldButton.addEventListener('click', (event) => {
event.stopPropagation()
sortFieldMenu.classList.toggle('d-none')
})
// Außerhalb des Menüs klicken schließt es wieder
document.addEventListener('click', (event) => {
if (!sortFieldMenu.classList.contains('d-none') && !sortFieldMenu.contains(event.target) && event.target !== sortFieldButton) {
sortFieldMenu.classList.add('d-none')
}
})
sortFieldOptions.forEach(option => {
option.addEventListener('click', () => {
sortField = option.dataset.value
sortFieldLabel.innerText = option.dataset.label
sortFieldMenu.classList.add('d-none')
saveSortPreference()
getActualDataAndFillView(cursorMonth, cursorYear)
})
})
sortDirectionToggle.addEventListener('click', () => {
sortDirection = (sortDirection === 'asc') ? 'desc' : 'asc'
sortDirectionIcon.innerText = (sortDirection === 'asc') ? 'A → Z' : 'Z → A'
saveSortPreference()
getActualDataAndFillView(cursorMonth, cursorYear)
})
//
// FILTER/SORTIER-OPTIONEN EIN-/AUSBLENDEN
//
// Lädt die gespeicherte Sichtbarkeit der Filter-Optionen aus dem Cache (localStorage)
function loadFilterVisibility() {
try {
const saved = localStorage.getItem('piomintFilterVisible')
if (saved !== null) {
isFilterVisible = (saved === 'true')
}
} catch (error) {
console.error('Filter-Sichtbarkeit konnte nicht aus dem Cache geladen werden:', error)
}
sortOptionsRow.classList.toggle('sortOptionsCollapsed', !isFilterVisible)
}
toggleSortOptions.addEventListener('click', () => {
isFilterVisible = !isFilterVisible
sortOptionsRow.classList.toggle('sortOptionsCollapsed', !isFilterVisible)
// Offenes Dropdown-Menü beim Einklappen der Filterzeile mit schließen
if (!isFilterVisible) {
sortFieldMenu.classList.add('d-none')
}
try {
localStorage.setItem('piomintFilterVisible', isFilterVisible)
} catch (error) {
console.error('Filter-Sichtbarkeit konnte nicht im Cache gespeichert werden:', 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();
})
// Button-Status beim Öffnen des Modals einmal anhand der Standardwerte (z.B. Minuten = 0) setzen,
// da sonst ohne ein tatsächliches 'input'-Event der Button trotz gültiger Vorbelegung deaktiviert bleibt
document.getElementById('newEntryModal').addEventListener('show.bs.modal', () => {
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 (Stunden sind optional -> ohne Eingabe wird 0 gespeichert)
const duration = ((parseInt(hours.value) || 0)*60) + parseInt(mins.value)
const newEntryData = {
date: document.getElementById('datum').value,
duration: duration,
type: type,
status: 1,
sondertext: document.getElementById('sonstigesInput').value,
}
addEntry(newEntryData, 'hours').then((id) => {
// console.log('Eintrag hinzugefügt mit ID:', id);
location.reload()
});
hours.value = null
mins.value = null
document.getElementById('sonstigesInput').value = null
checkInput()
}
})
// SETTINGS ACTIONS
SETStudySaveButton.addEventListener('click', () => {
var actualSettings = 0
getAllEntries('settings')
.then(function(result) {
const SETDBData = result.find(element => element.SettingsID === 1)
actualSettingsEntryID = SETDBData ? SETDBData.id : undefined;
actualSettings = SETDBData ? SETDBData.SettingsValue : undefined;
// AKTUELLE DATEN AUS FELD ÜBERNHEMEN
var ActInput = document.getElementById('studysinput').value
const StudySettingsData = {
SettingsID: 1,
SettingsValue: parseInt(ActInput),
}
// ÜBERPRÜFEN OB EIN EINTRAG MTI DER SETTINGS ID VORHANDEN IST - WENN JA DANN UPDATE WENN NEIN DANN NEUEN ERSTELLEN
if ( actualSettings != undefined ) {
updateEntry(actualSettingsEntryID, 'settings', StudySettingsData)
} else {
addEntry(StudySettingsData, 'settings')
}
})
SETStudySaveButton.classList.add('d-none')
})
SETMonthGoalSaveButton.addEventListener('click', () => {
getAllEntries('settings')
.then(function(result){
const SETDBData = result.find(element => element.SettingsID === 2)
actualSettingsEntryID = SETDBData ? SETDBData.id : undefined;
actualSettings = SETDBData ? SETDBData.SettingsValue : undefined;
// AKTUELLE DATEN AUS FELD ÜBERNHEMEN
var ActInput = document.getElementById('MonthGoalInput').value
const StudySettingsData = {
SettingsID: 2,
SettingsValue: parseInt(ActInput),
}
// ÜBERPRÜFEN OB EIN EINTRAG MTI DER SETTINGS ID VORHANDEN IST - WENN JA DANN UPDATE WENN NEIN DANN NEUEN ERSTELLEN
if ( actualSettings != undefined ) {
updateEntry(actualSettingsEntryID, 'settings', StudySettingsData)
} else {
addEntry(StudySettingsData, 'settings')
}
// UPDATE DER MONATSANSICHT
// Aktueller Monatsstand an Stunden
const GesamtStundenMonat = parseInt(document.getElementById('MonthSumHours').value)
document.getElementById('monthHours').innerText = GesamtStundenMonat + "/" + parseInt(ActInput)
document.getElementById('prBarMonth').style.width = `${(100/parseInt(ActInput))*parseInt(GesamtStundenMonat)}%`
// Aktueller Rest an Stunden
const rest = parseInt(ActInput) - parseInt(GesamtStundenMonat)
if (rest > 0) {
document.getElementById('monthRest').innerText = rest
} else {
document.getElementById('monthRest').innerText = 0
}
})
SETMonthGoalSaveButton.classList.add('d-none')
})
// Lädt die individuelle LDC-Bezeichnung (SettingsID 4) aus der DB, setzt ldcLabel,
// füllt das Einstellungen-Feld vor und wendet den Namen überall im UI an.
async function loadLdcLabel() {
const result = await getAllEntries('settings')
const setting = result.find(element => element.SettingsID === 4)
ldcLabel = (setting == undefined || !setting.SettingsValue) ? 'LDC' : setting.SettingsValue
document.getElementById('ldcNameInput').value = ldcLabel
applyLdcLabel()
}
// Setzt die aktuelle LDC-Bezeichnung überall dort, wo sie im UI (außerhalb der Tabelle) auftaucht.
// Die Tabelle selbst bekommt den Namen bei jedem Render über fillTableWithEntries(...).
function applyLdcLabel() {
document.getElementById('ldcCheckLabel').innerText = ldcLabel
document.getElementById('editldcCheckLabel').innerText = ldcLabel
document.getElementById('monthHourLDCLabel').innerText = ldcLabel
}
SETLdcNameSaveButton.addEventListener('click', () => {
getAllEntries('settings')
.then(function(result) {
const SETDBData = result.find(element => element.SettingsID === 4)
actualSettingsEntryID = SETDBData ? SETDBData.id : undefined;
actualSettings = SETDBData ? SETDBData.SettingsValue : undefined;
// AKTUELLE DATEN AUS FELD ÜBERNHEMEN - bei leerem Feld auf "LDC" zurückfallen
var ActInput = document.getElementById('ldcNameInput').value.trim() || 'LDC'
document.getElementById('ldcNameInput').value = ActInput
const LdcNameSettingsData = {
SettingsID: 4,
SettingsValue: ActInput,
}
// ÜBERPRÜFEN OB EIN EINTRAG MTI DER SETTINGS ID VORHANDEN IST - WENN JA DANN UPDATE WENN NEIN DANN NEUEN ERSTELLEN
if ( actualSettings != undefined ) {
updateEntry(actualSettingsEntryID, 'settings', LdcNameSettingsData)
} else {
addEntry(LdcNameSettingsData, 'settings')
}
ldcLabel = ActInput
applyLdcLabel()
// Tabelle neu füllen, damit die Typ-Spalte den neuen Namen sofort übernimmt
getActualDataAndFillView(cursorMonth, cursorYear)
})
SETLdcNameSaveButton.classList.add('d-none')
})
//
// BERICHT FÜR WHATSAPP TEILEN
//
// Baut den vorformatierten Bericht für den gerade angezeigten Monat (WhatsApp-Formatierung: *fett*)
function buildMonthReportText() {
const monthLabel = `${monate[cursorMonth]} ${cursorYear}`
const dienstHours = document.getElementById('monthHourService').innerText
const bibelstudien = document.getElementById('studysinput').value
const ldcHours = document.getElementById('monthHourLDC').innerText
// Sonstige Einträge nach ihrem individuellen Bemerkungstext gruppieren und Stunden je Gruppe summieren
const sonstigeGroups = {}
currentMonthEntries
.filter(entry => entry.type === 3)
.forEach(entry => {
const label = entry.sondertext || 'Sonstiges'
sonstigeGroups[label] = (sonstigeGroups[label] || 0) + entry.duration
})
var message = `Bericht: *${monthLabel}*\n`
message += `Dienst: ${dienstHours}h\n`
message += `Bibelstudien: ${bibelstudien}\n`
message += `Bemerkungen:\n`
message += `${ldcLabel}: ${ldcHours}h`
Object.keys(sonstigeGroups).forEach(label => {
message += `\n${label}: ${formatDuration(sonstigeGroups[label], true)}h`
})
return message
}
// Kopiert Text in die Zwischenablage - mit Fallback für Umgebungen ohne Clipboard-API
async function copyTextToClipboard(text) {
if (navigator.clipboard && navigator.clipboard.writeText) {
await navigator.clipboard.writeText(text)
return
}
const textarea = document.createElement('textarea')
textarea.value = text
textarea.style.position = 'fixed'
textarea.style.opacity = '0'
document.body.appendChild(textarea)
textarea.select()
document.execCommand('copy')
document.body.removeChild(textarea)
}
// Bestätigung als Vorschau-Modal statt kurzem Icon-Blitz: so sieht man den Bericht direkt
// (auch praktisch, wenn man ihn gar nicht kopieren, sondern nur ansehen möchte) und kann
// in Ruhe wieder schließen.
shareIcon.addEventListener('click', () => {
const message = buildMonthReportText()
shareReportPreview.innerText = message
copyTextToClipboard(message)
.then(() => {
shareReportStatus.innerText = '✓ In die Zwischenablage kopiert'
shareReportStatus.style.color = 'rgb(120,170,86)'
})
.catch((error) => {
console.error('Bericht konnte nicht in die Zwischenablage kopiert werden:', error)
shareReportStatus.innerText = 'Kopieren nicht möglich - Text unten manuell markieren'
shareReportStatus.style.color = '#dc3545'
})
.finally(() => {
new bootstrap.Modal(shareReportModalEl).show()
})
})
async function getActualDataAndFillView(monat = currentDate.getMonth(), jahr = currentDate.getFullYear()) {
try {
// Einfüfen des aktuellen Monats
document.getElementById('actualMonthName').innerHTML = monate[monat !== 12 ? monat : 0];
console.log("AKTUELLER MONAT SYSTEM: ", monat)
console.log("AKTUELLER MONAT REAL: ", currentDate.getMonth())
// Settings vor ausfüllen
// Monatswunsch-Stunden Abfragen
var MonthGoal = 50
// DATEN VON SETTINGS ABFRAGEN
getAllEntries('settings')
.then(function(result) {
document.getElementById('studysinput').value = (result.find(element => element.SettingsID === 1) == undefined) ? 0 : parseInt(result.find(element => element.SettingsID === 1).SettingsValue)
document.getElementById('MonthGoalInput').value = (result.find(element => element.SettingsID === 2) == undefined) ? 50 : parseInt(result.find(element => element.SettingsID === 2).SettingsValue)
MonthGoal = (result.find(element => element.SettingsID === 2) == undefined) ? 50 : parseInt(result.find(element => element.SettingsID === 2).SettingsValue)
});
// Filter funktion aufrufen und entsprechend mit dem aktuellen Datum füllen
const filteredEntries = await filterEntriesByMonthYear(monat === 12 ? 1 : monat + 1, jahr);
currentMonthEntries = filteredEntries
console.log("update-complete")
console.log(jahr)
// Tabelle mit den aktuellen informationen füllen (funktion triggern und Daten übergeben)
fillTableWithEntries(filteredEntries, sortField, sortDirection, ldcLabel)
// 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 + "/" + MonthGoal
document.getElementById('prBarMonth').style.width = `${(100/MonthGoal)*parseInt(GesamtStundenMonat)}%`
document.getElementById('MonthSumHours').value = GesamtStundenMonat
// Aktueller Rest an Stunden
const rest = MonthGoal - 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 (Dienstjahr, gekoppelt an den gerade angezeigten Monat/Jahr)
// Bei aktiver 55h-Regel wird jeder Monat mit LDC/Sonstiges-Anteil auf max. 55h gedeckelt,
// reine Dienststunden zählen dabei immer voll (siehe calculateServiceYearTotal).
var requestServiceYear = getServiceYear(new Date(jahr, monat, 1));
var yearEntries = await filterEntriesByServiceYear(requestServiceYear)
var yearData = formatDuration(calculateServiceYearTotal(yearEntries, rule55Active), true)
document.getElementById('yearHours').innerText = yearData
document.getElementById('yearRest').innerText = 600 - parseInt(yearData)
document.getElementById('prBarYear').style.width = `${Math.round((100/600)*parseInt(yearData))}%`
updateRule55Badge()
} 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
}
});
//
// BEARBEITUNGS FORMULAR
//
var edithours = document.getElementById('editStunden')
var editMins = document.getElementById('editMinuten')
var editldcCheck = document.getElementById('editldcCheck');
var editsonstigesCheck = document.getElementById('editsonstigesCheck');
var editsonstigesText = document.getElementById('edit-sonstiges-text');
var editsonstigesInput = document.getElementById('editsonstigesInput');
var EditSaveButton = document.getElementById('editEntrySubmitButton');
// Änderungen überwachen damit die das Formular nicht zu früh abgesendet wird
edithours.addEventListener('input', () => {
checkEditInput();
console.log(this.value)
})
editMins.addEventListener('input', () => {
checkEditInput();
console.log(this.value)
})
editsonstigesInput.addEventListener('input', () => {
checkEditInput();
console.log(this.value)
})
editldcCheck.addEventListener('change', function() {
if (editldcCheck.checked) {
editsonstigesCheck.checked = false;
editsonstigesText.style.display = 'none';
editsonstigesInput.removeAttribute('required'); // Entferne required, wenn "Sonstiges" abgewählt ist
}
});
editsonstigesCheck.addEventListener('change', function() {
checkEditInput();
if (editsonstigesCheck.checked) {
editldcCheck.checked = false;
editsonstigesText.style.display = 'block';
editsonstigesInput.setAttribute('required', 'required'); // Setze required, wenn "Sonstiges" ausgewählt ist
} else {
editsonstigesText.style.display = 'none';
editsonstigesInput.removeAttribute('required'); // Entferne required, wenn "Sonstiges" abgewählt ist
}
});
document.getElementById('editEntrySubmitButton').addEventListener('click', () => {
var ToEditID = document.getElementById('editEntryID').value
// console.log(`ID: ${ToEditID}, Hours: ${editHours.values}, Minutes: ${editMins.values}`)
var type = 1
// Abfragen der Checkboxen
const ldcCheck = document.getElementById('editldcCheck').checked
if (ldcCheck) {
type = 2
document.getElementById('editldcCheck').checked = false
} else if (document.getElementById('editsonstigesCheck').checked) {
type = 3;
document.getElementById('editsonstigesCheck').checked = false;
sonstigesText.style.display = 'none';
}
updateEntry(parseInt(ToEditID), 'hours', {
date: document.getElementById('editDatum').value,
duration: ((parseInt(edithours.value) || 0)*60) + parseInt(editMins.value),
type: type,
status: 1,
sondertext: document.getElementById('editsonstigesInput').value,
}).then(() => {
// console.log('Eintrag aktualisiert.');
location.reload()
});
})
document.getElementById('DeleteEntryButton').addEventListener('click', () => {
const ToEditID = document.getElementById('editEntryID').value
deleteEntry(parseInt(ToEditID)).then(() => {
console.log(`Löschen von Eintrag: ${ToEditID}`);
location.reload()
})
})
//
// MONATSANSICHT Anpassen
//
const monthEntrys = document.querySelectorAll('.monthEntrys');
// Cursor für die Monatsnavigation: echtes Kalenderjahr + 0-basierter Monat (JS-Konvention).
// Startet auf dem aktuellen Monat/Jahr und wird bei Vor/Zurück direkt fortgeschrieben,
// unabhängig vom Dienstjahr-Label - dadurch keine künstliche Sperre mehr bei Sept/Aug.
var cursorMonth = new Date().getMonth();
var cursorYear = new Date().getFullYear();
document.getElementById('dashbord_month_area').addEventListener('click', () =>{
if (!document.getElementById('dashbord_month_area').classList.contains('ActiveMonth')) {
document.getElementById('dashbord_month_area').classList.replace('closeMonthArea', 'openMonthArea')
document.getElementById('dashbord_month_area').classList.add(['openMonthArea'])
document.getElementById('dashbord_month_area').classList.add(['ActiveMonth'])
document.getElementById('ActivitysTable').classList.add(['shrinkActivitys'])
document.getElementById('ActivitysTable').classList.replace('growActivitys', 'shrinkActivitys')
document.getElementById('dashbord_month_area').classList.remove('mt-4')
// document.getElementById('dashbord_year_area').classList.add('fade-out')
// Für jedes ausgewählte Element die neue Klasse hinzufügen
setTimeout(function() {
monthEntrys.forEach(element => {
if (element.classList.contains('fade-out')) {
element.classList.replace('fade-out', 'fade-in');
} else {
element.classList.add('fade-in');
}
});
document.getElementById('MonthNameOfActual').innerHTML = "Aktuell:"
}, 300);
} else {
document.getElementById('dashbord_month_area').classList.remove('ActiveMonth')
document.getElementById('dashbord_month_area').classList.replace('openMonthArea', 'closeMonthArea')
document.getElementById('ActivitysTable').classList.replace('shrinkActivitys', 'growActivitys')
monthEntrys.forEach(element => {
element.classList.replace('fade-in', 'fade-out');
});
document.getElementById('MonthNameOfActual').innerHTML = "Monat:"
cursorMonth = new Date().getMonth();
cursorYear = new Date().getFullYear();
getActualDataAndFillView(cursorMonth, cursorYear)
}
})
document.getElementById('btn-month-before').addEventListener('click', () =>{
if (cursorMonth === 0) {
// Januar -> Dezember des Vorjahres
cursorMonth = 11;
cursorYear -= 1;
} else {
cursorMonth -= 1;
}
getActualDataAndFillView(cursorMonth, cursorYear)
});
document.getElementById('btn-month-next').addEventListener('click', () =>{
if (cursorMonth === 11) {
// Dezember -> Januar des Folgejahres
cursorMonth = 0;
cursorYear += 1;
} else {
cursorMonth += 1;
}
getActualDataAndFillView(cursorMonth, cursorYear)
})
function setNewCalsOfMonth(TheMonth) {
}
//
// 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 (mins.value) { // Stunden sind optional, Minuten bleiben Pflicht
// 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');
}
}
var editallowToSend = true;
function checkEditInput() {
var edithours = document.getElementById('editStunden')
var editMins = document.getElementById('editMinuten')
var editsonstigesCheck = document.getElementById('editsonstigesCheck');
var editsonstigesText = document.getElementById('edit-sonstiges-text');
var editsonstigesInput = document.getElementById('editsonstigesInput');
var EditSaveButton = document.getElementById('editEntrySubmitButton');
// Eingabe feld für Beschreibung leeren wenn sonstiges abgewählt wird
if (!editsonstigesCheck.checked) {
editsonstigesInput.value = null;
}
// Berechtigungen durch gehen damit Button verfügbar und Form abgesendet werden kann
if ((editsonstigesCheck.checked && editsonstigesInput.value !== "") || !(editsonstigesCheck.checked)) {
// Debug Ausgabe für Bedingungsstufen
// console.log("Erste Bedingung: TRUE")
if (editMins.value) { // Stunden sind optional, Minuten bleiben Pflicht
// Debug Ausgabe für Bedingungsstufen
// console.log("Zweite Bedingung: TRUE")
if (!editallowToSend) {
// Debug Ausgabe für Bedingungsstufen
// console.log("Dritte Bedingung: TRUE")
editallowToSend = true;
EditSaveButton.classList.remove('disabled');
EditSaveButton.classList.replace('btn-light', 'btn-primary');
}
} else if (editallowToSend) {
editallowToSend = false;
EditSaveButton.classList.add('disabled');
EditSaveButton.classList.replace('btn-primary', 'btn-light');
}
} else if (editallowToSend) {
editallowToSend = false;
EditSaveButton.classList.add('disabled');
EditSaveButton.classList.replace('btn-primary', 'btn-light');
}
// Debug ausgabe er Werte
console.log(`Status: ${editallowToSend} - Check: ${editsonstigesCheck.checked} - Input: ${editsonstigesInput.value} - Stunden: ${edithours.value} - Min: ${editMinuten.value}`)
}

Powered by TurnKey Linux.