From 8e0c55230ef59869bda1ca19ca8697b447d57698 Mon Sep 17 00:00:00 2001 From: Martin Kagamino Lehoux Date: Sun, 6 Sep 2026 12:38:16 +0200 Subject: Preview: analyze a raw GPX or FIT file without persisting it --- web/frontend/ride-detail.ts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'web/frontend') diff --git a/web/frontend/ride-detail.ts b/web/frontend/ride-detail.ts index b8d2898..dcebbe4 100644 --- a/web/frontend/ride-detail.ts +++ b/web/frontend/ride-detail.ts @@ -146,6 +146,34 @@ export const mountRideDetail = (): void => { }); if (climbItems.length > 0) updateClimbFocus(0, false); else profileCanvas.redraw(); + mountPreviewSave([...document.querySelectorAll("form[data-preview-form]")]); +}; + +// Preview ride forms save official climbs via fetch so the un-persisted preview stays on screen. +const mountPreviewSave = (forms: HTMLFormElement[]): void => { + for (const form of forms) { + if (!form.dataset.previewForm) continue; + const item = form.closest("[data-climb-item]"); + form.addEventListener("submit", async (event) => { + event.preventDefault(); + const submitButton = form.querySelector("button[type=submit]"); + if (submitButton) submitButton.disabled = true; + let message: string; + try { + const response = await fetch(form.action, { method: "POST", body: new FormData(form) }); + const payload = (await response.json()) as { ok?: boolean; name?: string; error?: string }; + message = + response.ok && payload.ok && payload.name + ? `Official climb “${payload.name}” saved. Re-upload the file to see it matched.` + : `Saving the official climb failed${payload.error ? `: ${payload.error}` : "."}`; + } catch { + message = "Saving the official climb failed."; + } + const status = item?.querySelector(".climb-status"); + if (status) status.textContent = message; + else window.alert(message); + }); + } }; mountRideDetail(); -- cgit v1.3