aboutsummaryrefslogtreecommitdiff
path: root/web/frontend/ride-detail.ts
diff options
context:
space:
mode:
authorMartin Kagamino Lehoux <martin@lehoux.net>2026-09-06 12:38:16 +0200
committerMartin Kagamino Lehoux <martin@lehoux.net>2026-09-06 12:38:16 +0200
commit8e0c55230ef59869bda1ca19ca8697b447d57698 (patch)
tree2d5941e95949c43a84326cc5d10db8e4fab72a64 /web/frontend/ride-detail.ts
parent28a7c9f281c16d1928b37dd1afdfe8399b7a03f8 (diff)
Preview: analyze a raw GPX or FIT file without persisting it
Diffstat (limited to 'web/frontend/ride-detail.ts')
-rw-r--r--web/frontend/ride-detail.ts28
1 files changed, 28 insertions, 0 deletions
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<HTMLFormElement>("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<HTMLElement>("[data-climb-item]");
+ form.addEventListener("submit", async (event) => {
+ event.preventDefault();
+ const submitButton = form.querySelector<HTMLButtonElement>("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<HTMLElement>(".climb-status");
+ if (status) status.textContent = message;
+ else window.alert(message);
+ });
+ }
};
mountRideDetail();