diff --git a/assets/js/rover_map_hook.ts b/assets/js/rover_map_hook.ts index 194a172f..6a15f0c3 100644 --- a/assets/js/rover_map_hook.ts +++ b/assets/js/rover_map_hook.ts @@ -29,6 +29,7 @@ interface RoverMapHook extends ViewHook { homeLon: number driveRadiusKm: number visibilityHandler: (() => void) | null + driveRadiusListener: ((e: Event) => void) | null renderStations(this: RoverMapHook): void buildQualityLayer(this: RoverMapHook): L.GridLayer @@ -174,6 +175,12 @@ export const RoverMap: Partial = { } document.addEventListener("visibilitychange", this.visibilityHandler) + this.driveRadiusListener = (e: Event) => { + const km = (e as CustomEvent<{ km: number }>).detail?.km + if (typeof km === "number") this.setDriveRadius(km) + } + window.addEventListener("rover:drive-radius", this.driveRadiusListener) + this.handleEvent("stations_updated", ({ stations }: { stations: Station[] }) => { this.stations = stations this.renderStations() @@ -229,6 +236,10 @@ export const RoverMap: Partial = { document.removeEventListener("visibilitychange", this.visibilityHandler) this.visibilityHandler = null } + if (this.driveRadiusListener) { + window.removeEventListener("rover:drive-radius", this.driveRadiusListener) + this.driveRadiusListener = null + } }, setDriveRadius(this: RoverMapHook, km: number) { diff --git a/assets/js/rover_slider_hook.ts b/assets/js/rover_slider_hook.ts index 4e55445f..1368cb4d 100644 --- a/assets/js/rover_slider_hook.ts +++ b/assets/js/rover_slider_hook.ts @@ -3,9 +3,12 @@ import type { ViewHook } from "phoenix_live_view" interface RoverSliderHook extends ViewHook { labelEl: HTMLElement | null formatter: (v: number) => string + format: string inputHandler: () => void } +const AVG_SPEED_KMH = 65.0 + const formatters: Record string> = { forecast: (v) => `+${v}h`, drive: (v) => { @@ -17,14 +20,18 @@ const formatters: Record string> = { export const RoverSlider: Partial = { mounted(this: RoverSliderHook) { const labelId = this.el.dataset.labelId || "" - const format = this.el.dataset.format || "forecast" + this.format = this.el.dataset.format || "forecast" - this.formatter = formatters[format] || formatters.forecast + this.formatter = formatters[this.format] || formatters.forecast this.labelEl = document.getElementById(labelId) this.inputHandler = () => { - if (this.labelEl) { - this.labelEl.textContent = this.formatter(Number((this.el as HTMLInputElement).value)) + const value = Number((this.el as HTMLInputElement).value) + if (this.labelEl) this.labelEl.textContent = this.formatter(value) + + if (this.format === "drive") { + const km = (value * AVG_SPEED_KMH) / 60.0 + window.dispatchEvent(new CustomEvent("rover:drive-radius", { detail: { km } })) } }