diff --git a/admin.html b/admin.html index 0b13b80..f6a02b0 100644 --- a/admin.html +++ b/admin.html @@ -159,6 +159,14 @@ .cat-info { flex: 1; font-family: Arial, sans-serif; font-size: 0.88rem; color: #3b2a1a; } .cat-info span { color: #7a5c3e; font-size: 0.78rem; } + /* User list */ + .user-table { width: 100%; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 0.88rem; } + .user-table th { text-align: left; color: #7a5c3e; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px; padding: 6px 10px; border-bottom: 2px solid #e8d5c0; } + .user-table td { padding: 9px 10px; border-bottom: 1px solid #f0e8dc; color: #3b2a1a; } + .user-table tr:last-child td { border-bottom: none; } + .user-table .user-nick { font-weight: bold; color: #7c4a1e; } + .user-table .badge { display: inline-block; background: #f0e8dc; color: #7a5c3e; padding: 2px 8px; border-radius: 10px; font-size: 0.78rem; } + .empty-state { text-align: center; color: #7a5c3e; font-style: italic; padding: 20px 0; } .toast { @@ -340,9 +348,15 @@ - +
+ +
+

Käyttäjät

+

Ladataan...

+
+

Kategoriat

@@ -454,17 +468,20 @@ } async function loadAdminData() { - const [postsData, catsData] = await Promise.all([ + const [postsData, catsData, usersData] = await Promise.all([ apiGet('posts'), apiGet('categories'), + apiGet('admin_users'), ]); ADMIN.posts = postsData.posts || []; ADMIN.categories = catsData.categories || []; + ADMIN.users = usersData.users || []; document.getElementById('backLink').textContent = at('back'); document.getElementById('saveBtn').textContent = at('save'); populateCategorySelect(); renderCatList(); renderPostList(); + renderUserList(); } // =========================== @@ -803,6 +820,28 @@ }); } + // =========================== + // USER LIST + // =========================== + function renderUserList() { + const users = ADMIN.users || []; + const el = document.getElementById('userList'); + if (!users.length) { el.innerHTML = '

Ei rekisteröityneitä käyttäjiä.

'; return; } + el.innerHTML = ` + + + ${users.map(u => ` + + + + + + + `).join('')} + +
NimimerkkiSähköpostiJulkaisutTykkäyksetLiittynyt
${u.nickname}${u.email || ''}${u.postCount}${u.likes}${u.created || '–'}
`; + } + // =========================== // TOAST // =========================== diff --git a/api.php b/api.php index 00dc218..bfc0737 100644 --- a/api.php +++ b/api.php @@ -843,6 +843,28 @@ switch ($action) { case 'admin_check': ok(['loggedIn' => isAdmin()]); + case 'admin_users': + if (!isAdmin()) err('Unauthorized', 403); + $users = readData('users.json', []); + $posts = getOrInitPosts(); + $result = []; + foreach ($users as $u) { + $nick = mb_strtolower($u['nickname']); + $postCount = 0; + foreach ($posts as $p) { + if (mb_strtolower($p['author'] ?? '') === $nick) $postCount++; + } + $result[] = [ + 'id' => $u['id'], + 'nickname' => $u['nickname'], + 'email' => $u['email'] ?? '', + 'created' => $u['created'] ?? '', + 'likes' => count($u['likes'] ?? []), + 'postCount' => $postCount, + ]; + } + ok(['users' => $result]); + // ─── Käyttäjätunnukset ───────────────────────────────────── case 'user_register': $nickname = trim($body['nickname'] ?? ''); diff --git a/script.js b/script.js index 651b609..13e1655 100644 --- a/script.js +++ b/script.js @@ -213,7 +213,7 @@ function renderCards() {
${getCategoryLabel(p.category)}

${p.title}

- ${p.author ? `

✍️ ${p.author}

` : ''} + ${p.author ? `

✍️ ${p.author}${p.submittedBy?.validated ? ' ✔ Vahvistettu' : (p.submittedBy?.guestCode ? ` #${p.submittedBy.guestCode}` : '')}

` : ''}

${p.desc || ''}

${metaRow}
@@ -326,7 +326,7 @@ async function openPost(id) {