diff options
| author | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-09-06 12:38:16 +0200 |
|---|---|---|
| committer | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-09-06 12:38:16 +0200 |
| commit | 8e0c55230ef59869bda1ca19ca8697b447d57698 (patch) | |
| tree | 2d5941e95949c43a84326cc5d10db8e4fab72a64 /web/templates.templ | |
| parent | 28a7c9f281c16d1928b37dd1afdfe8399b7a03f8 (diff) | |
Preview: analyze a raw GPX or FIT file without persisting it
Diffstat (limited to 'web/templates.templ')
| -rw-r--r-- | web/templates.templ | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/web/templates.templ b/web/templates.templ index 14f8d69..14e9aab 100644 --- a/web/templates.templ +++ b/web/templates.templ @@ -15,7 +15,7 @@ templ Layout(title string, content templ.Component) { <body> <header class="site-header"> <a class="brand" href="/">biking_home</a> - <nav class="nav"><a href="/">Rides</a><a href="/analytics">Analytics</a><a href="/data-quality">Data quality</a><a href="/sync">Sync Strava</a></nav> + <nav class="nav"><a href="/">Rides</a><a href="/analytics">Analytics</a><a href="/preview">Preview</a><a href="/data-quality">Data quality</a><a href="/sync">Sync Strava</a></nav> </header> <main class="container"> @content @@ -200,6 +200,25 @@ templ AnalyticsContent(data AnalyticsPageData) { <script type="module" src="/static/analytics.js"></script> } +templ PreviewPage(data PreviewPageData) { + @Layout("Preview", PreviewContent(data)) +} + +templ PreviewContent(data PreviewPageData) { + <div class="toolbar"> + <div><h1 class="ride-detail-title">Preview a ride file</h1><p class="lead">Analyze a GPX or FIT file without importing it: climbs, official climb matches and mountain-pass crossings.</p></div> + </div> + if data.Error != "" { + <div class="error">{ data.Error }</div> + } + <section class="panel"> + <form method="post" action="/preview" enctype="multipart/form-data" class="preview-form"> + <label>GPX or FIT file<input type="file" name="file" accept=".gpx,.fit" required/></label> + <button class="button" type="submit">Preview</button> + </form> + </section> +} + templ RideDetailPage(data RideDetailView) { @Layout("Ride detail", RideDetailContent(data)) } @@ -233,7 +252,8 @@ templ RideDetailContent(data RideDetailView) { <div><dt>Cotacol</dt><dd>{ data.Cotacol }</dd></div> </dl> </section> - <section class="panel categories-panel"> + if !data.Preview { + <section class="panel categories-panel"> <details class="categories-details" open?={ data.Ride.BikeType == "" && data.Ride.RideType == "" }> <summary class="categories-summary"> <div class="categories-heading"> @@ -260,9 +280,10 @@ templ RideDetailContent(data RideDetailView) { </div> </fieldset> <button class="button" type="submit">Save</button> - </form> - </details> + </form> + </details> </section> + } if data.HasRoute { if len(data.Profile.OfficialClimbs()) > 0 { <section class="panel official-climbs-panel"> @@ -317,7 +338,7 @@ templ RideDetailContent(data RideDetailView) { </div> <p class="climb-metrics" data-climb-metrics>{ climb.Category } · { formatProfileDistance(climb.DistanceKm) } at { formatSlope(climb.SlopePercent) } · Cotacol { formatCotacol(climb.Cotacol) }</p> <p class="climb-status">Waiting for an official climb match.</p> - <form class="official-climb-form" data-official-climb-form method="post" action={ templ.URL(officialClimbCreateURL(data.Ride.ID)) }> + <form class="official-climb-form" data-official-climb-form data-preview-form?={ data.Preview } method="post" action={ templ.URL(data.OfficialClimbFormURL) }> <label>Name<input type="text" name="name" required placeholder="Official climb name"/></label> <input type="hidden" name="start_index" value={ formatRouteIndex(climb.StartIndex) } data-boundary-input="start"/> <input type="hidden" name="end_index" value={ formatRouteIndex(climb.EndIndex) } data-boundary-input="end"/> |
