@ -38,8 +38,7 @@ var sortField = 'date';
var sortDirection = 'asc' ;
var sortDirection = 'asc' ;
// Ob die Filter/Sortier-Optionen gerade sichtbar sind (wird ebenfalls im Cache gespeichert).
// Ob die Filter/Sortier-Optionen gerade sichtbar sind (wird ebenfalls im Cache gespeichert).
// Standardmäßig ausgeblendet, bis der Nutzer sie einmal selbst einblendet.
var isFilterVisible = true ;
var isFilterVisible = false ;
// Ob die Aktivitäten-Tabelle gerade maximiert ist (Timer-Karte ist dann ausgeblendet).
// Ob die Aktivitäten-Tabelle gerade maximiert ist (Timer-Karte ist dann ausgeblendet).
var isTableMaximized = false ;
var isTableMaximized = false ;
@ -52,61 +51,8 @@ var currentMonthEntries = [];
// Trigger
// Trigger
//
//
//
// ANONYME NUTZUNGSSTATISTIK (Admin-Dashboard)
//
// Liest die zufällige Geräte-ID aus dem localStorage oder legt einmalig eine neue an.
// Kein Bezug zu einer Person - rein lokal generiert, dient nur der Dashboard-Zählung.
function getOrCreateDeviceId ( ) {
try {
let id = localStorage . getItem ( 'piomintDeviceId' )
if ( ! id ) {
id = ( window . crypto && crypto . randomUUID ) ? crypto . randomUUID ( ) : ` ${ Date . now ( ) } - ${ Math . random ( ) . toString ( 16 ) . slice ( 2 ) } `
localStorage . setItem ( 'piomintDeviceId' , id )
}
return id
} catch ( error ) {
return null
}
}
// Meldet höchstens einmal pro Gerät und Tag ein anonymes "App genutzt"-Signal ans Backend.
// Darf die App unter keinen Umständen blockieren oder zum Absturz bringen - daher überall try/catch.
function pingUsageIfNeeded ( ) {
try {
const today = new Date ( ) . toISOString ( ) . slice ( 0 , 10 )
if ( localStorage . getItem ( 'piomintLastPing' ) === today ) {
return
}
const deviceId = getOrCreateDeviceId ( )
if ( ! deviceId ) {
return
}
const standalone = ( window . matchMedia && window . matchMedia ( '(display-mode: standalone)' ) . matches ) || window . navigator . standalone === true
fetch ( '/app/track/' , {
method : 'POST' ,
headers : { 'Content-Type' : 'application/json' } ,
body : JSON . stringify ( {
device _id : deviceId ,
app _version : document . body . dataset . appVersion || '' ,
standalone : standalone ,
} ) ,
} ) . then ( ( ) => {
localStorage . setItem ( 'piomintLastPing' , today )
} ) . catch ( ( ) => {
// Kein Netz/Fehler beim Tracking - einfach beim nächsten Öffnen erneut versuchen
} )
} catch ( error ) {
console . error ( 'Nutzungssignal konnte nicht gesendet werden:' , error )
}
}
// Wenn das Dokument komplett geladen ist
// Wenn das Dokument komplett geladen ist
document . addEventListener ( 'DOMContentLoaded' , ( event ) => {
document . addEventListener ( 'DOMContentLoaded' , ( event ) => {
pingUsageIfNeeded ( )
initDB ( ) . then ( async ( ) => {
initDB ( ) . then ( async ( ) => {
console . log ( 'IndexedDB erfolgreich initialisiert.' ) ;
console . log ( 'IndexedDB erfolgreich initialisiert.' ) ;
// Hier kannst du die App weiter initialisieren, z.B. Daten laden oder die UI aufbauen
// Hier kannst du die App weiter initialisieren, z.B. Daten laden oder die UI aufbauen
@ -327,7 +273,7 @@ NewEntryButton.addEventListener('click', () => {
}
}
// Berechnen der Duration (Stunden sind optional -> ohne Eingabe wird 0 gespeichert)
// Berechnen der Duration (Stunden sind optional -> ohne Eingabe wird 0 gespeichert)
const duration = ( ( parseInt ( hours . value ) || 0 ) * 60 ) + ( parseInt ( mins . value ) || 0 )
const duration = ( ( parseInt ( hours . value ) || 0 ) * 60 ) + parseInt ( mins . value )
const newEntryData = {
const newEntryData = {
date : document . getElementById ( 'datum' ) . value ,
date : document . getElementById ( 'datum' ) . value ,
@ -335,7 +281,6 @@ NewEntryButton.addEventListener('click', () => {
type : type ,
type : type ,
status : 1 ,
status : 1 ,
sondertext : document . getElementById ( 'sonstigesInput' ) . value ,
sondertext : document . getElementById ( 'sonstigesInput' ) . value ,
partner : document . getElementById ( 'partnerInput' ) . value . trim ( ) ,
}
}
addEntry ( newEntryData , 'hours' ) . then ( ( id ) => {
addEntry ( newEntryData , 'hours' ) . then ( ( id ) => {
@ -346,7 +291,6 @@ NewEntryButton.addEventListener('click', () => {
hours . value = null
hours . value = null
mins . value = null
mins . value = null
document . getElementById ( 'sonstigesInput' ) . value = null
document . getElementById ( 'sonstigesInput' ) . value = null
document . getElementById ( 'partnerInput' ) . value = null
checkInput ( )
checkInput ( )
}
}
} )
} )
@ -700,10 +644,6 @@ editsonstigesCheck.addEventListener('change', function() {
document . getElementById ( 'editEntrySubmitButton' ) . addEventListener ( 'click' , ( ) => {
document . getElementById ( 'editEntrySubmitButton' ) . addEventListener ( 'click' , ( ) => {
if ( ! editallowToSend ) {
return
}
var ToEditID = document . getElementById ( 'editEntryID' ) . value
var ToEditID = document . getElementById ( 'editEntryID' ) . value
// console.log(`ID: ${ToEditID}, Hours: ${editHours.values}, Minutes: ${editMins.values}`)
// console.log(`ID: ${ToEditID}, Hours: ${editHours.values}, Minutes: ${editMins.values}`)
@ -722,11 +662,10 @@ document.getElementById('editEntrySubmitButton').addEventListener('click', () =>
updateEntry ( parseInt ( ToEditID ) , 'hours' , {
updateEntry ( parseInt ( ToEditID ) , 'hours' , {
date : document . getElementById ( 'editDatum' ) . value ,
date : document . getElementById ( 'editDatum' ) . value ,
duration : ( ( parseInt ( edithours . value ) || 0 ) * 60 ) + ( parseInt ( editMins . value ) || 0 ) ,
duration : ( ( parseInt ( edithours . value ) || 0 ) * 60 ) + parseInt ( editMins . value ) ,
type : type ,
type : type ,
status : 1 ,
status : 1 ,
sondertext : document . getElementById ( 'editsonstigesInput' ) . value ,
sondertext : document . getElementById ( 'editsonstigesInput' ) . value ,
partner : document . getElementById ( 'editPartnerInput' ) . value . trim ( ) ,
} ) . then ( ( ) => {
} ) . then ( ( ) => {
// console.log('Eintrag aktualisiert.');
// console.log('Eintrag aktualisiert.');
location . reload ( )
location . reload ( )
@ -761,10 +700,9 @@ document.getElementById('dashbord_month_area').addEventListener('click', () =>{
document . getElementById ( 'dashbord_month_area' ) . classList . replace ( 'closeMonthArea' , 'openMonthArea' )
document . getElementById ( 'dashbord_month_area' ) . classList . replace ( 'closeMonthArea' , 'openMonthArea' )
document . getElementById ( 'dashbord_month_area' ) . classList . add ( [ 'openMonthArea' ] )
document . getElementById ( 'dashbord_month_area' ) . classList . add ( [ 'openMonthArea' ] )
document . getElementById ( 'dashbord_month_area' ) . classList . add ( [ 'ActiveMonth' ] )
document . getElementById ( 'dashbord_month_area' ) . classList . add ( [ 'ActiveMonth' ] )
// ActivitysTable ist jetzt flex:1 1 auto (siehe custom.css) und macht der wachsenden
document . getElementById ( 'ActivitysTable' ) . classList . add ( [ 'shrinkActivitys' ] )
// Monatskarte automatisch Platz - kein manuelles shrinkActivitys/growActivitys mehr nötig,
document . getElementById ( 'ActivitysTable' ) . classList . replace ( 'growActivitys' , 'shrinkActivitys' )
// das würde der Flex-Berechnung sonst mit einer festen vh-Höhe in die Quere kommen.
document . getElementById ( 'dashbord_month_area' ) . classList . remove ( 'mt-4' )
document . getElementById ( 'dashbord_month_area' ) . classList . remove ( 'mt-3' )
// document.getElementById('dashbord_year_area').classList.add('fade-out')
// document.getElementById('dashbord_year_area').classList.add('fade-out')
// Für jedes ausgewählte Element die neue Klasse hinzufügen
// Für jedes ausgewählte Element die neue Klasse hinzufügen
setTimeout ( function ( ) {
setTimeout ( function ( ) {
@ -780,7 +718,7 @@ document.getElementById('dashbord_month_area').addEventListener('click', () =>{
} else {
} else {
document . getElementById ( 'dashbord_month_area' ) . classList . remove ( 'ActiveMonth' )
document . getElementById ( 'dashbord_month_area' ) . classList . remove ( 'ActiveMonth' )
document . getElementById ( 'dashbord_month_area' ) . classList . replace ( 'openMonthArea' , 'closeMonthArea' )
document . getElementById ( 'dashbord_month_area' ) . classList . replace ( 'openMonthArea' , 'closeMonthArea' )
document . getElementById ( ' dashbord_month_area') . classList . add ( 'mt-3 ')
document . getElementById ( ' ActivitysTable') . classList . replace ( 'shrinkActivitys' , 'growActivitys ')
monthEntrys . forEach ( element => {
monthEntrys . forEach ( element => {
element . classList . replace ( 'fade-in' , 'fade-out' ) ;
element . classList . replace ( 'fade-in' , 'fade-out' ) ;
} ) ;
} ) ;
@ -844,19 +782,16 @@ function checkInput() {
allowToSend = true ;
allowToSend = true ;
NewEntryButton . classList . remove ( 'disabled' ) ;
NewEntryButton . classList . remove ( 'disabled' ) ;
NewEntryButton . classList . replace ( 'btn-light' , 'btn-primary' ) ;
NewEntryButton . classList . replace ( 'btn-light' , 'btn-primary' ) ;
NewEntryButton . disabled = false ;
}
}
} else if ( allowToSend ) {
} else if ( allowToSend ) {
allowToSend = false ;
allowToSend = false ;
NewEntryButton . classList . add ( 'disabled' ) ;
NewEntryButton . classList . add ( 'disabled' ) ;
NewEntryButton . classList . replace ( 'btn-primary' , 'btn-light' ) ;
NewEntryButton . classList . replace ( 'btn-primary' , 'btn-light' ) ;
NewEntryButton . disabled = true ;
}
}
} else if ( allowToSend ) {
} else if ( allowToSend ) {
allowToSend = false ;
allowToSend = false ;
NewEntryButton . classList . add ( 'disabled' ) ;
NewEntryButton . classList . add ( 'disabled' ) ;
NewEntryButton . classList . replace ( 'btn-primary' , 'btn-light' ) ;
NewEntryButton . classList . replace ( 'btn-primary' , 'btn-light' ) ;
NewEntryButton . disabled = true ;
}
}
}
}
@ -887,20 +822,17 @@ function checkEditInput() {
editallowToSend = true ;
editallowToSend = true ;
EditSaveButton . classList . remove ( 'disabled' ) ;
EditSaveButton . classList . remove ( 'disabled' ) ;
EditSaveButton . classList . replace ( 'btn-light' , 'btn-primary' ) ;
EditSaveButton . classList . replace ( 'btn-light' , 'btn-primary' ) ;
EditSaveButton . disabled = false ;
}
}
} else if ( editallowToSend ) {
} else if ( editallowToSend ) {
editallowToSend = false ;
editallowToSend = false ;
EditSaveButton . classList . add ( 'disabled' ) ;
EditSaveButton . classList . add ( 'disabled' ) ;
EditSaveButton . classList . replace ( 'btn-primary' , 'btn-light' ) ;
EditSaveButton . classList . replace ( 'btn-primary' , 'btn-light' ) ;
EditSaveButton . disabled = true ;
}
}
} else if ( editallowToSend ) {
} else if ( editallowToSend ) {
editallowToSend = false ;
editallowToSend = false ;
EditSaveButton . classList . add ( 'disabled' ) ;
EditSaveButton . classList . add ( 'disabled' ) ;
EditSaveButton . classList . replace ( 'btn-primary' , 'btn-light' ) ;
EditSaveButton . classList . replace ( 'btn-primary' , 'btn-light' ) ;
EditSaveButton . disabled = true ;
}
}
// Debug ausgabe er Werte
// Debug ausgabe er Werte
console . log ( ` Status: ${ editallowToSend } - Check: ${ editsonstigesCheck . checked } - Input: ${ editsonstigesInput . value } - Stunden: ${ edithours . value } - Min: ${ editMin s . value } ` )
console . log ( ` Status: ${ editallowToSend } - Check: ${ editsonstigesCheck . checked } - Input: ${ editsonstigesInput . value } - Stunden: ${ edithours . value } - Min: ${ editMin uten . value } ` )
}
}