feat: Add tier change functionality to Players module
WHAT WAS DONE: - Added tier change dropdown in Players Actions column - Created POST route /admin/players/:discord_id/tier - Implemented database tier update with MRR recalculation - Added audit log entry for tier changes - htmx reload of table after tier change WHY: - Trinity needs ability to manually adjust subscriber tiers - Customer service: upgrades, downgrades, support cases - Accountability via audit logging - Last missing feature in Players module HOW IT WORKS: - Dropdown shows all tiers (except Admin 1000) - On change, htmx POSTs to tier change endpoint - Route updates subscriptions table (tier_level + mrr_value) - Audit log records who made the change - After success, table reloads to show updated tier FEATURES: - Real-time tier changes without page refresh - Automatic MRR recalculation - Audit trail for compliance - Skips Admin tier (reserved for Trinity) - Shows current tier as selected in dropdown IMPACT: - Trinity can now manage all subscriber tiers manually - Critical for customer support scenarios - Completes Players module functionality - Ready for soft launch customer service TODO: - Discord role sync integration (marked in code) - This requires bot API endpoint to be built FILES MODIFIED: - services/arbiter-3.0/src/views/admin/players/_table_body.ejs - services/arbiter-3.0/src/routes/admin/players.js TESTED: - Not yet deployed - needs testing on Command Center Signed-off-by: Claude (Chronicler #52) <claude@firefrostgaming.com>
This commit is contained in:
@@ -32,4 +32,41 @@ router.get('/table', async (req, res) => {
|
||||
res.render('admin/players/_table_body', { players, TIER_INFO, page, search });
|
||||
});
|
||||
|
||||
// POST endpoint for tier changes
|
||||
router.post('/:discord_id/tier', async (req, res) => {
|
||||
const { discord_id } = req.params;
|
||||
const { tier_level } = req.body;
|
||||
|
||||
try {
|
||||
// Validate tier exists
|
||||
if (!TIER_INFO[tier_level]) {
|
||||
return res.status(400).send('Invalid tier');
|
||||
}
|
||||
|
||||
// Update tier in database
|
||||
const tierInfo = TIER_INFO[tier_level];
|
||||
await db.query(`
|
||||
UPDATE subscriptions
|
||||
SET tier_level = $1, mrr_value = $2, updated_at = NOW()
|
||||
WHERE discord_id = $3
|
||||
`, [tier_level, tierInfo.price, discord_id]);
|
||||
|
||||
// TODO: Sync Discord roles via bot
|
||||
// This will be implemented when Discord bot integration is ready
|
||||
|
||||
// Create audit log entry
|
||||
await db.query(`
|
||||
INSERT INTO admin_audit_log (admin_discord_id, action, target_discord_id, details)
|
||||
VALUES ($1, 'tier_change', $2, $3)
|
||||
`, [req.user.id, discord_id, `Changed tier to ${tierInfo.name}`]);
|
||||
|
||||
// Return success (htmx will handle UI update)
|
||||
res.send('OK');
|
||||
|
||||
} catch (error) {
|
||||
console.error('Tier change error:', error);
|
||||
res.status(500).send('Error updating tier');
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
||||
@@ -28,7 +28,20 @@
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-right">
|
||||
<span class="text-gray-400 text-sm">(Coming Soon)</span>
|
||||
<form hx-post="/admin/players/<%= player.discord_id %>/tier"
|
||||
hx-trigger="change from:select"
|
||||
hx-on::after-request="htmx.ajax('GET', '/admin/players/table', {target:'#player-table-body', swap:'innerHTML'})">
|
||||
<select class="bg-gray-50 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded px-2 py-1 text-sm"
|
||||
name="tier_level">
|
||||
<option value="">Change Tier...</option>
|
||||
<% Object.keys(TIER_INFO).sort((a, b) => parseInt(b) - parseInt(a)).forEach(tierLevel => {
|
||||
const tierData = TIER_INFO[tierLevel];
|
||||
if (tierLevel == 1000) return; // Skip Admin tier
|
||||
%>
|
||||
<option value="<%= tierLevel %>" <%= player.tier_level == tierLevel ? 'selected' : '' %>><%= tierData.name %> ($<%= tierData.price %>)</option>
|
||||
<% }); %>
|
||||
</select>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<% }) %>
|
||||
|
||||
Reference in New Issue
Block a user