feat: add configurable mode groups to award detail view
Add per-award configurable mode groups for filtering multiple modes together in the award detail view. Mode groups are displayed with visual separators in the mode filter dropdown. Backend changes: - Add modeGroups to getAllAwards() return mapping - Add getAwardById() function to fetch single award definition - Add GET /api/awards/:awardId endpoint Frontend changes: - Fetch award definition separately to get modeGroups - Update availableModes to include mode groups with separator - Update filteredEntities logic to handle mode groups - Update groupDataForTable() and applyFilter() for mode groups - Disable separator option in dropdown Award definitions: - DXCC: Add Digi-Modes, Classic Digi-Modes, Mixed-Mode w/o WSJT-Modes, Phone-Modes groups - DLD: Add same mode groups (adjusted for available modes) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -40,6 +40,7 @@ import {
|
||||
} from './services/job-queue.service.js';
|
||||
import {
|
||||
getAllAwards,
|
||||
getAwardById,
|
||||
getAwardProgressDetails,
|
||||
getAwardEntityBreakdown,
|
||||
} from './services/awards.service.js';
|
||||
@@ -913,6 +914,42 @@ const app = new Elysia()
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* GET /api/awards/:awardId
|
||||
* Get a single award by ID (requires authentication)
|
||||
*/
|
||||
.get('/api/awards/:awardId', async ({ user, params, set }) => {
|
||||
if (!user) {
|
||||
set.status = 401;
|
||||
return { success: false, error: 'Unauthorized' };
|
||||
}
|
||||
|
||||
try {
|
||||
const { awardId } = params;
|
||||
const award = getAwardById(awardId);
|
||||
|
||||
if (!award) {
|
||||
set.status = 404;
|
||||
return {
|
||||
success: false,
|
||||
error: 'Award not found',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
award,
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Error fetching award', { error: error.message });
|
||||
set.status = 500;
|
||||
return {
|
||||
success: false,
|
||||
error: 'Failed to fetch award',
|
||||
};
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* GET /api/awards/:awardId/progress
|
||||
* Get award progress for user (requires authentication)
|
||||
|
||||
@@ -66,9 +66,34 @@ export async function getAllAwards() {
|
||||
caption: def.caption,
|
||||
category: def.category,
|
||||
rules: def.rules,
|
||||
modeGroups: def.modeGroups || null,
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single award by ID
|
||||
* @param {string} awardId - Award ID
|
||||
* @returns {Object|null} Award definition or null if not found
|
||||
*/
|
||||
export function getAwardById(awardId) {
|
||||
const definitions = loadAwardDefinitions();
|
||||
const award = definitions.find((def) => def.id === awardId);
|
||||
|
||||
if (!award) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
id: award.id,
|
||||
name: award.name,
|
||||
description: award.description,
|
||||
caption: award.caption,
|
||||
category: award.category,
|
||||
rules: award.rules,
|
||||
modeGroups: award.modeGroups || null,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate award progress for a user
|
||||
* @param {number} userId - User ID
|
||||
|
||||
Reference in New Issue
Block a user