package web templ Layout(title string, content templ.Component) { { title } · biking_home
@content
} templ RidesPage(items []RideView, headers []RideSortHeader) { @Layout("Rides", RidesContent(items, headers)) } templ RidesContent(items []RideView, headers []RideSortHeader) {

Ride library

All rides

Your imported rides, ready for climb analysis.

Sync Strava
if len(items) == 0 {
No rides stored yet. Import your first Strava rides.
} else { for _, header := range headers { } for _, item := range items { }
{ header.Label }
{ item.Name }
{ item.Type }
{ formatRideDate(item.StartDate) }{ formatDistance(item.DistanceM) }{ formatDuration(item.MovingTimeS) }{ formatElevation(item.TotalElevationGainM) }{ item.Cotacol }{ item.CotacolPer100Km }
}
} templ RideDetailPage(data RideDetailView) { @Layout("Ride detail", RideDetailContent(data)) } templ RideDetailContent(data RideDetailView) {

{ data.Ride.Name }

{ data.Ride.Type } · { formatRideDate(data.Ride.StartDate) }

Back to rides
if data.RouteError != "" {
{ data.RouteError }
} if data.Notice != "" {
{ data.Notice }
} if data.ActionError != "" {
{ data.ActionError }
}
Distance
{ formatDistance(data.Ride.DistanceM) }
Moving time
{ formatDuration(data.Ride.MovingTimeS) }
Elevation
{ formatElevation(data.Ride.TotalElevationGainM) }
if data.HasRoute {
if len(data.Profile.Climbs) > 0 { } if len(data.Profile.Climbs) == 0 {

No climbs detected in this ride.

} if len(data.Profile.Climbs) > 0 {
for index, climb := range data.Profile.Climbs {
Climb { formatClimbNumber(index) }{ climb.Name } { formatProfileDistance(climb.StartKm) }–{ formatProfileDistance(climb.EndKm) }

{ climb.Category } · { formatProfileDistance(climb.DistanceKm) } at { formatSlope(climb.SlopePercent) } · Cotacol { formatCotacol(climb.Cotacol) }

if climb.OfficialClimbID > 0 {

Official climb matched: { climb.OfficialName }

} else {

No official climb matched yet.

Start
{ formatProfileDistance(climb.StartKm) }
End
{ formatProfileDistance(climb.EndKm) }
Preview the corrected climb boundaries.
}
}
}
}
if data.HasRoute {

Elevation profile

Hover or focus the profile to inspect the ride at that distance.

Hover or focus the profile to inspect elevation.
}
if data.HasRoute { @templ.JSONScript("ride-route", data.Route) @templ.JSONScript("ride-profile", data.Profile) } } templ SyncPage(data SyncPageData) { @Layout("Sync Strava", SyncContent(data)) } templ SyncContent(data SyncPageData) {

Data import

Sync Strava rides

Choose a date range. New rides are downloaded as GPX files and recorded in the local library.

if data.Notice != "" {
{ data.Notice }
} else { } if data.Error != "" {
{ data.Error }
} else { }
if !data.HasAuth {

Strava authorization is required before the first sync.

Authorize Strava } else {
}
}