(`${base}/classes`),
+ ])
+ if (!mountedRef.current) return
+ const mine = tournamentsData?.find((t) => t.id === tournamentId) ?? null
+ if (!mine) {
+ setError("Fant ikke turneringen.")
+ return
+ }
+ setTournament(mine)
+ setParticipants(participantsData ?? [])
+ setRounds(roundsData ?? [])
+ setCourses(coursesData ?? [])
+ setClasses(classesData ?? [])
+ } catch {
+ if (mountedRef.current) setError("Klarte ikke å laste turneringen. Prøv å laste siden på nytt.")
+ } finally {
+ if (mountedRef.current) setLoading(false)
+ }
+ }
+
+ useEffect(() => {
+ loadTournamentData()
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [organizationId, tournamentId, base])
+
+ // Stille bakgrunns-refresh (ingen loading-spinner -- setLoading(false)
+ // er allerede satt) når fanen/vinduet blir synlig igjen, ELLER siden
+ // gjenopprettes fra bfcache (pageshow med persisted=true er det
+ // spesifikke signalet for akkurat det tilfellet).
+ useEffect(() => {
+ function handleVisible() {
+ if (document.visibilityState === "visible") loadTournamentData()
+ }
+ function handlePageShow(e: PageTransitionEvent) {
+ if (e.persisted) loadTournamentData()
+ }
+ document.addEventListener("visibilitychange", handleVisible)
+ window.addEventListener("pageshow", handlePageShow)
+ return () => {
+ document.removeEventListener("visibilitychange", handleVisible)
+ window.removeEventListener("pageshow", handlePageShow)
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [organizationId, tournamentId, base])
async function updateStatus(newStatus: TournamentStatus) {
@@ -1218,6 +1254,26 @@ function SetupTab({
}
}, [organizationId])
+ // Samme "frisk opp ved synlig igjen"-behov som gjelder hele siden
+ // (se IndividualTournamentDetail sin tilsvarende lytter) -- "Rediger i
+ // spillerpoolen" er en full sidenavigasjon, og bfcache kan gjenopprette
+ // denne komponenten i utdatert tilstand ved tilbake-navigasjon.
+ useEffect(() => {
+ function handleVisible() {
+ if (document.visibilityState === "visible") refreshPool()
+ }
+ function handlePageShow(e: PageTransitionEvent) {
+ if (e.persisted) refreshPool()
+ }
+ document.addEventListener("visibilitychange", handleVisible)
+ window.addEventListener("pageshow", handlePageShow)
+ return () => {
+ document.removeEventListener("visibilitychange", handleVisible)
+ window.removeEventListener("pageshow", handlePageShow)
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [organizationId])
+
// Rundedeltakelse-tabellen (ADR-093, "Spillere"-steget) -- lat innlasting,
// KUN når steget faktisk vises (ikke eagerly ved sideinnlasting), av alle
// rundenes rundedeltakere OG alle unike baners utslag samtidig. Flere
diff --git a/frontend/components/org-player-roster-panel.tsx b/frontend/components/org-player-roster-panel.tsx
index dbda015..5865c65 100644
--- a/frontend/components/org-player-roster-panel.tsx
+++ b/frontend/components/org-player-roster-panel.tsx
@@ -200,7 +200,10 @@ export function OrgPlayerRosterPanel({
if (field === "gender") {
patch.gender = toBackendGender(row.gender)
} else if (field === "handicap_index") {
- patch.handicap_index = row.handicap_index.trim() ? Number(row.handicap_index) : null
+ // Komma-desimal skal fungere likt som punktum (2026-08-19).
+ patch.handicap_index = row.handicap_index.trim()
+ ? Number(row.handicap_index.replace(",", "."))
+ : null
} else if (field === "birth_date") {
patch.birth_date = row.birth_date.trim() || null
} else {
@@ -232,7 +235,7 @@ export function OrgPlayerRosterPanel({
body: JSON.stringify({
display_name: row.display_name.trim(),
email: row.email.trim() || null,
- handicap_index: row.handicap_index.trim() ? Number(row.handicap_index) : null,
+ handicap_index: row.handicap_index.trim() ? Number(row.handicap_index.replace(",", ".")) : null,
gender: toBackendGender(row.gender),
birth_date: row.birth_date.trim() || null,
mobile: row.mobile.trim() || null,
diff --git a/frontend/components/player-import-panel.tsx b/frontend/components/player-import-panel.tsx
index 2c4e57f..2df541d 100644
--- a/frontend/components/player-import-panel.tsx
+++ b/frontend/components/player-import-panel.tsx
@@ -299,7 +299,7 @@ export function PlayerImportPanel({
data: {
display_name: r.display_name.trim(),
email: r.email.trim() || null,
- handicap_index: r.handicap_index.trim() ? Number(r.handicap_index) : null,
+ handicap_index: r.handicap_index.trim() ? Number(r.handicap_index.replace(",", ".")) : null,
gender: toBackendGender(r.gender),
birth_date: r.birth_date.trim() || null,
mobile: r.mobile.trim() || null,
diff --git a/frontend/components/player-import-view.tsx b/frontend/components/player-import-view.tsx
index c8de7cb..6cc98b0 100644
--- a/frontend/components/player-import-view.tsx
+++ b/frontend/components/player-import-view.tsx
@@ -496,7 +496,15 @@ function EditTable({
- {rows.map((row, rowIndex) => (
+ {rows.map((row, rowIndex) => {
+ // Annenhver rad-bakgrunn (2026-08-19, bruker: "hvit og lys
+ // grå") -- ren pekepinn for å lese på tvers av en rad i en
+ // bred tabell, samme rutenett-linjer som ellers. Den sticky
+ // første cellen må få SAMME bakgrunn som resten av raden
+ // (ikke alltid bg-card), ellers ser den frakoblet ut fra
+ // stripen bak den ved sidescroll.
+ const rowBg = rowIndex % 2 === 1 ? "bg-muted/40" : "bg-card"
+ return (
{editFields.map((field, i) => (
- |
+ |
{field === "gender" ? (
|
- ))}
+ )
+ })}
diff --git a/frontend/components/round-detail.tsx b/frontend/components/round-detail.tsx
index 89c06ba..66251b9 100644
--- a/frontend/components/round-detail.tsx
+++ b/frontend/components/round-detail.tsx
@@ -4748,9 +4748,11 @@ function AddGuestForm({
setHcp(e.target.value)}
placeholder="F.eks. 18"
@@ -5392,9 +5394,9 @@ function EditParticipantPanel({
setHcp(e.target.value)}
placeholder="F.eks. 18"
diff --git a/frontend/components/tournament-players-table.tsx b/frontend/components/tournament-players-table.tsx
index 431d424..cfce296 100644
--- a/frontend/components/tournament-players-table.tsx
+++ b/frontend/components/tournament-players-table.tsx
@@ -361,7 +361,9 @@ function PlayerRow({
onSetHandicap(player.participantId, null)
return
}
- const num = Number(trimmed)
+ // Komma-desimal (norsk skrivemåte, "12,4") skal fungere likt som punktum
+ // -- 2026-08-19, bruker: "jeg vil at det skal være irrelevant".
+ const num = Number(trimmed.replace(",", "."))
if (Number.isNaN(num)) {
// Revert bad input back to the last known good value.
setHcpDraft(player.handicapSnapshot === null ? "" : String(player.handicapSnapshot))
@@ -382,11 +384,11 @@ function PlayerRow({
setHcpDraft(e.target.value)}
|