UX enhancements on data views

This commit is contained in:
2026-05-26 17:07:18 +02:00
parent 9d783b60a9
commit ea3a423186
8 changed files with 558 additions and 43 deletions

View File

@ -1,5 +1,6 @@
import { apiGet, apiPost, apiDelete } from '../api.js';
import { getRole, getUser, showToast } from '../app.js';
import { isDevTestUsername, testDataRowClassForUser } from '../test-data.js';
// Roles an admin can create; supervisors can only create coaches
const CREATEABLE_ROLES = {
@ -10,6 +11,8 @@ const CREATEABLE_ROLES = {
let usersList = [];
let supervisorsList = [];
let callerRole = '';
let filterSearch = '';
let filterTestData = '';
export async function usersPage() {
callerRole = getRole();
@ -86,8 +89,19 @@ function renderUsers() {
{ label: 'Coaches', key: 'coach' },
];
container.innerHTML = groups.map(group => {
const users = byRole[group.key] || [];
container.innerHTML = `
<div class="card" style="margin-bottom:16px">
<div class="filter-bar">
<input type="search" id="userListSearch" class="filter-search" placeholder="Search username…" value="${esc(filterSearch)}">
<select id="userTestFilter">
<option value="">All users</option>
<option value="test" ${filterTestData === 'test' ? 'selected' : ''}>Test data only (dev_*)</option>
<option value="hide-test" ${filterTestData === 'hide-test' ? 'selected' : ''}>Hide test data</option>
</select>
</div>
</div>
` + groups.map(group => {
const users = filterUsers(byRole[group.key] || []);
if (!users.length) return '';
return `
<div class="card" style="margin-bottom:16px">
@ -111,11 +125,34 @@ function renderUsers() {
</div>`;
}).join('');
document.getElementById('userListSearch')?.addEventListener('input', (e) => {
filterSearch = e.target.value.trim();
renderUsers();
});
document.getElementById('userTestFilter')?.addEventListener('change', (e) => {
filterTestData = e.target.value;
renderUsers();
});
container.querySelectorAll('.delete-user-btn').forEach(btn => {
btn.addEventListener('click', () => deleteUser(btn.dataset.id, btn.dataset.name));
});
}
function filterUsers(users) {
let list = users;
if (filterSearch) {
const q = filterSearch.toLowerCase();
list = list.filter(u => (u.username || '').toLowerCase().includes(q));
}
if (filterTestData === 'test') {
list = list.filter(u => isDevTestUsername(u.username));
} else if (filterTestData === 'hide-test') {
list = list.filter(u => !isDevTestUsername(u.username));
}
return list;
}
function userRowHTML(u, myUsername) {
const isSelf = u.username === myUsername;
const detail = u.role === 'coach'
@ -134,7 +171,7 @@ function userRowHTML(u, myUsername) {
);
return `
<tr>
<tr class="${testDataRowClassForUser(u.username).trim()}">
<td>
<strong>${esc(u.username)}</strong>
${isSelf ? '<span class="badge badge-you">You</span>' : ''}