Files
loot-hunt/src/views/admin/dashboard.ejs
Mike Johnston 83e552bd07
All checks were successful
Build Images and Deploy / Update-PROD-Stack (push) Successful in 29s
add organizer role and features
2026-02-28 01:50:20 -05:00

93 lines
4.8 KiB
Plaintext

<%- include('../partials/header') %>
<div class="container">
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 1.5rem;">
<h1><%= typeof isAdmin !== 'undefined' && isAdmin ? 'Admin' : 'Organizer' %> Dashboard</h1>
<a href="/admin/hunts/new" class="btn btn-primary">+ New Hunt</a>
</div>
<% if (hunts.length === 0) { %>
<div class="card" style="text-align: center; padding: 3rem;">
<p style="color: var(--muted); font-size: 1.1rem;">You haven't created any hunts yet.</p>
<a href="/admin/hunts/new" class="btn btn-primary" style="margin-top: 1rem;">Create Your First Hunt</a>
</div>
<% } else { %>
<% hunts.forEach(hunt => { %>
<a href="/admin/hunts/<%= hunt.id %>" class="hunt-card">
<div class="hunt-info">
<h3><%= hunt.name %></h3>
<span class="meta"><%= hunt.short_name %> &middot; <%= hunt.package_count %> packages
<% if (hunt.expiry_date) { %> &middot; Expires: <%= new Date(hunt.expiry_date).toLocaleDateString() %><% } %>
</span>
</div>
<span class="badge">Manage</span>
</a>
<% }) %>
<% } %>
<% if (typeof isAdmin !== 'undefined' && isAdmin) { %>
<h2 style="margin-top: 2rem; margin-bottom: 1rem;">Password Reset</h2>
<div class="card">
<p style="color: var(--muted); font-size: 0.9rem; margin-bottom: 1rem;">Generate a one-time password reset link for a user. The link expires in 24 hours.</p>
<form method="POST" action="/admin/reset-password" style="display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: flex-end;">
<div class="form-group" style="margin-bottom: 0; flex: 1; min-width: 180px;">
<label>Username</label>
<select name="username" class="form-control" required>
<option value="">Select user...</option>
<% if (typeof users !== 'undefined' && users) { users.forEach(u => { %>
<option value="<%= u.username %>"><%= u.username %><%= u.is_admin ? ' (admin)' : u.is_organizer ? ' (organizer)' : '' %></option>
<% }); } %>
</select>
</div>
<button type="submit" class="btn btn-primary">Generate Reset Link</button>
</form>
<% if (typeof resetUrl !== 'undefined' && resetUrl) { %>
<div style="margin-top: 1rem; padding: 1rem; background: var(--body-bg); border-radius: 8px;">
<p style="margin: 0 0 0.5rem; font-weight: 600;">Reset link for <strong><%= resetUsername %></strong>:</p>
<div style="display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap;">
<input type="text" class="form-control" value="<%= resetUrl %>" id="reset-url" readonly style="font-family: monospace; font-size: 0.85rem; flex: 1; min-width: 200px;">
<button class="btn btn-sm btn-outline" onclick="document.getElementById('reset-url').select();navigator.clipboard.writeText(document.getElementById('reset-url').value).then(()=>{this.textContent='Copied!';setTimeout(()=>this.textContent='Copy',1500)})">Copy</button>
</div>
<p style="font-size: 0.8rem; color: var(--muted); margin: 0.5rem 0 0;">Send this link to the user. It expires in 24 hours and can only be used once.</p>
</div>
<% } %>
</div>
<h2 style="margin-top: 2rem; margin-bottom: 1rem;">Manage Roles</h2>
<div class="card">
<p style="color: var(--muted); font-size: 0.9rem; margin-bottom: 1rem;">Grant or revoke the <strong>Organizer</strong> role. Organizers can create hunts and manage their own hunts only.</p>
<div class="table-wrapper">
<table>
<thead>
<tr><th>User</th><th>Role</th><th>Action</th></tr>
</thead>
<tbody>
<% if (typeof users !== 'undefined' && users) { users.filter(u => !u.is_admin).forEach(u => { %>
<tr>
<td><a href="/player/<%= u.username %>"><%= u.username %></a></td>
<td><%= u.is_organizer ? 'Organizer' : 'Player' %></td>
<td>
<% if (u.is_organizer) { %>
<form method="POST" action="/admin/users/<%= u.id %>/role" style="margin:0;">
<input type="hidden" name="role" value="player">
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Remove organizer role from <%= u.username %>?')">Remove Organizer</button>
</form>
<% } else { %>
<form method="POST" action="/admin/users/<%= u.id %>/role" style="margin:0;">
<input type="hidden" name="role" value="organizer">
<button type="submit" class="btn btn-sm btn-success">Make Organizer</button>
</form>
<% } %>
</td>
</tr>
<% }); } %>
</tbody>
</table>
</div>
</div>
<% } %>
</div>
<%- include('../partials/footer') %>