diff options
Diffstat (limited to 'web/templates.templ')
| -rw-r--r-- | web/templates.templ | 67 |
1 files changed, 66 insertions, 1 deletions
diff --git a/web/templates.templ b/web/templates.templ index d1719b8..6c3b09d 100644 --- a/web/templates.templ +++ b/web/templates.templ @@ -13,7 +13,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="/sync">Sync Strava</a></nav> + <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> </header> <main class="container"> @content @@ -359,3 +359,68 @@ templ SyncContent(data SyncPageData) { </section> <script type="module" src="/static/sync.js"></script> } + +templ DataQualityPage(data DataQualityPageData) { + @Layout("Data quality", DataQualityContent(data)) +} + +templ DataQualityContent(data DataQualityPageData) { + <p class="eyebrow">Curation</p> + <h1>Data quality</h1> + <p class="lead">Categorise rides that are missing bike or ride type. Select rides, pick categories, and apply in bulk.</p> + if data.Notice != "" { + <div class="notice">{ data.Notice }</div> + } + <section class="panel"> + <div class="section-heading"> + <div><p class="eyebrow">Todo</p><h2>Uncategorised rides</h2></div> + <span class="section-count">{ formatRideCount(data.Total) }</span> + </div> + if data.Total == 0 { + <div class="empty">All rides are categorised.</div> + } else if len(data.Items) == 0 { + <div class="empty">No uncategorised rides match the current view.</div> + } else { + <form method="post" action="/data-quality/categories" id="data-quality-form"> + <div class="data-quality-bulk"> + <label for="bulk-bike-type">Bike type + <select id="bulk-bike-type" name="bike_type" required> + <option value="">—</option> + for _, opt := range bikeTypeOptions { + <option value={ string(opt) }>{ bikeTypeLabels[opt] }</option> + } + </select> + </label> + <label for="bulk-ride-type">Ride type + <select id="bulk-ride-type" name="ride_type" required> + <option value="">—</option> + for _, opt := range rideTypeOptions { + <option value={ string(opt) }>{ rideTypeLabels[opt] }</option> + } + </select> + </label> + <button class="button" type="submit">Apply to selected</button> + <span class="data-quality-selected" id="data-quality-selected">0 selected</span> + </div> + <div class="data-quality-table-wrap"> + <table> + <thead><tr><th><input type="checkbox" id="data-quality-select-all" aria-label="Select all rides"/></th><th>Ride</th><th>Started</th><th class="numeric">Distance</th><th>Bike</th><th>Ride type</th></tr></thead> + <tbody> + for _, item := range data.Items { + <tr> + <td><input type="checkbox" name="ride_ids" value={ formatRideID(item.Ride.ID) } class="data-quality-checkbox"/></td> + <td><strong><a href={ templ.URL(rideDetailURL(item.Ride.ID)) }>{ item.Ride.Name }</a></strong><br/><small>{ item.Ride.Type }</small></td> + <td>{ formatRideDate(item.Ride.StartDate) }</td> + <td class="numeric">{ formatDistance(item.Ride.DistanceM) }</td> + <td>{ formatCategoryOrEmpty(string(item.Ride.BikeType)) }</td> + <td>{ formatCategoryOrEmpty(string(item.Ride.RideType)) }</td> + </tr> + } + </tbody> + </table> + </div> + </form> + <script type="module" src="/static/data-quality.js"></script> + } + </section> +} |
