feat: admin can reroll codes if needed
Build Images and Deploy / Update-PROD-Stack (push) Successful in 45s
Build Images and Deploy / Update-PROD-Stack (push) Successful in 45s
This commit is contained in:
@@ -337,6 +337,18 @@ const Packages = {
|
|||||||
return db.prepare('SELECT * FROM packages WHERE id = ?').get(id);
|
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) {
|
findByHuntAndCode(shortName, uniqueCode) {
|
||||||
return db.prepare(`
|
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
|
SELECT p.*, h.name as hunt_name, h.short_name as hunt_short_name, h.id as hunt_id, h.expiry_date
|
||||||
|
|||||||
@@ -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) ───────────────────────
|
// ─── Manage user roles (admin only) ───────────────────────
|
||||||
router.post('/users/:id/role', requireAdmin, (req, res) => {
|
router.post('/users/:id/role', requireAdmin, (req, res) => {
|
||||||
const userId = parseInt(req.params.id, 10);
|
const userId = parseInt(req.params.id, 10);
|
||||||
|
|||||||
@@ -123,6 +123,9 @@
|
|||||||
<div style="display: flex; gap: 0.4rem; align-items: stretch;">
|
<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>
|
<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>
|
<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.')">🎲</button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user