feat: admin can reroll codes if needed
All checks were successful
Build Images and Deploy / Update-PROD-Stack (push) Successful in 45s

This commit is contained in:
2026-04-01 15:57:49 -04:00
parent 0211b84565
commit 9e83173277
3 changed files with 29 additions and 0 deletions

View File

@@ -337,6 +337,18 @@ const Packages = {
return db.prepare('SELECT * FROM packages WHERE id = ?').get(id);
},
rerollCode(packageId) {
const pkg = this.findById(packageId);
if (!pkg) return null;
const existing = db.prepare('SELECT unique_code FROM packages WHERE hunt_id = ?').all(pkg.hunt_id).map(r => r.unique_code);
let code;
do {
code = generateCode(5);
} while (existing.includes(code));
db.prepare('UPDATE packages SET unique_code = ? WHERE id = ?').run(code, packageId);
return code;
},
findByHuntAndCode(shortName, uniqueCode) {
return db.prepare(`
SELECT p.*, h.name as hunt_name, h.short_name as hunt_short_name, h.id as hunt_id, h.expiry_date

View File

@@ -149,6 +149,20 @@ router.get('/hunts/:id/pdf', requireHuntAccess, async (req, res) => {
}
});
// ─── Reroll package code ──────────────────────────────────
router.post('/hunts/:id/packages/:pkgId/reroll', requireHuntAccess, (req, res) => {
const hunt = req.hunt;
const pkgId = parseInt(req.params.pkgId, 10);
const pkg = Packages.findById(pkgId);
if (!pkg || pkg.hunt_id !== hunt.id) {
req.session.flash = { type: 'danger', message: 'Package not found.' };
return res.redirect(`/admin/hunts/${hunt.id}`);
}
const newCode = Packages.rerollCode(pkgId);
req.session.flash = { type: 'success', message: `Package #${pkg.card_number} code changed from ${pkg.unique_code} to ${newCode}.` };
res.redirect(`/admin/hunts/${hunt.id}`);
});
// ─── Manage user roles (admin only) ───────────────────────
router.post('/users/:id/role', requireAdmin, (req, res) => {
const userId = parseInt(req.params.id, 10);

View File

@@ -123,6 +123,9 @@
<div style="display: flex; gap: 0.4rem; align-items: stretch;">
<a href="/hunt/<%= hunt.short_name %>/<%= pkg.card_number %>" class="btn btn-sm btn-outline">View</a>
<button class="btn btn-sm btn-outline" onclick="navigator.clipboard.writeText('<%= baseUrl %>/loot/<%= hunt.short_name %>/<%= pkg.unique_code %>').then(()=>{this.textContent='Copied!';setTimeout(()=>this.textContent='Copy Link',1500)})">Copy Link</button>
<form method="POST" action="/admin/hunts/<%= hunt.id %>/packages/<%= pkg.id %>/reroll" style="margin:0;">
<button type="submit" class="btn btn-sm btn-outline" title="Reroll code" onclick="return confirm('Reroll code for package #<%= pkg.card_number %>? The old code will stop working.')">&#x1F3B2;</button>
</form>
</div>
</td>
</tr>