feat(rover): live slider labels via RoverSlider hook for forecast hour + drive time
This commit is contained in:
parent
db1539086b
commit
10fcc764f6
3 changed files with 59 additions and 3 deletions
|
|
@ -20,6 +20,7 @@ import {ElevationProfile} from "./elevation_profile_hook"
|
|||
import {WeatherMap} from "./weather_map_hook"
|
||||
import {LocateMe, CopyLink} from "./locate_me_hook"
|
||||
import {RoverMap} from "./rover_map_hook"
|
||||
import {RoverSlider} from "./rover_slider_hook"
|
||||
import {BeaconMap} from "./beacon_map_hook"
|
||||
import {BeaconsListMap} from "./beacons_list_map_hook"
|
||||
|
||||
|
|
@ -311,7 +312,7 @@ const csrfToken = document.querySelector("meta[name='csrf-token']")!.getAttribut
|
|||
const liveSocket = new LiveSocket("/live", Socket, {
|
||||
longPollFallbackMs: 2500,
|
||||
params: initLiveStash({_csrf_token: csrfToken}),
|
||||
hooks: {...colocatedHooks, PropagationMap, PathForecast, UtcClock, ContactMap, ContactsMap, ElevationProfile, WeatherMap, LocateMe, CopyLink, RoverMap, BeaconMap, BeaconsListMap, CommaNumber, ImportConfetti, EmeGlobe, Skewt},
|
||||
hooks: {...colocatedHooks, PropagationMap, PathForecast, UtcClock, ContactMap, ContactsMap, ElevationProfile, WeatherMap, LocateMe, CopyLink, RoverMap, RoverSlider, BeaconMap, BeaconsListMap, CommaNumber, ImportConfetti, EmeGlobe, Skewt},
|
||||
})
|
||||
|
||||
// live_table rows are dead on their own — wire up whole-row clicks to
|
||||
|
|
|
|||
42
assets/js/rover_slider_hook.ts
Normal file
42
assets/js/rover_slider_hook.ts
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import type { ViewHook } from "phoenix_live_view"
|
||||
|
||||
interface RoverSliderHook extends ViewHook {
|
||||
labelEl: HTMLElement | null
|
||||
formatter: (v: number) => string
|
||||
inputHandler: () => void
|
||||
}
|
||||
|
||||
const formatters: Record<string, (v: number) => string> = {
|
||||
forecast: (v) => `+${v}h`,
|
||||
drive: (v) => {
|
||||
const hours = Math.round((v / 60) * 10) / 10
|
||||
return `${hours}h`
|
||||
}
|
||||
}
|
||||
|
||||
export const RoverSlider: Partial<RoverSliderHook> = {
|
||||
mounted(this: RoverSliderHook) {
|
||||
const labelId = this.el.dataset.labelId || ""
|
||||
const format = this.el.dataset.format || "forecast"
|
||||
|
||||
this.formatter = formatters[format] || formatters.forecast
|
||||
this.labelEl = document.getElementById(labelId)
|
||||
|
||||
this.inputHandler = () => {
|
||||
if (this.labelEl) {
|
||||
this.labelEl.textContent = this.formatter(Number((this.el as HTMLInputElement).value))
|
||||
}
|
||||
}
|
||||
|
||||
this.el.addEventListener("input", this.inputHandler)
|
||||
this.inputHandler()
|
||||
},
|
||||
|
||||
updated(this: RoverSliderHook) {
|
||||
if (this.inputHandler) this.inputHandler()
|
||||
},
|
||||
|
||||
destroyed(this: RoverSliderHook) {
|
||||
if (this.inputHandler) this.el.removeEventListener("input", this.inputHandler)
|
||||
}
|
||||
}
|
||||
|
|
@ -630,10 +630,17 @@ defmodule MicrowavepropWeb.RoverLive do
|
|||
value={@forecast_hour}
|
||||
phx-change="set_forecast_hour"
|
||||
phx-debounce="200"
|
||||
phx-hook="RoverSlider"
|
||||
phx-update="ignore"
|
||||
id="rover-forecast-slider"
|
||||
data-label-id="rover-forecast-label"
|
||||
data-format="forecast"
|
||||
name="value"
|
||||
class="range range-xs range-primary"
|
||||
/>
|
||||
<div class="text-xs opacity-70 mt-1">+{@forecast_hour}h</div>
|
||||
<div class="text-xs opacity-70 mt-1">
|
||||
<span id="rover-forecast-label">+{@forecast_hour}h</span>
|
||||
</div>
|
||||
</.sidebar_section>
|
||||
|
||||
<.sidebar_section title="BAND">
|
||||
|
|
@ -662,11 +669,17 @@ defmodule MicrowavepropWeb.RoverLive do
|
|||
value={@max_drive_min}
|
||||
phx-change="set_max_drive_time"
|
||||
phx-debounce="200"
|
||||
phx-hook="RoverSlider"
|
||||
phx-update="ignore"
|
||||
id="rover-drive-slider"
|
||||
data-label-id="rover-drive-label"
|
||||
data-format="drive"
|
||||
name="value"
|
||||
class="range range-xs range-primary"
|
||||
/>
|
||||
<div class="text-xs opacity-70 mt-1">
|
||||
{Float.round(@max_drive_min / 60, 1)}h from {@home.label}
|
||||
<span id="rover-drive-label">{Float.round(@max_drive_min / 60, 1)}h</span>
|
||||
from {@home.label}
|
||||
</div>
|
||||
</.sidebar_section>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue