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
+8 -3
View File
@@ -50,6 +50,7 @@ async def _find_active_passage(
async def log_passage(
db: aiosqlite.Connection,
*,
race_id: Optional[str] = None,
profile_id: Optional[str],
bib_number: Optional[str],
station: str,
@@ -112,14 +113,14 @@ async def log_passage(
await db.execute(
"""
INSERT INTO passages (
passage_id, profile_id, bib_number, station,
passage_id, race_id, profile_id, bib_number, station,
timestamp_utc, gps_lat, gps_lon, gps_alt,
confidence, id_method, source_image,
needs_review, review_note
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
passage_id, profile_id, bib_number, station,
passage_id, race_id, profile_id, bib_number, station,
timestamp_utc.isoformat(), gps_lat, gps_lon, gps_alt,
confidence, id_method, source_image,
int(needs_review), review_note,
@@ -153,12 +154,16 @@ async def get_passage_images(db: aiosqlite.Connection, passage_id: str) -> list[
async def get_passages(
db: aiosqlite.Connection,
race_id: Optional[str] = None,
profile_id: Optional[str] = None,
station: Optional[str] = None,
needs_review: Optional[bool] = None,
) -> list[dict]:
clauses = []
params = []
if race_id is not None:
clauses.append("p.race_id = ?")
params.append(race_id)
if profile_id is not None:
clauses.append("p.profile_id = ?")
params.append(profile_id)