feat: add achievements system to awards with mode filter support

Implement achievements milestone feature for awards with configurable
levels (Silver, Gold, Platinum, etc.) that track progress beyond the
base award target. Achievements display earned badges and progress bar
toward next level.

Backend:
- Add calculateAchievementProgress() helper in awards.service.js
- Include achievements field in getAllAwards() and getAwardById()
- Add achievements validation in awards-admin.service.js
- Update PUT endpoint validation schema to include achievements field

Frontend:
- Add achievements section to award detail page with gold badges
- Add reactive achievement progress calculation that respects mode filter
- Add achievements tab to admin create/edit pages with full CRUD

Award Definitions:
- Add achievements to DXCC (100/200/300/500)
- Add achievements to DLD (50/100/200/300)
- Add achievements to WAS (30/40/50)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-01-23 12:42:32 +01:00
parent 239963ed89
commit b09e2b3ea2
9 changed files with 844 additions and 20 deletions

View File

@@ -4,16 +4,37 @@
"description": "Deutschland Diplom - Confirm 100 unique DOKs on different bands/modes",
"caption": "Contact and confirm stations with 100 unique DOKs (DARC Ortsverband Kennung) on different band/mode combinations. Each unique DOK on a unique band/mode counts as one point. Only DCL-confirmed QSOs with valid DOK information count toward this award.",
"category": "darc",
"modeGroups": {
"Digi-Modes": ["FT8", "FT4", "MFSK", "PSK31", "RTTY"],
"Classic Digi-Modes": ["PSK31", "RTTY"],
"Mixed-Mode w/o WSJT-Modes": ["PSK31", "RTTY", "AM", "SSB", "FM", "CW"],
"Phone-Modes": ["AM", "SSB", "FM"]
},
"rules": {
"type": "dok",
"target": 100,
"confirmationType": "dcl",
"displayField": "darcDok"
"displayField": "darcDok",
"stations": []
},
"modeGroups": {
"Digi-Modes": [
"FT4",
"FT8",
"MFSK",
"PSK31",
"RTTY"
],
"Classic Digi-Modes": [
"PSK31",
"RTTY"
],
"Mixed-Mode w/o WSJT-Modes": [
"AM",
"CW",
"FM",
"PSK31",
"RTTY",
"SSB"
],
"Phone-Modes": [
"AM",
"FM",
"SSB"
]
}
}
}

View File

@@ -4,17 +4,71 @@
"description": "Confirm 100 DXCC entities on HF bands",
"caption": "Contact and confirm 100 different DXCC entities on HF bands (160m-10m). Only HF band QSOs count toward this award. QSOs are confirmed when LoTW QSL is received.",
"category": "dxcc",
"modeGroups": {
"Digi-Modes": ["FT8", "FT4", "MFSK", "PSK31", "RTTY", "JT65", "JT9"],
"Classic Digi-Modes": ["PSK31", "RTTY", "JT65", "JT9"],
"Mixed-Mode w/o WSJT-Modes": ["PSK31", "RTTY", "AM", "SSB", "FM", "CW"],
"Phone-Modes": ["AM", "SSB", "FM"]
},
"rules": {
"type": "entity",
"entityType": "dxcc",
"target": 100,
"displayField": "entity",
"allowed_bands": ["160m", "80m", "60m", "40m", "30m", "20m", "17m", "15m", "12m", "10m"]
}
}
"allowed_bands": [
"160m",
"80m",
"60m",
"40m",
"30m",
"20m",
"17m",
"15m",
"12m",
"10m"
],
"stations": []
},
"modeGroups": {
"Digi-Modes": [
"FT4",
"FT8",
"JT65",
"JT9",
"MFSK",
"PSK31",
"RTTY"
],
"Classic Digi-Modes": [
"JT65",
"JT9",
"PSK31",
"RTTY"
],
"Mixed-Mode w/o WSJT-Modes": [
"AM",
"CW",
"FM",
"PSK31",
"RTTY",
"SSB"
],
"Phone-Modes": [
"AM",
"FM",
"SSB"
]
},
"achievements": [
{
"name": "Silver",
"threshold": 100
},
{
"name": "Gold",
"threshold": 200
},
{
"name": "Platinum",
"threshold": 300
},
{
"name": "All",
"threshold": 341
}
]
}

View File

@@ -4,6 +4,9 @@
"description": "Confirm all 50 US states",
"caption": "Contact and confirm all 50 US states. Only QSOs with stations located in United States states count toward this award. QSOs are confirmed when LoTW QSL is received.",
"category": "was",
"achievements": [
{ "name": "WAS Award", "threshold": 50 }
],
"rules": {
"type": "entity",
"entityType": "state",