From 0912a6812fbfd49a3838b069b250579b872c98ff Mon Sep 17 00:00:00 2001 From: Kerim Atilgan Date: Fri, 15 May 2026 17:57:12 +0200 Subject: [PATCH] =?UTF-8?q?UI=20redesign=20step=202:=20=C3=9Cbersicht=20in?= =?UTF-8?q?=20Stitch=20style?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Page header gains the headline / subtitle pair and a primary "Neue Schaltung" CTA on the right that jumps back to the wizard. - Filter bar moves into a bordered white card with label-caps labels, compact 32px inputs, JetBrains Mono numeric inputs for ID/phone/date and a "Zurücksetzen" pill on the right. - Data table uses the Stitch shell: sticky surface-container-high header row with label-caps column titles, 40px body rows, zebra striping on the even rows and a hover highlight. The previously separate Eingabe/Schaltungs-Datum columns are merged into a single "Daten" cell (E:/A:), Anbieter renders as a primary pill, and the Bearbeiten/Löschen/Dokumente buttons become icon-only actions. - updateSchaltungenTable() now delegates to a single renderer used by both the initial load and the client-side filter, so the layout stays consistent after applying filters. Co-Authored-By: Claude Opus 4.7 (1M context) --- public/index.html | 113 ++++++++++++++++++++--------------- public/script.js | 148 +++++++++++++++++++++------------------------- 2 files changed, 134 insertions(+), 127 deletions(-) diff --git a/public/index.html b/public/index.html index 9856c9f..f43c9a6 100644 --- a/public/index.html +++ b/public/index.html @@ -1166,66 +1166,83 @@
-

Schaltungs-Übersicht

- - -
-

Filter

-
-
- -
-
- -
-
- - +
+ +
-
- - +
+ +
-
- - +
+ +
+ + – + +
-
- - -
-
- + +
+ + +
+
+ + + + + + + + + + + + + + + +
IDDatenKunde / FirmaRufnummerAnbieterTarifHardwareDokumenteAktionen
- -
- - - - - - - - - - - - - - - - - -
Schaltungs-IDEingabe-DatumSchaltungs-DatumNameFirmaRufnummerAnbieterTarifHardwareDokumenteAktionen
-
diff --git a/public/script.js b/public/script.js index a8ea70d..14bc2b9 100644 --- a/public/script.js +++ b/public/script.js @@ -703,46 +703,76 @@ async function refreshDataAfterSchaltungChange() { async function loadSchaltungen() { try { const schaltungen = await apiRequest('/api/schaltungen'); - const tbody = document.querySelector('#schaltungenTable tbody'); - - tbody.innerHTML = ''; - - schaltungen.forEach(s => { - const row = document.createElement('tr'); - row.innerHTML = ` - ${escapeHtml(s.schaltungs_id)} - ${escapeHtml(formatDate(s.eingabe_datum))} - ${escapeHtml(formatDate(s.schaltungs_datum))} - ${escapeHtml(s.vorname)} ${escapeHtml(s.nachname)} - ${escapeHtml(s.firma || '-')} - ${escapeHtml(s.rufnummer)} - ${escapeHtml(s.anbieter_name)} - ${escapeHtml(s.tarif_name)} - ${escapeHtml(s.hardware || '')} - - - - - - `; - // Wire delegated handlers so we don't need inline onclick (avoids JS-injection via names). - row.querySelectorAll('button[data-action]').forEach(btn => { - btn.addEventListener('click', () => { - const action = btn.dataset.action; - const id = parseInt(btn.dataset.id, 10); - if (action === 'documents') showDocuments(id); - else if (action === 'edit') editSchaltung(id); - else if (action === 'delete') deleteSchaltung(id, btn.dataset.schaltungsId, btn.dataset.name); - }); - }); - tbody.appendChild(row); - }); - + renderSchaltungenRows(schaltungen); } catch (error) { console.error('Fehler beim Laden der Schaltungen:', error); } } +// Render schaltungen rows in the Stitch overview table. +function renderSchaltungenRows(schaltungen) { + const tbody = document.querySelector('#schaltungenTable tbody'); + if (!tbody) return; + tbody.innerHTML = ''; + if (!schaltungen || !schaltungen.length) { + const tr = document.createElement('tr'); + tr.innerHTML = 'Keine Schaltungen vorhanden'; + tbody.appendChild(tr); + return; + } + schaltungen.forEach(s => { + const tr = document.createElement('tr'); + tr.className = 'border-b border-outline-variant/30 even:bg-surface-container-low/50 hover:bg-surface-variant/30 transition-colors'; + tr.innerHTML = ` + ${escapeHtml(s.schaltungs_id)} + +
+ E: ${escapeHtml(formatDate(s.eingabe_datum))} + A: ${escapeHtml(formatDate(s.schaltungs_datum))} +
+ + +
${escapeHtml((s.vorname || '') + ' ' + (s.nachname || ''))}
+
${escapeHtml(s.firma || '–')}
+ + ${escapeHtml(s.rufnummer || '–')} + + ${escapeHtml(s.anbieter_name)} + + ${escapeHtml(s.tarif_name)} + ${escapeHtml(s.hardware || '–')} + + + + +
+ + +
+ + `; + tr.querySelectorAll('button[data-action]').forEach(btn => { + btn.addEventListener('click', () => { + const action = btn.dataset.action; + const id = parseInt(btn.dataset.id, 10); + if (action === 'documents') showDocuments(id); + else if (action === 'edit') editSchaltung(id); + else if (action === 'delete') deleteSchaltung(id, btn.dataset.schaltungsId, btn.dataset.name); + }); + }); + tbody.appendChild(tr); + }); +} + // Format any ISO-like date string (YYYY-MM-DD or full timestamp) as DD.MM.YYYY // with leading zeros. Returns the original string unchanged if it cannot be parsed. function formatDate(dateString) { @@ -2256,52 +2286,12 @@ function applyFiltersProvisionen() { function updateSchaltungenTable(schaltungen) { const tbody = document.querySelector('#schaltungenTable tbody'); if (!tbody) return; - - tbody.innerHTML = ''; - - if (schaltungen.length === 0) { - // Show "no results" message - const row = document.createElement('tr'); - row.innerHTML = ` - - 📋 Keine Schaltungen entsprechen den gewählten Filterkriterien - - `; - tbody.appendChild(row); + if (!schaltungen || schaltungen.length === 0) { + tbody.innerHTML = 'Keine Schaltungen entsprechen den Filterkriterien'; return; } - - schaltungen.forEach(s => { - const row = document.createElement('tr'); - row.innerHTML = ` - ${escapeHtml(s.schaltungs_id)} - ${escapeHtml(formatDate(s.eingabe_datum))} - ${escapeHtml(formatDate(s.schaltungs_datum))} - ${escapeHtml(s.vorname)} ${escapeHtml(s.nachname)} - ${escapeHtml(s.firma || '-')} - ${escapeHtml(s.rufnummer)} - ${escapeHtml(s.anbieter_name)} - ${escapeHtml(s.tarif_name)} - ${escapeHtml(s.hardware || '')} - - - - - - - - `; - row.querySelectorAll('button[data-filt-action]').forEach(btn => { - btn.addEventListener('click', () => { - const action = btn.dataset.filtAction; - const id = parseInt(btn.dataset.id, 10); - if (action === 'documents') showDocuments(id); - else if (action === 'edit') editSchaltung(id); - else if (action === 'delete') deleteSchaltung(id, btn.dataset.schaltungsId, btn.dataset.name); - }); - }); - tbody.appendChild(row); - }); + // Delegate to the canonical renderer used by loadSchaltungen. + renderSchaltungenRows(schaltungen); } // Update Provisionen table with filtered data