From cc55bd66a5eb486b2ce386e10e49a41e97cfd18d Mon Sep 17 00:00:00 2001 From: Daniel Michelberger Date: Wed, 2 Sep 2026 12:55:33 +0200 Subject: [PATCH] feat: Ein Dialog fuer die Zeitnahme, keine Aktionen mehr inline Start und Stopp laufen ausschliesslich ueber TimeDialog. Der fuehrt immer beide Angaben - Fahrer und Run -, auch wenn eine davon aus dem Kontext vorbelegt ist: Beim Stoppen an der Strecke soll kein Zweifel bleiben, wen man gerade erwischt. DNF fragt nach, bevor es schreibt. Eine Zeit ohne Wertung laesst sich nicht zurueckholen, ein Fehlgriff waere also endgueltig. Tabelle und Toast-Leiste zeigen damit nur noch an; ihre Knoepfe oeffnen den Dialog mit passender Vorbelegung. Der alte Stopp-Dialog und der Fahrerlisten-Start entfallen - beides waren Ein-Tipp-Aktionen und damit genau das, was hier nicht mehr sein soll. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_014dh9W1i7aLSdPYJzQPid5o --- .../lib/components/RunningTimesToast.svelte | 38 ++- .../src/lib/components/StopTimeDialog.svelte | 84 ------- frontend/src/lib/components/TimeDialog.svelte | 219 ++++++++++++++++++ .../events/[id]/runs/[runId]/+page.svelte | 154 ++---------- 4 files changed, 264 insertions(+), 231 deletions(-) delete mode 100644 frontend/src/lib/components/StopTimeDialog.svelte create mode 100644 frontend/src/lib/components/TimeDialog.svelte diff --git a/frontend/src/lib/components/RunningTimesToast.svelte b/frontend/src/lib/components/RunningTimesToast.svelte index 43e6168..84095ed 100644 --- a/frontend/src/lib/components/RunningTimesToast.svelte +++ b/frontend/src/lib/components/RunningTimesToast.svelte @@ -7,15 +7,17 @@ * * Bei mehreren Zeiten zeigt die Leiste eingeklappt nur die Zahl und die * längste Zeit; ausgeklappt alle. Bei genau einer entfällt das Klappen. + * + * Gestoppt wird auch von hier aus nicht direkt: Der Knopf öffnet den + * Zeit-Dialog mit Fahrer und Run vorbelegt. */ import { getTimeContext } from '$lib/stores/times.svelte' import { fullName, getRiderContext } from '$lib/stores/riders.svelte' import { getRunContext } from '$lib/stores/runs.svelte' import { ticker } from '$lib/stores/ticker.svelte' - import StopTimeDialog from './StopTimeDialog.svelte' - import { Badge } from '@/components/ui/badge' + import TimeDialog from './TimeDialog.svelte' import { Button } from '@/components/ui/button' - import { ChevronDown, ChevronUp, Square } from 'lucide-svelte' + import { ChevronDown, ChevronUp, Timer } from 'lucide-svelte' const times = getTimeContext() const riders = getRiderContext() @@ -26,7 +28,22 @@ const single = $derived(running.length === 1) let expanded = $state(false) - let stopTimeId = $state(null) + + // Vorbelegung für den Zeit-Dialog + let timeDialog = $state(false) + let dialogEvent = $state('') + let dialogRider = $state(null) + let dialogRun = $state(null) + + function openTimeDialog(riderId: string | undefined, runId: string | undefined) { + const run = runId ? runs.getById(runId) : undefined + if (!run?.event) return + + dialogEvent = run.event + dialogRider = riderId ?? null + dialogRun = run.id + timeDialog = true + } // Eine einzelne Zeit steht immer offen da; bei mehreren entscheidet der // Nutzer. Fällt die Anzahl wieder auf eine, ist der Zustand egal. @@ -111,10 +128,10 @@ variant="ghost" size="icon" class="shrink-0" - title="Zeit stoppen" - onclick={() => (stopTimeId = t.id)} + title="Zeit erfassen" + onclick={() => openTimeDialog(t.rider, t.run)} > - + {/each} @@ -123,5 +140,10 @@ - + {/if} diff --git a/frontend/src/lib/components/StopTimeDialog.svelte b/frontend/src/lib/components/StopTimeDialog.svelte deleted file mode 100644 index 8483908..0000000 --- a/frontend/src/lib/components/StopTimeDialog.svelte +++ /dev/null @@ -1,84 +0,0 @@ - - - { - if (!open) close() - }} -> - - - Zeit stoppen? - - {#if time} - #{rider?.number ?? '—'} {rider ? fullName(rider) : 'Unbekannter Fahrer'} - {:else} - Diese Zeit läuft nicht mehr. - {/if} - - - - {#if time} -

- {time.formattedTime} -

- {/if} - - {#if error} -

{error}

- {/if} - - - - - - -
-
diff --git a/frontend/src/lib/components/TimeDialog.svelte b/frontend/src/lib/components/TimeDialog.svelte new file mode 100644 index 0000000..8733c21 --- /dev/null +++ b/frontend/src/lib/components/TimeDialog.svelte @@ -0,0 +1,219 @@ + + + + + + Zeit erfassen + + Fahrer und Run wählen — je nach Stand wird gestartet oder gestoppt. + + + +
+
+ + + {riderLabel} + + {#each eventRiders as r (r.id)} + + #{r.number || '—'} {fullName(r)} + + {/each} + + + {#if eventRiders.length === 0} +

Für dieses Event gibt es noch keine Fahrer.

+ {/if} +
+ +
+ + + {runLabel} + + {#each eventRuns as r (r.id)} + {r.description || 'Run'} + {/each} + + + {#if eventRuns.length === 0} +

Für dieses Event gibt es noch keine Runs.

+ {/if} +
+ + {#if active} +
+

läuft seit

+

{active.formattedTime}

+
+ {:else if existing} +

+ Für diese Paarung gibt es bereits eine Zeit ({existing.formattedTime}). + Ein neuer Start legt eine zweite an. +

+ {/if} + + {#if error} +

{error}

+ {/if} +
+ + {#if confirmDnf} + +
+

+ + + Wirklich als DNF werten? Die Zeit wird beendet und taucht in keiner + Rangliste auf. + +

+
+ + +
+
+ {:else} + + + {#if active} + + + {:else} + + {/if} + + {/if} +
+
diff --git a/frontend/src/routes/dashboard/events/[id]/runs/[runId]/+page.svelte b/frontend/src/routes/dashboard/events/[id]/runs/[runId]/+page.svelte index a16545a..3149afc 100644 --- a/frontend/src/routes/dashboard/events/[id]/runs/[runId]/+page.svelte +++ b/frontend/src/routes/dashboard/events/[id]/runs/[runId]/+page.svelte @@ -1,8 +1,9 @@