diff options
| author | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-08-21 19:19:45 +0200 |
|---|---|---|
| committer | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-08-21 19:19:45 +0200 |
| commit | 72cc720e91e531fda3da073a8231951e0cccb696 (patch) | |
| tree | acc51bc53166f59531d1a4bf9be979042cc600b9 | |
| parent | b3a83b2fdd5b406d020398e7c3cf6f46149a2523 (diff) | |
Componentize and isolate the ride range filter
| -rw-r--r-- | web/ride-filters.go | 70 | ||||
| -rw-r--r-- | web/ride-range-filter.templ | 13 | ||||
| -rw-r--r-- | web/templates.templ | 30 |
3 files changed, 86 insertions, 27 deletions
diff --git a/web/ride-filters.go b/web/ride-filters.go index 888d6bc..1fb647b 100644 --- a/web/ride-filters.go +++ b/web/ride-filters.go @@ -65,6 +65,76 @@ type RideFilterView struct { ResetURL string } +type RangeFilterConfig struct { + Legend string + IDPrefix string + Format string + ParamMin string + ParamMax string + BoundMin int + BoundMax int + Step int + ValueMin int + ValueMax int + LabelMin string + LabelMax string + FormatValue func(int) string +} + +func rideDistanceFilterConfig(view RideFilterView) RangeFilterConfig { + return RangeFilterConfig{ + Legend: "Distance", + IDPrefix: "distance", + Format: "distance", + ParamMin: rideFilterDistanceMinParam, + ParamMax: rideFilterDistanceMaxParam, + BoundMin: rideFilterDistanceMinKm, + BoundMax: rideFilterDistanceMaxKm, + Step: rideFilterDistanceStepKm, + ValueMin: view.DistanceMinKm, + ValueMax: view.DistanceMaxKm, + LabelMin: "Minimum distance", + LabelMax: "Maximum distance", + FormatValue: formatRideFilterDistance, + } +} + +func rideDurationFilterConfig(view RideFilterView) RangeFilterConfig { + return RangeFilterConfig{ + Legend: "Moving duration", + IDPrefix: "duration", + Format: "duration", + ParamMin: rideFilterDurationMinParam, + ParamMax: rideFilterDurationMaxParam, + BoundMin: rideFilterDurationMinMinutes, + BoundMax: rideFilterDurationMaxMinutes, + Step: rideFilterDurationStepMinutes, + ValueMin: view.DurationMinMinutes, + ValueMax: view.DurationMaxMinutes, + LabelMin: "Minimum moving duration", + LabelMax: "Maximum moving duration", + FormatValue: formatRideFilterDuration, + } +} + +func rideCotacolFilterConfig(view RideFilterView) RangeFilterConfig { + return RangeFilterConfig{ + Legend: "Cotacol", + IDPrefix: "cotacol", + Format: "cotacol", + ParamMin: rideFilterCotacolMinParam, + ParamMax: rideFilterCotacolMaxParam, + BoundMin: rideFilterCotacolMinPoints, + BoundMax: rideFilterCotacolMaxPoints, + Step: rideFilterCotacolStepPoints, + ValueMin: view.CotacolMinPoints, + ValueMax: view.CotacolMaxPoints, + LabelMin: "Minimum Cotacol", + LabelMax: "Maximum Cotacol", + FormatValue: formatRideFilterCotacol, + } +} + func parseRideFilters(query url.Values) RideFilters { filters := RideFilters{ DistanceMinKm: parseRideFilterInt(query.Get(rideFilterDistanceMinParam), rideFilterDistanceMinKm, rideFilterDistanceMaxKm, rideFilterDistanceStepKm), diff --git a/web/ride-range-filter.templ b/web/ride-range-filter.templ new file mode 100644 index 0000000..27eb802 --- /dev/null +++ b/web/ride-range-filter.templ @@ -0,0 +1,13 @@ +package web + +templ RideRangeFilter(field RangeFilterConfig) { + <fieldset class="ride-filter-group"> + <legend>{ field.Legend }</legend> + <div class="range-values"><output data-range-value="min" for={ field.IDPrefix + "-min" }>{ field.FormatValue(field.ValueMin) }</output><span aria-hidden="true">to</span><output data-range-value="max" for={ field.IDPrefix + "-max" }>{ field.FormatValue(field.ValueMax) }</output></div> + <div class="range-control" data-range-filter={ field.Format } data-range-format={ field.Format }> + <div class="range-track" data-range-track></div> + <input id={ field.IDPrefix + "-min" } class="range-input range-input-min" type="range" name={ field.ParamMin } min={ formatRideFilterInt(field.BoundMin) } max={ formatRideFilterInt(field.BoundMax) } step={ formatRideFilterInt(field.Step) } value={ formatRideFilterInt(field.ValueMin) } data-range-min aria-label={ field.LabelMin }/> + <input id={ field.IDPrefix + "-max" } class="range-input range-input-max" type="range" name={ field.ParamMax } min={ formatRideFilterInt(field.BoundMin) } max={ formatRideFilterInt(field.BoundMax) } step={ formatRideFilterInt(field.Step) } value={ formatRideFilterInt(field.ValueMax) } data-range-max aria-label={ field.LabelMax }/> + </div> + </fieldset> +} diff --git a/web/templates.templ b/web/templates.templ index 0bfef9c..71df20b 100644 --- a/web/templates.templ +++ b/web/templates.templ @@ -37,33 +37,9 @@ templ RidesContent(data RidesPageData) { <input type="hidden" name="sort" value={ data.Sort.Column }/> <input type="hidden" name="dir" value={ rideSortDirection(data.Sort) }/> <div class="ride-filter-ranges"> - <fieldset class="ride-filter-group"> - <legend>Distance</legend> - <div class="range-values"><output data-range-value="min" for="distance-min">{ formatRideFilterDistance(data.Filters.DistanceMinKm) }</output><span aria-hidden="true">to</span><output data-range-value="max" for="distance-max">{ formatRideFilterDistance(data.Filters.DistanceMaxKm) }</output></div> - <div class="range-control" data-range-filter="distance" data-range-format="distance"> - <div class="range-track" data-range-track></div> - <input id="distance-min" class="range-input range-input-min" type="range" name="distance_min" min={ formatRideFilterInt(rideFilterDistanceMinKm) } max={ formatRideFilterInt(rideFilterDistanceMaxKm) } step={ formatRideFilterInt(rideFilterDistanceStepKm) } value={ formatRideFilterInt(data.Filters.DistanceMinKm) } data-range-min aria-label="Minimum distance"/> - <input id="distance-max" class="range-input range-input-max" type="range" name="distance_max" min={ formatRideFilterInt(rideFilterDistanceMinKm) } max={ formatRideFilterInt(rideFilterDistanceMaxKm) } step={ formatRideFilterInt(rideFilterDistanceStepKm) } value={ formatRideFilterInt(data.Filters.DistanceMaxKm) } data-range-max aria-label="Maximum distance"/> - </div> - </fieldset> - <fieldset class="ride-filter-group"> - <legend>Moving duration</legend> - <div class="range-values"><output data-range-value="min" for="duration-min">{ formatRideFilterDuration(data.Filters.DurationMinMinutes) }</output><span aria-hidden="true">to</span><output data-range-value="max" for="duration-max">{ formatRideFilterDuration(data.Filters.DurationMaxMinutes) }</output></div> - <div class="range-control" data-range-filter="duration" data-range-format="duration"> - <div class="range-track" data-range-track></div> - <input id="duration-min" class="range-input range-input-min" type="range" name="duration_min" min={ formatRideFilterInt(rideFilterDurationMinMinutes) } max={ formatRideFilterInt(rideFilterDurationMaxMinutes) } step={ formatRideFilterInt(rideFilterDurationStepMinutes) } value={ formatRideFilterInt(data.Filters.DurationMinMinutes) } data-range-min aria-label="Minimum moving duration"/> - <input id="duration-max" class="range-input range-input-max" type="range" name="duration_max" min={ formatRideFilterInt(rideFilterDurationMinMinutes) } max={ formatRideFilterInt(rideFilterDurationMaxMinutes) } step={ formatRideFilterInt(rideFilterDurationStepMinutes) } value={ formatRideFilterInt(data.Filters.DurationMaxMinutes) } data-range-max aria-label="Maximum moving duration"/> - </div> - </fieldset> - <fieldset class="ride-filter-group"> - <legend>Cotacol</legend> - <div class="range-values"><output data-range-value="min" for="cotacol-min">{ formatRideFilterCotacol(data.Filters.CotacolMinPoints) }</output><span aria-hidden="true">to</span><output data-range-value="max" for="cotacol-max">{ formatRideFilterCotacol(data.Filters.CotacolMaxPoints) }</output></div> - <div class="range-control" data-range-filter="cotacol" data-range-format="cotacol"> - <div class="range-track" data-range-track></div> - <input id="cotacol-min" class="range-input range-input-min" type="range" name="cotacol_min" min={ formatRideFilterInt(rideFilterCotacolMinPoints) } max={ formatRideFilterInt(rideFilterCotacolMaxPoints) } step={ formatRideFilterInt(rideFilterCotacolStepPoints) } value={ formatRideFilterInt(data.Filters.CotacolMinPoints) } data-range-min aria-label="Minimum Cotacol"/> - <input id="cotacol-max" class="range-input range-input-max" type="range" name="cotacol_max" min={ formatRideFilterInt(rideFilterCotacolMinPoints) } max={ formatRideFilterInt(rideFilterCotacolMaxPoints) } step={ formatRideFilterInt(rideFilterCotacolStepPoints) } value={ formatRideFilterInt(data.Filters.CotacolMaxPoints) } data-range-max aria-label="Maximum Cotacol"/> - </div> - </fieldset> + @RideRangeFilter(rideDistanceFilterConfig(data.Filters)) + @RideRangeFilter(rideDurationFilterConfig(data.Filters)) + @RideRangeFilter(rideCotacolFilterConfig(data.Filters)) </div> <div class="ride-filter-meta"> <fieldset class="ride-filter-group date-filter-group"> |
