diff options
| -rw-r--r-- | web/server_test.go | 8 | ||||
| -rw-r--r-- | web/templates.templ | 14 | ||||
| -rw-r--r-- | web/templates_templ.go | 18 | ||||
| -rw-r--r-- | web/views.go | 41 |
4 files changed, 46 insertions, 35 deletions
diff --git a/web/server_test.go b/web/server_test.go index d04f1d6..281f46a 100644 --- a/web/server_test.go +++ b/web/server_test.go @@ -196,8 +196,8 @@ func TestBuildRideProfileIncludesClimbsAndCrossings(t *testing.T) { require.Len(t, profile.Climbs, 1) assert.Equal(t, "Pas de Magnan", profile.Climbs[0].Name) assert.Equal(t, 1.0, profile.Climbs[0].TopKm) - assert.Empty(t, profile.OfficialClimbs) - assert.Len(t, profile.UnmatchedClimbs, 1) + assert.Empty(t, profile.OfficialClimbs()) + assert.Len(t, profile.UnmatchedClimbs(), 1) require.Len(t, profile.Crossings, 1) assert.Equal(t, "Pas de Magnan", profile.Crossings[0].Name) assert.Equal(t, 1.0, profile.Crossings[0].DistanceKm) @@ -221,8 +221,8 @@ func TestBuildRideProfileIncludesOfficialClimbMatch(t *testing.T) { assert.Equal(t, int64(42), profile.Climbs[0].OfficialClimbID) assert.Equal(t, "Col de Test", profile.Climbs[0].OfficialName) assert.Equal(t, "Col de Test", profile.Climbs[0].Name) - assert.Len(t, profile.OfficialClimbs, 1) - assert.Empty(t, profile.UnmatchedClimbs) + assert.Len(t, profile.OfficialClimbs(), 1) + assert.Empty(t, profile.UnmatchedClimbs()) } func TestBuildRideProfileUsesOfficialClimbBoundaries(t *testing.T) { diff --git a/web/templates.templ b/web/templates.templ index 9f57696..1decad5 100644 --- a/web/templates.templ +++ b/web/templates.templ @@ -79,13 +79,13 @@ templ RideDetailContent(data RideDetailView) { </dl> </section> if data.HasRoute { - if len(data.Profile.OfficialClimbs) > 0 { + if len(data.Profile.OfficialClimbs()) > 0 { <section class="panel official-climbs-panel"> <div class="section-heading"> <p class="eyebrow">Official climbs</p> </div> <div class="official-climb-list"> - for _, climb := range data.Profile.OfficialClimbs { + for _, climb := range data.Profile.OfficialClimbs() { <details class="official-climb-card" data-official-climb-card> <summary> <span class="official-climb-card-title"><span class="climb-number">Climb { formatClimbNumber(climb.Index) }</span><strong>{ climb.OfficialName }</strong></span> @@ -112,20 +112,20 @@ templ RideDetailContent(data RideDetailView) { </div> </section> } - <div class={ rideDetailColumnsClass(len(data.Profile.UnmatchedClimbs)) }> - if len(data.Profile.UnmatchedClimbs) > 0 { + <div class={ rideDetailColumnsClass(len(data.Profile.UnmatchedClimbs())) }> + if len(data.Profile.UnmatchedClimbs()) > 0 { <section class="panel climbs-panel"> <div class="section-heading"> <div><p class="eyebrow">Next steps</p><h2>Climbs to match</h2></div> - <span class="section-count">{ formatClimbCount(len(data.Profile.UnmatchedClimbs)) }</span> + <span class="section-count">{ formatClimbCount(len(data.Profile.UnmatchedClimbs())) }</span> </div> <nav class="climb-navigation" aria-label="Climb navigation"> <button class="button secondary" type="button" data-climb-previous aria-label="Previous climb">←</button> - <output data-climb-position>Climb 1 of { formatClimbCount(len(data.Profile.UnmatchedClimbs)) }</output> + <output data-climb-position>Climb 1 of { formatClimbCount(len(data.Profile.UnmatchedClimbs())) }</output> <button class="button secondary" type="button" data-climb-next aria-label="Next climb">→</button> </nav> <div class="climb-list" data-climb-list> - for _, climb := range data.Profile.UnmatchedClimbs { + for _, climb := range data.Profile.UnmatchedClimbs() { <article class="climb-item todo-item" data-climb-item data-climb-index={ formatRouteIndex(climb.Index) }> <div class="climb-item-heading"> <strong><span class="todo-check" aria-hidden="true"></span><span class="climb-number">Climb { formatClimbNumber(climb.Index) }</span>{ climb.Name }</strong> diff --git a/web/templates_templ.go b/web/templates_templ.go index cfad073..0ecca3d 100644 --- a/web/templates_templ.go +++ b/web/templates_templ.go @@ -524,12 +524,12 @@ func RideDetailContent(data RideDetailView) templ.Component { return templ_7745c5c3_Err } if data.HasRoute { - if len(data.Profile.OfficialClimbs) > 0 { + if len(data.Profile.OfficialClimbs()) > 0 { _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<section class=\"panel official-climbs-panel\"><div class=\"section-heading\"><p class=\"eyebrow\">Official climbs</p></div><div class=\"official-climb-list\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - for _, climb := range data.Profile.OfficialClimbs { + for _, climb := range data.Profile.OfficialClimbs() { _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<details class=\"official-climb-card\" data-official-climb-card><summary><span class=\"official-climb-card-title\"><span class=\"climb-number\">Climb ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err @@ -648,7 +648,7 @@ func RideDetailContent(data RideDetailView) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var39 = []any{rideDetailColumnsClass(len(data.Profile.UnmatchedClimbs))} + var templ_7745c5c3_Var39 = []any{rideDetailColumnsClass(len(data.Profile.UnmatchedClimbs()))} templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var39...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err @@ -670,15 +670,15 @@ func RideDetailContent(data RideDetailView) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - if len(data.Profile.UnmatchedClimbs) > 0 { + if len(data.Profile.UnmatchedClimbs()) > 0 { _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<section class=\"panel climbs-panel\"><div class=\"section-heading\"><div><p class=\"eyebrow\">Next steps</p><h2>Climbs to match</h2></div><span class=\"section-count\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var41 string - templ_7745c5c3_Var41, templ_7745c5c3_Err = templ.JoinStringErrs(formatClimbCount(len(data.Profile.UnmatchedClimbs))) + templ_7745c5c3_Var41, templ_7745c5c3_Err = templ.JoinStringErrs(formatClimbCount(len(data.Profile.UnmatchedClimbs()))) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates.templ`, Line: 120, Col: 87} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates.templ`, Line: 120, Col: 89} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var41)) if templ_7745c5c3_Err != nil { @@ -689,9 +689,9 @@ func RideDetailContent(data RideDetailView) templ.Component { return templ_7745c5c3_Err } var templ_7745c5c3_Var42 string - templ_7745c5c3_Var42, templ_7745c5c3_Err = templ.JoinStringErrs(formatClimbCount(len(data.Profile.UnmatchedClimbs))) + templ_7745c5c3_Var42, templ_7745c5c3_Err = templ.JoinStringErrs(formatClimbCount(len(data.Profile.UnmatchedClimbs()))) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates.templ`, Line: 124, Col: 98} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates.templ`, Line: 124, Col: 100} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var42)) if templ_7745c5c3_Err != nil { @@ -701,7 +701,7 @@ func RideDetailContent(data RideDetailView) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - for _, climb := range data.Profile.UnmatchedClimbs { + for _, climb := range data.Profile.UnmatchedClimbs() { _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<article class=\"climb-item todo-item\" data-climb-item data-climb-index=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err diff --git a/web/views.go b/web/views.go index 6c96576..f8a45d3 100644 --- a/web/views.go +++ b/web/views.go @@ -29,11 +29,29 @@ type RideDetailView struct { } type RideProfile struct { - Points []RideProfilePoint `json:"points"` - Climbs []RideProfileClimb `json:"climbs"` - OfficialClimbs []RideProfileClimb `json:"-"` - UnmatchedClimbs []RideProfileClimb `json:"-"` - Crossings []RideProfileCrossing `json:"crossings"` + Points []RideProfilePoint `json:"points"` + Climbs []RideProfileClimb `json:"climbs"` + Crossings []RideProfileCrossing `json:"crossings"` +} + +func (profile RideProfile) OfficialClimbs() []RideProfileClimb { + climbs := make([]RideProfileClimb, 0) + for _, climb := range profile.Climbs { + if climb.OfficialClimbID > 0 { + climbs = append(climbs, climb) + } + } + return climbs +} + +func (profile RideProfile) UnmatchedClimbs() []RideProfileClimb { + climbs := make([]RideProfileClimb, 0) + for _, climb := range profile.Climbs { + if climb.OfficialClimbID == 0 { + climbs = append(climbs, climb) + } + } + return climbs } type RideProfilePoint struct { @@ -228,11 +246,9 @@ func buildRideDetailView(item rides.Ride, parsed ride.Ride, passes []mountain_pa func buildRideProfile(parsed ride.Ride, passes []mountain_pass.MountainPass, officialClimbs []official_climb.OfficialClimb, matchPolicy official_climb.MatchPolicy) RideProfile { profile := RideProfile{ - Points: make([]RideProfilePoint, parsed.Len()), - Climbs: make([]RideProfileClimb, 0), - OfficialClimbs: make([]RideProfileClimb, 0), - UnmatchedClimbs: make([]RideProfileClimb, 0), - Crossings: make([]RideProfileCrossing, 0), + Points: make([]RideProfilePoint, parsed.Len()), + Climbs: make([]RideProfileClimb, 0), + Crossings: make([]RideProfileCrossing, 0), } for i := 0; i < parsed.Len(); i++ { coordinate := parsed.Coord(i) @@ -264,11 +280,6 @@ func buildRideProfile(parsed ride.Ride, passes []mountain_pass.MountainPass, off EndIndex: segment.EndIndex(), } profile.Climbs = append(profile.Climbs, climb) - if climb.OfficialClimbID > 0 { - profile.OfficialClimbs = append(profile.OfficialClimbs, climb) - } else { - profile.UnmatchedClimbs = append(profile.UnmatchedClimbs, climb) - } } for _, crossing := range analysis.Crossings { profile.Crossings = append(profile.Crossings, RideProfileCrossing{ |