feat: add HTMX endpoint stubs for all admin modules
Templates use HTMX to load data dynamically via AJAX Added 5 endpoint stubs (will implement with real data): 1. /admin/servers/matrix - Server status grid 2. /admin/players/table - Player list 3. /admin/grace/list - Grace period users (WORKING with real DB query) 4. /admin/audit/feed - Recent webhook events 5. /admin/roles/mismatches - Discord role diagnostics Grace endpoint COMPLETE - queries PostgreSQL and shows users in grace period Others return 'Coming Soon' placeholders TESTING: - Grace Period page should show real data - Other pages show 'Coming Soon' instead of loading spinner Signed-off-by: Claude (Chronicler #57) <claude@firefrostgaming.com>
This commit is contained in:
@@ -136,3 +136,104 @@ router.post('/mappings', isAdmin, express.json(), (req, res) => {
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
||||
// ==========================================
|
||||
// HTMX API ENDPOINTS (Return HTML fragments)
|
||||
// ==========================================
|
||||
|
||||
// Servers Matrix Endpoint
|
||||
router.get('/servers/matrix', isAdmin, async (req, res) => {
|
||||
// TODO: Query server status from Pterodactyl API
|
||||
res.send(`
|
||||
<div class="p-6 text-center text-gray-500 dark:text-gray-400">
|
||||
<p class="text-lg font-medium mb-2">Server Matrix Coming Soon</p>
|
||||
<p class="text-sm">Will display real-time status of all 13 Minecraft servers</p>
|
||||
</div>
|
||||
`);
|
||||
});
|
||||
|
||||
// Players Table Endpoint
|
||||
router.get('/players/table', isAdmin, async (req, res) => {
|
||||
// TODO: Query subscriptions with Discord user data
|
||||
res.send(`
|
||||
<div class="p-6 text-center text-gray-500 dark:text-gray-400">
|
||||
<p class="text-lg font-medium mb-2">Player Database Coming Soon</p>
|
||||
<p class="text-sm">Will display all subscribers with search/filter</p>
|
||||
</div>
|
||||
`);
|
||||
});
|
||||
|
||||
// Grace Period List Endpoint
|
||||
router.get('/grace/list', isAdmin, async (req, res) => {
|
||||
const { Pool } = require('pg');
|
||||
const pool = new Pool({
|
||||
host: '127.0.0.1',
|
||||
user: 'arbiter',
|
||||
password: 'FireFrost2026!Arbiter',
|
||||
database: 'arbiter_db'
|
||||
});
|
||||
|
||||
try {
|
||||
const result = await pool.query(`
|
||||
SELECT discord_id, tier_level, grace_period_started_at, grace_period_ends_at
|
||||
FROM subscriptions
|
||||
WHERE status = 'grace_period'
|
||||
ORDER BY grace_period_ends_at ASC
|
||||
`);
|
||||
|
||||
if (result.rows.length === 0) {
|
||||
res.send(`
|
||||
<div class="p-8 text-center text-gray-500 dark:text-gray-400">
|
||||
<p class="text-lg">✅ No users in grace period!</p>
|
||||
<p class="text-sm mt-2">All subscribers are current on payments</p>
|
||||
</div>
|
||||
`);
|
||||
} else {
|
||||
let html = '<div class="divide-y divide-gray-200 dark:divide-gray-700">';
|
||||
result.rows.forEach(row => {
|
||||
const endsAt = new Date(row.grace_period_ends_at);
|
||||
const hoursLeft = Math.round((endsAt - new Date()) / (1000 * 60 * 60));
|
||||
html += `
|
||||
<div class="p-4 hover:bg-gray-50 dark:hover:bg-gray-800">
|
||||
<div class="flex justify-between items-center">
|
||||
<div>
|
||||
<div class="font-medium dark:text-white">Discord ID: ${row.discord_id}</div>
|
||||
<div class="text-sm text-gray-500">Tier ${row.tier_level}</div>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<div class="text-yellow-600 dark:text-yellow-400 font-medium">${hoursLeft}h remaining</div>
|
||||
<div class="text-xs text-gray-500">${endsAt.toLocaleString()}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
html += '</div>';
|
||||
res.send(html);
|
||||
}
|
||||
} catch (error) {
|
||||
res.send(`<div class="p-6 text-red-600">Error: ${error.message}</div>`);
|
||||
}
|
||||
});
|
||||
|
||||
// Audit Log Feed Endpoint
|
||||
router.get('/audit/feed', isAdmin, async (req, res) => {
|
||||
// TODO: Query webhook_events_processed table
|
||||
res.send(`
|
||||
<div class="p-6 text-center text-gray-500 dark:text-gray-400">
|
||||
<p class="text-lg font-medium mb-2">Audit Log Coming Soon</p>
|
||||
<p class="text-sm">Will display recent webhook events and role changes</p>
|
||||
</div>
|
||||
`);
|
||||
});
|
||||
|
||||
// Role Mismatches Diagnostic Endpoint
|
||||
router.get('/roles/mismatches', isAdmin, async (req, res) => {
|
||||
// TODO: Compare Discord roles vs database subscriptions
|
||||
res.send(`
|
||||
<div class="p-6 text-center text-gray-500 dark:text-gray-400">
|
||||
<p class="text-lg font-medium mb-2">Role Diagnostics Coming Soon</p>
|
||||
<p class="text-sm">Will scan Discord server and compare with database</p>
|
||||
</div>
|
||||
`);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user