Add race and station management
Build & Deploy / build-and-deploy (push) Successful in 2m18s

- races table: name, date, description, is_active
- stations table: ordered checkpoints with GPS per race
- New /api/races and /api/races/{id}/stations endpoints
- Upload now requires race + station selection; uses station GPS
  so images without GPS EXIF are accepted
- passages filtered by active race throughout
- RacePage: create races, manage stations (add/edit/delete checkpoints)
- Navbar shows active race name
- Start and finish stations created automatically per race

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-21 09:44:45 +01:00
parent 3dcf979e6f
commit 5393e85a74
15 changed files with 841 additions and 139 deletions
+7 -6
View File
@@ -7,21 +7,22 @@ from typing import Optional
import aiosqlite
async def get_results(db: aiosqlite.Connection) -> list[dict]:
async def get_results(db: aiosqlite.Connection, race_id: Optional[str] = None) -> list[dict]:
"""
Hent totalresultat for alle utøvere som har passert start og mål.
Returnerer sortert liste med split-tider.
"""
# Hent alle bekreftede passeringer gruppert per utøver
async with db.execute("""
race_filter = "AND p.race_id = ?" if race_id else ""
params = [race_id] if race_id else []
async with db.execute(f"""
SELECT p.profile_id, p.bib_number, a.name, a.club,
p.station, p.timestamp_utc
FROM passages p
LEFT JOIN athletes a ON a.profile_id = p.profile_id
WHERE p.needs_review = 0 AND p.profile_id IS NOT NULL
WHERE p.needs_review = 0 AND p.profile_id IS NOT NULL {race_filter}
ORDER BY p.profile_id, p.timestamp_utc
""") as cur:
""", params) as cur:
rows = await cur.fetchall()
# Grupper per utøver