UI redesign step 7 (Benutzer-Verwaltung): Stitch style
- Header gets the same title/subtitle pair + primary "Neuer Benutzer" pill on the right that the other tabs use, with the person_add glyph. - Table shell now matches Übersicht/Provisionen: bordered white card, surface-container-high header band with label-caps column titles, zebra rows, hover highlight. - "Admin" column renders a verified_user icon for admins and a long dash otherwise instead of the previous green check. The username column shows a small primary "Sie" badge for the logged-in user. - Action column collapses to two icon-only buttons (edit / delete); delete is rendered with reduced opacity and disabled when it is the logged-in user's row. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
968cb183f2
commit
ff0d7398db
2 files changed
+61
-26
No files matched your search
+29
-11
@@ -3979,29 +3979,47 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
async function loadUsers() {
|
||||
const tbody = document.getElementById('usersTableBody');
|
||||
if (!tbody) return;
|
||||
tbody.innerHTML = '<tr><td colspan="5" style="text-align:center; color:#666;">Lade...</td></tr>';
|
||||
tbody.innerHTML = '<tr><td colspan="5" class="px-md py-lg text-center text-body-sm text-on-surface-variant">Lade…</td></tr>';
|
||||
try {
|
||||
const users = await apiRequest('/api/users');
|
||||
tbody.innerHTML = '';
|
||||
if (!users.length) {
|
||||
tbody.innerHTML = '<tr><td colspan="5" style="text-align:center; color:#666;">Keine Benutzer</td></tr>';
|
||||
tbody.innerHTML = '<tr><td colspan="5" class="px-md py-lg text-center text-body-sm text-on-surface-variant">Keine Benutzer</td></tr>';
|
||||
return;
|
||||
}
|
||||
users.forEach(u => {
|
||||
const tr = document.createElement('tr');
|
||||
const isSelf = currentUser && currentUser.username === u.username;
|
||||
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 = `
|
||||
<td>${escapeHtml(u.username)}${isSelf ? ' <small style="color:#3498db;">(Sie)</small>' : ''}</td>
|
||||
<td>${escapeHtml(u.displayName || '')}</td>
|
||||
<td>${u.isAdmin ? '<span style="color:#27ae60;">✓</span>' : ''}</td>
|
||||
<td>${escapeHtml(formatDateTime(u.createdAt))}</td>
|
||||
<td>
|
||||
<button data-user-action="edit" data-uuid="${escapeHtml(u.uuid)}" class="btn-success" style="margin-right:5px;">Bearbeiten</button>
|
||||
<button data-user-action="delete" data-uuid="${escapeHtml(u.uuid)}" data-username="${escapeHtml(u.username)}" class="btn-danger" ${isSelf ? 'disabled title="Eigener Account kann nicht gelöscht werden"' : ''}>Löschen</button>
|
||||
<td class="px-md py-xs">
|
||||
<span class="font-semibold text-on-background">${escapeHtml(u.username)}</span>
|
||||
${isSelf ? '<span class="ml-xs text-label-caps text-primary">Sie</span>' : ''}
|
||||
</td>
|
||||
<td class="px-md py-xs text-on-surface">${escapeHtml(u.displayName || '–')}</td>
|
||||
<td class="px-md py-xs text-center">
|
||||
${u.isAdmin
|
||||
? '<span class="material-symbols-outlined text-primary text-[20px]" title="Administrator">verified_user</span>'
|
||||
: '<span class="text-on-surface-variant">—</span>'}
|
||||
</td>
|
||||
<td class="px-md py-xs font-label-numeric text-label-numeric text-on-surface-variant">${escapeHtml(formatDateTime(u.createdAt))}</td>
|
||||
<td class="px-md py-xs">
|
||||
<div class="flex items-center justify-center gap-sm">
|
||||
<button data-user-action="edit" data-uuid="${escapeHtml(u.uuid)}" title="Bearbeiten"
|
||||
class="text-outline hover:text-primary transition-colors">
|
||||
<span class="material-symbols-outlined text-[18px]">edit</span>
|
||||
</button>
|
||||
<button data-user-action="delete" data-uuid="${escapeHtml(u.uuid)}" data-username="${escapeHtml(u.username)}" title="${isSelf ? 'Eigener Account kann nicht gelöscht werden' : 'Löschen'}"
|
||||
class="text-outline hover:text-error transition-colors ${isSelf ? 'opacity-40 cursor-not-allowed' : ''}"
|
||||
${isSelf ? 'disabled' : ''}>
|
||||
<span class="material-symbols-outlined text-[18px]">delete</span>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
`;
|
||||
tr.querySelectorAll('button[data-user-action]').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
if (btn.disabled) return;
|
||||
const action = btn.dataset.userAction;
|
||||
const uuid = btn.dataset.uuid;
|
||||
if (action === 'edit') openUserModal(u);
|
||||
@@ -4011,7 +4029,7 @@ async function loadUsers() {
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
} catch (err) {
|
||||
tbody.innerHTML = '<tr><td colspan="5" style="text-align:center; color:#c0392b;">Fehler beim Laden</td></tr>';
|
||||
tbody.innerHTML = '<tr><td colspan="5" class="px-md py-lg text-center text-body-sm text-error">Fehler beim Laden</td></tr>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user