Files
Htmx/templates/auth/users.html
T

106 lines
7.9 KiB
HTML

{% extends "base.html" %}
{% import "components/macros.html" as ui %}
{% block title %}User Management - Stick{% endblock %}
{% block content %}
<div class="grow py-12 px-4 sm:px-6 lg:px-8 max-w-5xl mx-auto w-full">
<!-- Header -->
<div class="flex flex-col md:flex-row md:items-center md:justify-between mb-8 pb-6 border-b border-slate-900 gap-4">
<div>
<h1 class="text-3xl font-extrabold text-slate-100 tracking-tight">User Management</h1>
<p class="text-slate-400 text-sm mt-1">Manage system access, toggle roles, and provision credentials</p>
</div>
<div class="flex items-center gap-3">
<a href="/auth/audit" class="inline-flex items-center justify-center rounded-xl text-xs font-bold transition-all px-4 py-2.5 bg-indigo-650 hover:bg-indigo-600 text-white shadow-md shadow-indigo-600/10">
View Audit Logs
</a>
<a href="/auth/register" class="inline-flex items-center justify-center rounded-xl text-xs font-bold transition-all px-4 py-2.5 bg-emerald-600 hover:bg-emerald-500 text-white shadow-md shadow-emerald-500/10">
Register New User
</a>
<span class="text-xs font-semibold px-3 py-1.5 rounded-xl bg-slate-900 border border-slate-800 text-slate-300">
Total Users: {{ users.len() }}
</span>
</div>
</div>
<!-- User List -->
{{ ui::table_container_open(id="users-table", has_top_scroll=false, max_height="auto") }}
<table class="min-w-full divide-y divide-slate-800 text-left text-sm text-slate-300 relative">
<thead class="shadow-[0_1px_0_0_rgba(255,255,255,0.05)]">
<tr class="text-xs font-bold text-slate-400 uppercase tracking-wider">
<th scope="col" class="sticky top-0 z-10 px-6 py-4 bg-[#162031]">Username</th>
<th scope="col" class="sticky top-0 z-10 px-6 py-4 bg-[#162031]">Role</th>
<th scope="col" class="sticky top-0 z-10 px-6 py-4 bg-[#162031]">Created At</th>
<th scope="col" class="sticky top-0 z-10 px-6 py-4 bg-[#162031] text-right">Actions</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-800">
{% if users.is_empty() %}
<tr>
<td colspan="4" class="px-6 py-8 text-center text-slate-500">
No registered users found.
</td>
</tr>
{% else %}
{% for user_item in users %}
<tr class="hover:bg-[#1e293b]/20 transition duration-150">
<td class="px-6 py-4.5 whitespace-nowrap font-medium text-slate-200">
{{ user_item.username }}
{% if user_item.username == username %}
<span class="ml-2 text-[10px] bg-sky-500/10 text-sky-400 border border-sky-500/20 px-2 py-0.5 rounded-full font-bold">You</span>
{% endif %}
</td>
<td class="px-6 py-4.5 whitespace-nowrap">
{% if user_item.is_admin %}
<span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-bold bg-emerald-500/10 text-emerald-400 border border-emerald-500/20">
Administrator
</span>
{% else %}
<span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium bg-slate-900 text-slate-400 border border-slate-800">
Standard User
</span>
{% endif %}
</td>
<td class="px-6 py-4.5 whitespace-nowrap text-slate-400 text-xs">
{{ user_item.created_at.format("%B %d, %Y at %H:%M UTC") }}
</td>
<td class="px-6 py-4.5 whitespace-nowrap text-right text-xs font-medium">
<div class="flex items-center justify-end gap-2">
<a href="/auth/users/{{ user_item.id.unwrap().to_hex() }}/edit" class="p-2 rounded-lg bg-sky-500/10 hover:bg-sky-500/20 border border-sky-500/20 text-sky-400 transition" title="Edit User">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-4 h-4">
<path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.83 20.013a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10" />
</svg>
</a>
{% if user_item.username != username %}
<form action="/auth/users/{{ user_item.id.unwrap().to_hex() }}/delete" method="post" class="inline" onsubmit="return confirm('Are you sure you want to permanently delete user \'{{ user_item.username }}\'?');">
<button type="submit" class="p-2 rounded-lg bg-rose-500/10 hover:bg-rose-500/20 border border-rose-500/20 text-rose-400 transition" title="Delete User">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-4 h-4">
<path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.34 9m-4.72 0-.34-9m9.03-3.03-.58 17.5A2.25 2.25 0 0 1 17.11 21H6.9a2.25 2.25 0 0 1-2.18-2.13L4.1 6.57m3.07-7.94h14.98m-14.98 0A1.75 1.75 0 0 1 7.25 1.5H16.75A1.75 1.75 0 0 1 18 3m-12 0h12" />
</svg>
</button>
</form>
{% else %}
<span class="p-2 rounded-lg opacity-30 text-slate-600 border border-slate-800 cursor-not-allowed" title="You cannot delete yourself">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-4 h-4">
<path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.34 9m-4.72 0-.34-9m9.03-3.03-.58 17.5A2.25 2.25 0 0 1 17.11 21H6.9a2.25 2.25 0 0 1-2.18-2.13L4.1 6.57m3.07-7.94h14.98m-14.98 0A1.75 1.75 0 0 1 7.25 1.5H16.75A1.75 1.75 0 0 1 18 3m-12 0h12" />
</svg>
</span>
{% endif %}
</div>
</td>
</tr>
{% endfor %}
{% endif %}
</tbody>
</table>
{{ ui::table_container_close(id="users-table", has_top_scroll=false) }}
<div class="mt-6 text-center text-sm text-slate-400">
<a href="/auth/password" class="font-medium text-sky-400 hover:underline">← Back to Account Settings</a>
</div>
</div>
{% endblock %}