UX: Upgrade-Tab — Cards statt Tabelle, Freischalten-Button immer sichtbar (SW by-v942)

This commit is contained in:
rene 2026-05-14 13:20:11 +02:00
parent 6762efa04e
commit 9da8665aca
4 changed files with 49 additions and 39 deletions

View file

@ -3,7 +3,7 @@
Router, State-Management, Navigation, Initialisierung.
============================================================ */
const APP_VER = '941'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const APP_VER = '942'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const APP_VERSION = '1.5.1'; // ← semantische Version, wird bei make release gesetzt
const IS_STAGING = location.hostname === 'staging.banyaro.app';
// Cache-Bust-Parameter nach Update-Reload sofort entfernen

View file

@ -3519,55 +3519,65 @@ window.Page_admin = (() => {
const pending = rows.filter(r => !r.fulfilled_at);
const done = rows.filter(r => r.fulfilled_at);
const _row = (r, showBtn) => `
// Offene Anfragen als Cards (mobile-freundlich, Button immer sichtbar)
const _pendingCard = r => `
<div class="card" style="padding:var(--space-4);margin-bottom:var(--space-3)">
<div style="display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-3);flex-wrap:wrap">
<div style="flex:1;min-width:0">
<div style="font-weight:600;font-size:var(--text-sm)">${_esc(r.name)}</div>
<div style="font-size:var(--text-xs);color:var(--c-text-muted);margin-bottom:var(--space-2)">${_esc(r.email)}</div>
<div style="display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap">
${tierBadge(r.tier)}
<span style="font-size:var(--text-xs);color:var(--c-text-muted)">${r.created_at?.slice(0,10) || ''}</span>
</div>
${r.message ? `<div style="margin-top:var(--space-2);font-size:var(--text-xs);color:var(--c-text-secondary);
padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);
background:var(--c-surface-raised,rgba(0,0,0,.04))">
${_esc(r.message)}
</div>` : ''}
</div>
</div>
<button class="btn adm-fulfill-btn" data-id="${r.id}" data-name="${_esc(r.name)}" data-tier="${r.tier}"
style="width:100%;margin-top:var(--space-3);background:#16a34a;color:#fff;border:none;
padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);
cursor:pointer;font-size:var(--text-sm);font-weight:600">
Freischalten
</button>
</div>`;
// Erledigte als kompakte Tabellenzeilen
const _doneRow = r => `
<tr>
<td style="padding:var(--space-2) var(--space-3)">${_esc(r.name)}<br>
<td style="padding:var(--space-2) var(--space-3);font-size:var(--text-sm)">${_esc(r.name)}<br>
<span style="font-size:var(--text-xs);color:var(--c-text-muted)">${_esc(r.email)}</span></td>
<td style="padding:var(--space-2) var(--space-3)">${tierBadge(r.tier)}</td>
<td style="padding:var(--space-2) var(--space-3);font-size:var(--text-xs);color:var(--c-text-muted)">
${r.message ? _esc(r.message) : '—'}</td>
<td style="padding:var(--space-2) var(--space-3);font-size:var(--text-xs);color:var(--c-text-muted)">
${r.created_at?.slice(0,10) || ''}</td>
<td style="padding:var(--space-2) var(--space-3)">
${showBtn
? `<button class="btn btn-sm adm-fulfill-btn" data-id="${r.id}" data-name="${_esc(r.name)}" data-tier="${r.tier}"
style="background:#16a34a;color:#fff;border:none;padding:4px 12px;
border-radius:var(--radius-md);cursor:pointer;font-size:var(--text-xs);font-weight:600">
Freischalten
</button>`
: `<span style="font-size:var(--text-xs);color:var(--c-success)">✓ ${r.fulfilled_at?.slice(0,10)}</span>`}
</td>
<td style="padding:var(--space-2) var(--space-3);font-size:var(--text-xs);color:var(--c-success)">
${r.fulfilled_at?.slice(0,10) || ''}</td>
</tr>`;
const thead = `<thead><tr>
${['Nutzer','Tarif','Nachricht','Datum','Aktion'].map(h =>
`<th style="padding:var(--space-2) var(--space-3);text-align:left;font-size:var(--text-xs);
color:var(--c-text-muted);font-weight:600;border-bottom:1px solid var(--c-border)">${h}</th>`
).join('')}</tr></thead>`;
el.innerHTML = `
<div class="card adm-table-card" style="margin-bottom:var(--space-4)">
<div class="by-card-section-header">Offene Anfragen (${pending.length})</div>
<div class="adm-table-scroll">
<table class="adm-table" style="width:100%;border-collapse:collapse">
${thead}
<tbody>
${pending.length
? pending.map(r => _row(r, true)).join('')
: `<tr><td colspan="5" style="padding:var(--space-4);text-align:center;color:var(--c-text-muted)">
Keine offenen Anfragen
</td></tr>`}
</tbody>
</table>
<div style="margin-bottom:var(--space-4)">
<div class="by-card-section-header" style="margin-bottom:var(--space-3)">
Offene Anfragen (${pending.length})
</div>
${pending.length
? pending.map(_pendingCard).join('')
: `<div class="card" style="padding:var(--space-4);text-align:center;color:var(--c-text-muted);font-size:var(--text-sm)">
Keine offenen Anfragen
</div>`}
</div>
${done.length ? `
<div class="card adm-table-card">
<div class="by-card-section-header">Erledigt (${done.length})</div>
<div class="adm-table-scroll">
<table class="adm-table" style="width:100%;border-collapse:collapse">
${thead}
<tbody>${done.map(r => _row(r, false)).join('')}</tbody>
<thead><tr>
${['Nutzer','Tarif','Freigegeben'].map(h =>
`<th style="padding:var(--space-2) var(--space-3);text-align:left;font-size:var(--text-xs);
color:var(--c-text-muted);font-weight:600;border-bottom:1px solid var(--c-border)">${h}</th>`
).join('')}
</tr></thead>
<tbody>${done.map(_doneRow).join('')}</tbody>
</table>
</div>
</div>` : ''}`;