Files
Buchhaltung/public/script.js
T
2025-11-15 18:54:32 +01:00

257 lines
9.3 KiB
JavaScript

// Event-Listener für das Laden der Seite
window.addEventListener('DOMContentLoaded', () => {
const savedYear = localStorage.getItem('selectedYear');
const savedMonth = localStorage.getItem('selectedMonth');
document.getElementById('jahr').value = savedYear || new Date().getFullYear();
document.getElementById('monat').value = savedMonth || String(new Date().getMonth() + 1).padStart(2, '0');
loadData();
});
document.getElementById('jahr').addEventListener('change', loadData);
document.getElementById('monat').addEventListener('change', loadData);
document.getElementById('eintrag').addEventListener('click', addNewEntry);
document.getElementById('export').addEventListener('click', async () => {
try {
const res = await fetch('/api/ordner-oeffnen');
const data = await res.json();
console.log(data.message);
} catch (err) {
console.error('Fehler beim Öffnen des Ordners:', err);
alert('Ordner konnte nicht geöffnet werden');
}
});
document.getElementById('path').addEventListener('click', async () => {
try {
const res = await fetch('/api/pfad-aendern', { method: 'POST' });
const data = await res.json();
alert(`Pfad geändert: ${data.path || 'Abgebrochen'}`);
} catch (err) {
console.error(err);
alert('Fehler beim Ändern des Pfades');
}
});
function zeigeNachricht(text, typ = 'erfolg') {
const nachrichtContainer = document.getElementById('nachricht-container');
nachrichtContainer.textContent = text;
nachrichtContainer.className = `nachricht ${typ}`;
nachrichtContainer.style.display = 'block';
setTimeout(() => nachrichtContainer.style.display = 'none', 3000);
}
function getMonthName(monthNumber) {
const months = ['Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'];
return months[parseInt(monthNumber)-1];
}
async function loadData() {
const selectedYear = document.getElementById('jahr').value;
const selectedMonth = document.getElementById('monat').value;
localStorage.setItem('selectedYear', selectedYear);
localStorage.setItem('selectedMonth', selectedMonth);
const tableBody = document.querySelector('#buchhaltung-tabelle tbody');
tableBody.innerHTML = '';
try {
const response = await fetch(`/api/daten/${selectedYear}/${selectedMonth}`);
let data = [];
if (response.ok) {
data = await response.json();
} else {
console.warn('Daten nicht gefunden, erzeuge leere Tabelle');
}
if (!data || data.length === 0) {
addNewEntry(true);
zeigeNachricht(`Für den Monat ${getMonthName(selectedMonth)} gibt es keine Daten!`, 'fehler');
} else {
data.forEach((row, idx) => {
const tr = document.createElement('tr');
tr.dataset.rowIndex = idx;
row.forEach(cell => {
const td = document.createElement('td');
td.contentEditable = true;
td.textContent = cell || '';
tr.appendChild(td);
});
const betragZelle = tr.querySelector('td');
betragZelle.addEventListener('blur', () => {
betragZelle.textContent = formatAsEuro(betragZelle.textContent);
});
tr.appendChild(createButtonCell(tr));
tableBody.appendChild(tr);
});
}
updateSumme();
} catch (err) {
console.error(err);
addNewEntry(true);
updateSumme();
zeigeNachricht('Keine Verbindung zum Server - arbeite offline.', 'fehler');
}
}
function addNewEntry(suppressMessage = false) {
const tableBody = document.querySelector('#buchhaltung-tabelle tbody');
const tr = document.createElement('tr');
const rowIndex = tableBody.children.length;
tr.dataset.rowIndex = rowIndex;
const today = new Date();
const formattedDate = `${String(today.getDate()).padStart(2,'0')}.${String(today.getMonth()+1).padStart(2,'0')}.${today.getFullYear()}`;
const ausgabeTd = createEditableCell();
ausgabeTd.addEventListener('blur', () => ausgabeTd.textContent = formatAsEuro(ausgabeTd.textContent));
const kategorieTd = createEditableCell();
const datumTd = document.createElement('td');
datumTd.textContent = formattedDate;
datumTd.contentEditable = false;
tr.appendChild(ausgabeTd);
tr.appendChild(kategorieTd);
tr.appendChild(datumTd);
tr.appendChild(createButtonCell(tr));
tableBody.appendChild(tr);
if (!suppressMessage) zeigeNachricht('Neue Zeile hinzugefügt!', 'erfolg');
}
function createEditableCell() {
const td = document.createElement('td');
td.contentEditable = true;
return td;
}
function createButtonCell(tr) {
const td = document.createElement('td');
td.style.textAlign = 'center';
td.innerHTML = `<button class="speichern-btn">Speichern</button><button class="loeschen-btn">Löschen</button>`;
td.querySelector('.speichern-btn').addEventListener('click', () => saveRowData(tr));
td.querySelector('.loeschen-btn').addEventListener('click', () => handleDeleteButtonClick(tr));
return td;
}
async function saveRowData(tr) {
const rowIndex = parseInt(tr.dataset.rowIndex, 10);
const updatedRowData = Array.from(tr.querySelectorAll('td')).slice(0, -1).map(td => td.textContent);
// Immer aktuelle Dropdown-Werte nehmen
const selectedYear = document.getElementById('jahr').value;
const selectedMonth = document.getElementById('monat').value;
// In LocalStorage speichern
localStorage.setItem('selectedYear', selectedYear);
localStorage.setItem('selectedMonth', selectedMonth);
try {
const response = await fetch('/api/zeile-speichern', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
rowIndex,
updatedRowData,
jahr: selectedYear,
monat: selectedMonth
})
});
if (!response.ok) {
const errData = await response.json();
throw new Error(errData.error || 'Fehler beim Speichern');
}
zeigeNachricht('Daten gespeichert!', 'erfolg');
} catch (err) {
console.error(err);
zeigeNachricht(`Fehler beim Speichern der Zeile: ${err.message}`, 'fehler');
}
updateSumme();
}
function handleDeleteButtonClick(tr) {
const popup = document.getElementById('confirm-popup');
const yes = document.getElementById('confirm-yes');
const no = document.getElementById('confirm-no');
if (!popup) return console.error('Popup nicht gefunden!');
popup.style.display = 'grid';
yes.replaceWith(yes.cloneNode(true));
no.replaceWith(no.cloneNode(true));
document.getElementById('confirm-yes').addEventListener('click', () => { deleteRow(tr); popup.style.display='none'; });
document.getElementById('confirm-no').addEventListener('click', () => popup.style.display='none');
}
async function deleteRow(tr) {
const rowIndex = parseInt(tr.dataset.rowIndex, 10);
const selectedYear = document.getElementById('jahr').value;
const selectedMonth = document.getElementById('monat').value;
try {
const response = await fetch('/api/zeile-loeschen', {
method: 'POST',
headers: {'Content-Type':'application/json'},
body: JSON.stringify({
zeileIndex: rowIndex, // korrekt benennen
jahr: localStorage.getItem('selectedYear'),
monat: localStorage.getItem('selectedMonth')
})
});
if (!response.ok) throw new Error((await response.json()).error || 'Fehler beim Löschen');
tr.remove();
updateSumme();
zeigeNachricht('Zeile erfolgreich gelöscht!', 'erfolg');
} catch (err) {
console.error(err);
zeigeNachricht(`Fehler: ${err.message}`, 'fehler');
}
}
function updateSumme() {
const rows = document.querySelectorAll('#buchhaltung-tabelle tbody tr');
let summe = 0;
rows.forEach(row => {
let val = row.querySelector('td').textContent.trim();
// Punkte als Tausender-Trennzeichen entfernen
val = val.replace(/\./g, '');
// Komma als Dezimaltrennzeichen in Punkt konvertieren
val = val.replace(',', '.');
const num = parseFloat(val);
summe += isNaN(num) ? 0 : num;
});
const summeZelle = document.getElementById('summe-zelle');
if (summeZelle) summeZelle.textContent = `Summe: ${new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(summe)}`;
}
document.getElementById('suche').addEventListener('input', function() {
const term = this.value.toLowerCase().trim();
document.querySelectorAll('#buchhaltung-tabelle tbody tr').forEach(row => {
const kategorie = row.querySelectorAll('td')[1]?.textContent.toLowerCase().trim();
row.style.display = kategorie?.includes(term) ? '' : 'none';
});
});
function formatAsEuro(value) {
const parsed = parseFloat(value.replace(/[^\d,.-]/g,'').replace(',','.'));
if (isNaN(parsed)) return '';
return new Intl.NumberFormat('de-DE',{style:'currency',currency:'EUR',minimumFractionDigits:2,maximumFractionDigits:2}).format(parsed);
}