feat: organizer application system
Build Images and Deploy / Update-PROD-Stack (push) Successful in 30s
Build Images and Deploy / Update-PROD-Stack (push) Successful in 30s
This commit is contained in:
+34
-2
@@ -1,7 +1,7 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const { requireAuth } = require('../middleware/auth');
|
||||
const { Hunts, Packages, Scans, Users } = require('../models');
|
||||
const { Hunts, Packages, Scans, Users, OrganizerApplications } = require('../models');
|
||||
|
||||
// ─── Hunt profile ─────────────────────────────────────────
|
||||
router.get('/hunt/:shortName', (req, res) => {
|
||||
@@ -94,6 +94,7 @@ router.get('/player/:username', (req, res) => {
|
||||
const totalPlayers = Users.getTotalPlayerCount();
|
||||
|
||||
const isOwnProfile = req.session && req.session.userId === user.id;
|
||||
const pendingApplication = isOwnProfile ? OrganizerApplications.findByUser(user.id) : null;
|
||||
|
||||
res.render('player/profile', {
|
||||
title: `${user.username}'s Profile`,
|
||||
@@ -102,7 +103,8 @@ router.get('/player/:username', (req, res) => {
|
||||
huntBreakdown,
|
||||
rank,
|
||||
totalPlayers,
|
||||
isOwnProfile
|
||||
isOwnProfile,
|
||||
pendingApplication
|
||||
});
|
||||
});
|
||||
|
||||
@@ -155,6 +157,36 @@ router.post('/player/:username/display-name', requireAuth, (req, res) => {
|
||||
res.redirect(`/player/${user.username}`);
|
||||
});
|
||||
|
||||
// ─── Apply to become organizer ────────────────────────────
|
||||
router.post('/player/:username/apply-organizer', requireAuth, (req, res) => {
|
||||
const user = Users.findByUsername(req.params.username);
|
||||
if (!user || user.id !== req.session.userId) {
|
||||
return res.status(403).render('error', { title: 'Forbidden', message: 'You can only submit your own application.' });
|
||||
}
|
||||
if (user.is_organizer || user.is_admin) {
|
||||
req.session.flash = { type: 'info', message: 'You already have organizer access.' };
|
||||
return res.redirect(`/player/${user.username}`);
|
||||
}
|
||||
if (OrganizerApplications.findByUser(user.id)) {
|
||||
req.session.flash = { type: 'info', message: 'You already have a pending application.' };
|
||||
return res.redirect(`/player/${user.username}`);
|
||||
}
|
||||
|
||||
const reason = (req.body.reason || '').trim();
|
||||
if (!reason || reason.length < 10) {
|
||||
req.session.flash = { type: 'danger', message: 'Please provide a reason (at least 10 characters).' };
|
||||
return res.redirect(`/player/${user.username}`);
|
||||
}
|
||||
if (reason.length > 1000) {
|
||||
req.session.flash = { type: 'danger', message: 'Reason is too long (max 1000 characters).' };
|
||||
return res.redirect(`/player/${user.username}`);
|
||||
}
|
||||
|
||||
OrganizerApplications.submit(user.id, reason);
|
||||
req.session.flash = { type: 'success', message: 'Your organizer application has been submitted!' };
|
||||
res.redirect(`/player/${user.username}`);
|
||||
});
|
||||
|
||||
// ─── Delete own account ───────────────────────────────────
|
||||
router.post('/player/:username/delete', requireAuth, (req, res) => {
|
||||
const user = Users.findByUsername(req.params.username);
|
||||
|
||||
Reference in New Issue
Block a user