Portal-Admin: archivierte Projekte/Kunden ausblenden, Kundentabelle ohne Horizontal-Scroll
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -21,6 +21,11 @@
|
|||||||
.admin-search { width: 100%; max-width: 380px; padding: 9px 14px; border-radius: 10px;
|
.admin-search { width: 100%; max-width: 380px; padding: 9px 14px; border-radius: 10px;
|
||||||
border: 1px solid rgba(255,255,255,0.18); background: rgba(255,255,255,0.06); color: inherit; margin-bottom: 12px; }
|
border: 1px solid rgba(255,255,255,0.18); background: rgba(255,255,255,0.06); color: inherit; margin-bottom: 12px; }
|
||||||
.admin-table-wrap { overflow-x: auto; border-radius: 12px; border: 1px solid rgba(255,255,255,0.1); }
|
.admin-table-wrap { overflow-x: auto; border-radius: 12px; border: 1px solid rgba(255,255,255,0.1); }
|
||||||
|
/* Kundentabelle: volle Breite, kein Links-/Rechts-Scroll */
|
||||||
|
.admin-table-wrap.no-scroll { overflow-x: visible; }
|
||||||
|
.admin-table-wrap.no-scroll table.admin-table { table-layout: fixed; }
|
||||||
|
.admin-table-wrap.no-scroll .admin-table td { word-break: break-word; overflow-wrap: anywhere; }
|
||||||
|
.cust-actions { display: flex; flex-wrap: wrap; gap: 6px; }
|
||||||
table.admin-table { width: 100%; border-collapse: collapse; font-size: 14px; }
|
table.admin-table { width: 100%; border-collapse: collapse; font-size: 14px; }
|
||||||
.admin-table th, .admin-table td { text-align: left; padding: 9px 12px; border-bottom: 1px solid rgba(255,255,255,0.08); vertical-align: middle; }
|
.admin-table th, .admin-table td { text-align: left; padding: 9px 12px; border-bottom: 1px solid rgba(255,255,255,0.08); vertical-align: middle; }
|
||||||
.admin-table th { font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; opacity: 0.65; }
|
.admin-table th { font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; opacity: 0.65; }
|
||||||
@@ -34,7 +39,7 @@
|
|||||||
padding: 5px 11px; border-radius: 8px; cursor: pointer; font-size: 13px; white-space: nowrap; }
|
padding: 5px 11px; border-radius: 8px; cursor: pointer; font-size: 13px; white-space: nowrap; }
|
||||||
.mini-btn:hover { background: rgba(255,255,255,0.14); }
|
.mini-btn:hover { background: rgba(255,255,255,0.14); }
|
||||||
.mini-btn.primary { background: rgba(94,234,212,0.16); border-color: rgba(94,234,212,0.5); }
|
.mini-btn.primary { background: rgba(94,234,212,0.16); border-color: rgba(94,234,212,0.5); }
|
||||||
.code-input { width: 90px; padding: 4px 8px; border-radius: 7px; border: 1px solid rgba(255,255,255,0.2);
|
.code-input { width: 100%; min-width: 60px; max-width: 90px; padding: 4px 8px; border-radius: 7px; border: 1px solid rgba(255,255,255,0.2);
|
||||||
background: rgba(255,255,255,0.06); color: inherit; font: inherit; font-size: 13px; }
|
background: rgba(255,255,255,0.06); color: inherit; font: inherit; font-size: 13px; }
|
||||||
.detail-row td { background: rgba(255,255,255,0.03); }
|
.detail-row td { background: rgba(255,255,255,0.03); }
|
||||||
.detail-box { padding: 6px 4px; }
|
.detail-box { padding: 6px 4px; }
|
||||||
@@ -137,8 +142,12 @@
|
|||||||
<section class="admin-section" id="tab-customers">
|
<section class="admin-section" id="tab-customers">
|
||||||
<input class="admin-search" id="customer-search" type="search"
|
<input class="admin-search" id="customer-search" type="search"
|
||||||
placeholder="Kunden suchen (Kundennr., Name, E-Mail, Ort)…">
|
placeholder="Kunden suchen (Kundennr., Name, E-Mail, Ort)…">
|
||||||
<div class="admin-table-wrap">
|
<div class="admin-table-wrap no-scroll">
|
||||||
<table class="admin-table">
|
<table class="admin-table">
|
||||||
|
<colgroup>
|
||||||
|
<col style="width:9%"><col style="width:23%"><col style="width:11%"><col style="width:11%">
|
||||||
|
<col style="width:13%"><col style="width:8%"><col style="width:25%">
|
||||||
|
</colgroup>
|
||||||
<thead>
|
<thead>
|
||||||
<tr><th>Kundennr.</th><th>Kunde</th><th>Status</th><th>Portal</th><th>Letzter Login</th><th>Projekte</th><th>Aktionen</th></tr>
|
<tr><th>Kundennr.</th><th>Kunde</th><th>Status</th><th>Portal</th><th>Letzter Login</th><th>Projekte</th><th>Aktionen</th></tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|||||||
@@ -217,9 +217,11 @@ async function loadCustomers(search = '') {
|
|||||||
}
|
}
|
||||||
tbody.innerHTML = customers.map((c) => `
|
tbody.innerHTML = customers.map((c) => `
|
||||||
<tr data-customer-row="${escapeHtml(c.id)}">
|
<tr data-customer-row="${escapeHtml(c.id)}">
|
||||||
<td style="white-space:nowrap">
|
<td>
|
||||||
<input class="code-input" data-code-for="${escapeHtml(c.id)}" value="${escapeHtml(c.code)}" placeholder="–">
|
<div class="cust-actions">
|
||||||
<button class="mini-btn" data-save-code="${escapeHtml(c.id)}" title="Kundennummer speichern">✓</button>
|
<input class="code-input" data-code-for="${escapeHtml(c.id)}" value="${escapeHtml(c.code)}" placeholder="–">
|
||||||
|
<button class="mini-btn" data-save-code="${escapeHtml(c.id)}" title="Kundennummer speichern">✓</button>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<strong>${escapeHtml(c.name)}</strong><br>
|
<strong>${escapeHtml(c.name)}</strong><br>
|
||||||
@@ -229,10 +231,12 @@ async function loadCustomers(search = '') {
|
|||||||
<td>${c.portalAccessEnabled ? '<span class="pill pill-ok">aktiv</span>' : '<span class="pill pill-muted">kein Zugang</span>'}</td>
|
<td>${c.portalAccessEnabled ? '<span class="pill pill-ok">aktiv</span>' : '<span class="pill pill-muted">kein Zugang</span>'}</td>
|
||||||
<td>${fmtDateTime(c.lastLoginAt)}</td>
|
<td>${fmtDateTime(c.lastLoginAt)}</td>
|
||||||
<td>${c.projectCount}</td>
|
<td>${c.projectCount}</td>
|
||||||
<td style="white-space:nowrap">
|
<td>
|
||||||
<button class="mini-btn primary" data-view-as="${escapeHtml(c.id)}">Als Kunde ansehen</button>
|
<div class="cust-actions">
|
||||||
<button class="mini-btn" data-activity="${escapeHtml(c.id)}">Arbeiten</button>
|
<button class="mini-btn primary" data-view-as="${escapeHtml(c.id)}">Als Kunde ansehen</button>
|
||||||
<button class="mini-btn" data-invoices="${escapeHtml(c.id)}"${c.invoiceNinjaLinked ? '' : ' title="Nicht mit InvoiceNinja verknüpft"'}>Rechnungen</button>
|
<button class="mini-btn" data-activity="${escapeHtml(c.id)}">Arbeiten</button>
|
||||||
|
<button class="mini-btn" data-invoices="${escapeHtml(c.id)}"${c.invoiceNinjaLinked ? '' : ' title="Nicht mit InvoiceNinja verknüpft"'}>Rechnungen</button>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>`).join('')
|
</tr>`).join('')
|
||||||
|
|
||||||
|
|||||||
@@ -105,7 +105,9 @@ router.get('/projects', async (req, res) => {
|
|||||||
])
|
])
|
||||||
const nameById = customerNameMap(customers)
|
const nameById = customerNameMap(customers)
|
||||||
|
|
||||||
let items = projects.map((p) => ({
|
let items = projects
|
||||||
|
.filter((p) => !p.archived)
|
||||||
|
.map((p) => ({
|
||||||
id: p.$id,
|
id: p.$id,
|
||||||
projectName: p.projectName || '',
|
projectName: p.projectName || '',
|
||||||
subdomain: p.subdomain || '',
|
subdomain: p.subdomain || '',
|
||||||
@@ -155,7 +157,9 @@ router.get('/customers', async (req, res) => {
|
|||||||
if (p.customerId) projectCount[p.customerId] = (projectCount[p.customerId] || 0) + 1
|
if (p.customerId) projectCount[p.customerId] = (projectCount[p.customerId] || 0) + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
let items = customers.map((c) => ({
|
let items = customers
|
||||||
|
.filter((c) => !c.archived)
|
||||||
|
.map((c) => ({
|
||||||
id: c.$id,
|
id: c.$id,
|
||||||
code: c.code || '',
|
code: c.code || '',
|
||||||
name: c.name || '',
|
name: c.name || '',
|
||||||
|
|||||||
Reference in New Issue
Block a user