UX: Upgrade-Tab — Cards statt Tabelle, Freischalten-Button immer sichtbar (SW by-v942)
This commit is contained in:
parent
6762efa04e
commit
9da8665aca
4 changed files with 49 additions and 39 deletions
|
|
@ -406,7 +406,7 @@ async def serve_media(path: str, request: _Request):
|
||||||
raise _HE(404, "Nicht gefunden.")
|
raise _HE(404, "Nicht gefunden.")
|
||||||
return _media_response(filepath)
|
return _media_response(filepath)
|
||||||
|
|
||||||
APP_VER = "941" # muss mit APP_VER in app.js übereinstimmen
|
APP_VER = "942" # muss mit APP_VER in app.js übereinstimmen
|
||||||
|
|
||||||
@app.get("/.well-known/assetlinks.json")
|
@app.get("/.well-known/assetlinks.json")
|
||||||
async def assetlinks():
|
async def assetlinks():
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
Router, State-Management, Navigation, Initialisierung.
|
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 APP_VERSION = '1.5.1'; // ← semantische Version, wird bei make release gesetzt
|
||||||
const IS_STAGING = location.hostname === 'staging.banyaro.app';
|
const IS_STAGING = location.hostname === 'staging.banyaro.app';
|
||||||
// Cache-Bust-Parameter nach Update-Reload sofort entfernen
|
// Cache-Bust-Parameter nach Update-Reload sofort entfernen
|
||||||
|
|
|
||||||
|
|
@ -3519,55 +3519,65 @@ window.Page_admin = (() => {
|
||||||
const pending = rows.filter(r => !r.fulfilled_at);
|
const pending = rows.filter(r => !r.fulfilled_at);
|
||||||
const done = 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>
|
<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>
|
<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)">${tierBadge(r.tier)}</td>
|
||||||
<td style="padding:var(--space-2) var(--space-3);font-size:var(--text-xs);color:var(--c-text-muted)">
|
<td style="padding:var(--space-2) var(--space-3);font-size:var(--text-xs);color:var(--c-success)">
|
||||||
${r.message ? _esc(r.message) : '—'}</td>
|
✓ ${r.fulfilled_at?.slice(0,10) || ''}</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>
|
|
||||||
</tr>`;
|
</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 = `
|
el.innerHTML = `
|
||||||
<div class="card adm-table-card" style="margin-bottom:var(--space-4)">
|
<div style="margin-bottom:var(--space-4)">
|
||||||
<div class="by-card-section-header">Offene Anfragen (${pending.length})</div>
|
<div class="by-card-section-header" style="margin-bottom:var(--space-3)">
|
||||||
<div class="adm-table-scroll">
|
Offene Anfragen (${pending.length})
|
||||||
<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>
|
</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>
|
</div>
|
||||||
${done.length ? `
|
${done.length ? `
|
||||||
<div class="card adm-table-card">
|
<div class="card adm-table-card">
|
||||||
<div class="by-card-section-header">Erledigt (${done.length})</div>
|
<div class="by-card-section-header">Erledigt (${done.length})</div>
|
||||||
<div class="adm-table-scroll">
|
<div class="adm-table-scroll">
|
||||||
<table class="adm-table" style="width:100%;border-collapse:collapse">
|
<table class="adm-table" style="width:100%;border-collapse:collapse">
|
||||||
${thead}
|
<thead><tr>
|
||||||
<tbody>${done.map(r => _row(r, false)).join('')}</tbody>
|
${['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>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>` : ''}`;
|
</div>` : ''}`;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
Offline-Cache + Push Notifications + Tile-Cache
|
Offline-Cache + Push Notifications + Tile-Cache
|
||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
const CACHE_VERSION = 'by-v941';
|
const CACHE_VERSION = 'by-v942';
|
||||||
const CACHE_STATIC = `${CACHE_VERSION}-static`;
|
const CACHE_STATIC = `${CACHE_VERSION}-static`;
|
||||||
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten
|
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten
|
||||||
const CACHE_API = 'ban-yaro-api-v1'; // API-Response-Cache
|
const CACHE_API = 'ban-yaro-api-v1'; // API-Response-Cache
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue