diff --git a/frontend/components/round-detail.tsx b/frontend/components/round-detail.tsx index f4db87b..34222df 100644 --- a/frontend/components/round-detail.tsx +++ b/frontend/components/round-detail.tsx @@ -2044,6 +2044,13 @@ function ScoringWizard({ // en egen, enklere side-veiviser uten dette steget). Samme // urlBase-konstruksjon dekker begge hull-eiertyper (ADR-048 sine speilede // deltaker-/side-endepunkt), ingen egen gren trengs utover selve URL-en. +type ShotRecord = { + id: string + club: string + distance_meters: number + shared_round_message_id: string | null +} + function ShotMeasurementEntry({ roundId, holeNumber, @@ -2064,21 +2071,36 @@ function ShotMeasurementEntry({ const urlBase = `/rounds/${roundId}/${owner.kind === "participant" ? "participants" : "sides"}/${owner.id}/holes/${holeNumber}/shots` const [open, setOpen] = useState(false) - const [count, setCount] = useState(0) + // Brukertilbakemelding 2026-08-08: "jeg burde jo se slaget selv, selv om + // det ikke er delt" -- merkelappen viste tidligere KUN et antall, ingen + // måte å se kølle/avstand for egne, private slag. Lagrer nå hele listen + // (ikke bare .length), viser den i en utvidbar liste, med sletting av et + // feilmålt slag. + const [shots, setShots] = useState([]) + const [listOpen, setListOpen] = useState(false) const [submitting, setSubmitting] = useState(false) const [submitError, setSubmitError] = useState(null) + const [shareError, setShareError] = useState(null) useEffect(() => { let cancelled = false fetch(urlBase, { credentials: "include" }) .then((res) => (res.ok ? res.json() : [])) - .then((shots: unknown[]) => { - if (!cancelled) setCount(shots.length) + .then((data: ShotRecord[]) => { + if (!cancelled) setShots(data) }) .catch(() => {}) return () => { cancelled = true } }, [urlBase]) + const count = shots.length + + async function deleteShot(shotId: string) { + const res = await fetch(`/rounds/${roundId}/shots/${shotId}`, { method: "DELETE", credentials: "include" }) + if (res.ok) { + setShots((prev) => prev.filter((s) => s.id !== shotId)) + } + } // Reell bug funnet 2026-08-08: en avvist innsending (f.eks. serverens // distance_meters > 0-sjekk, hvis brukeren rakk å målt begge punkter for @@ -2125,16 +2147,29 @@ function ShotMeasurementEntry({ setSubmitError(message) return } - const shot = await res.json() + let shot = await res.json() + setShareError(null) if (result.share) { - await fetch(`/rounds/${roundId}/shots/${shot.id}/share`, { + const shareRes = await fetch(`/rounds/${roundId}/shots/${shot.id}/share`, { method: "POST", headers: { "Content-Type": "application/json" }, credentials: "include", body: JSON.stringify({ body: result.shareText }), }) + // Reell bug funnet 2026-08-08: dette svaret ble aldri sjekket -- en + // avvist deling (f.eks. en driftsfeil) lot slaget lagres som om alt + // gikk bra, ingen feilmelding, ingen melding i feeden. Slaget er + // uansett lagret på dette tidspunktet -- arket lukkes derfor alltid + // her (unngår en duplikat-innsending ved gjentatt "Lagre slag"), og + // en mislykket deling vises separat ved siden av merkelappen i + // stedet for å holde arket åpent. + if (shareRes.ok) { + shot = await shareRes.json() + } else { + setShareError("Slaget ble lagret, men delingen feilet. Prøv å dele på nytt fra listen.") + } } - setCount((n) => n + 1) + setShots((prev) => [...prev, shot]) setOpen(false) } catch { setSubmitError("Klarte ikke å nå serveren. Sjekk tilkoblingen og prøv igjen.") @@ -2143,29 +2178,103 @@ function ShotMeasurementEntry({ } } - if (readOnly) return null + async function shareExisting(shot: ShotRecord) { + const res = await fetch(`/rounds/${roundId}/shots/${shot.id}/share`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + credentials: "include", + body: JSON.stringify({ body: `⛳ ${shot.club}, ${shot.distance_meters} m – hull ${holeNumber}` }), + }) + if (res.ok) { + const updated = await res.json() + setShots((prev) => prev.map((s) => (s.id === shot.id ? updated : s))) + setShareError(null) + } else { + setShareError("Delingen feilet. Prøv igjen om litt.") + } + } - const text = count > 0 ? `${label ? `${label}: ` : ""}${count} slag målt` : `${label ? `${label}: ` : ""}Mål et slag` + if (readOnly) { + // Skrivebeskyttet visning (fullført/eldre runde): fortsatt nyttig å SE + // egne målte slag, bare uten å kunne måle/dele/slette nye. + if (count === 0) return null + return ( +
+ + {listOpen && } +
+ ) + } + + const addLabel = label ? `${label}: Mål et slag` : "Mål et slag" return ( - <> - )} - > -