You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
166 lines
6.5 KiB
166 lines
6.5 KiB
package templates
|
|
|
|
import (
|
|
"track-gopher/models"
|
|
"fmt"
|
|
"strconv"
|
|
)
|
|
|
|
// RacePublic renders the public race view
|
|
templ RacePublic(heatData *models.HeatData, nextHeat *models.HeatData, onDeckHeat *models.HeatData) {
|
|
@LayoutPublic("Race - " + heatData.Group.Name) {
|
|
<div class="container-fluid mt-3">
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card mb-4">
|
|
<div class="card-header bg-primary text-white">
|
|
<h2 class="mb-0 text-center">{ heatData.Group.Name } - Heat { strconv.Itoa(heatData.HeatNumber) } of { strconv.Itoa(heatData.TotalHeats) }</h2>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="current-heat" class="mb-4">
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="timer-display d-inline-flex align-items-center text-center mb-4" style="height: 200px;" hx-ext="sse" sse-connect="/api/events" sse-swap="race-status">
|
|
<div id="status-indicator" class="w-25 h-50 d-inline-flex align-items-center badge bg-primary">Idle</div>
|
|
</div>
|
|
|
|
<div class="lanes-container">
|
|
@raceCurrentHeatLanes(heatData)
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="card mb-4">
|
|
<div class="card-header bg-info text-white">
|
|
<h3 class="mb-0">Next Heat</h3>
|
|
</div>
|
|
<div class="card-body">
|
|
if nextHeat != nil {
|
|
@raceNextHeatPreview(nextHeat)
|
|
} else {
|
|
<div class="alert alert-info">No more heats in this group</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="card mb-4">
|
|
<div class="card-header bg-info text-white">
|
|
<h3 class="mb-0">Upcoming Heat</h3>
|
|
</div>
|
|
<div class="card-body">
|
|
if onDeckHeat != nil {
|
|
@raceNextHeatPreview(onDeckHeat)
|
|
} else {
|
|
<div class="alert alert-info">No more heats in this group</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
}
|
|
|
|
// Helper template for displaying current heat lanes
|
|
templ raceCurrentHeatLanes(heatData *models.HeatData) {
|
|
|
|
<div class="row row-cols-1 row-cols-md-4 g-4">
|
|
if heatData.Lane1 != nil {
|
|
@raceLaneCard(*heatData.Lane1)
|
|
}
|
|
if heatData.Lane2 != nil {
|
|
@raceLaneCard(*heatData.Lane2)
|
|
}
|
|
if heatData.Lane3 != nil {
|
|
@raceLaneCard(*heatData.Lane3)
|
|
}
|
|
if heatData.Lane4 != nil {
|
|
@raceLaneCard(*heatData.Lane4)
|
|
}
|
|
</div>
|
|
}
|
|
|
|
// Helper template for displaying a lane card
|
|
templ raceLaneCard(laneData models.LaneData) {
|
|
<div class="col">
|
|
<div class="card h-100 lane-card">
|
|
<div class="card-header bg-primary text-white">
|
|
<h4 class="mb-0">Lane { strconv.Itoa(laneData.Lane) }</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<h5 class="card-title">{ laneData.Name }</h5>
|
|
<p class="card-text">
|
|
<strong>Car #:</strong> { laneData.CarNum }<br/>
|
|
<strong>Weight:</strong> { fmt.Sprintf("%.1f oz", laneData.CarWeight) }
|
|
</p>
|
|
<div class="result-area">
|
|
<div class="row">
|
|
<div class="col-6">
|
|
<div class="text-center">
|
|
<h6>Time</h6>
|
|
<div class="display-6" hx-ext="sse" sse-connect="/api/events" sse-swap={fmt.Sprintf("lane-%d-time", laneData.Lane)}>
|
|
{ fmt.Sprintf("%.3f", laneData.Time) }
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-6">
|
|
<div class="text-center">
|
|
<h6>Position</h6>
|
|
<div class="display-6" hx-ext="sse" sse-connect="/api/events" sse-swap={fmt.Sprintf("lane-%d-position", laneData.Lane)}>
|
|
{ strconv.Itoa(laneData.Place) }
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
// Helper template for displaying next heat preview
|
|
templ raceNextHeatPreview(heatData *models.HeatData) {
|
|
<h4 class="mb-3">Heat { strconv.Itoa(heatData.HeatNumber) }</h4>
|
|
<div class="table-responsive">
|
|
<table class="table table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th>Lane</th>
|
|
<th>Racer</th>
|
|
<th>Car #</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
if heatData.Lane1 != nil {
|
|
@raceNextHeatRow(*heatData.Lane1)
|
|
}
|
|
if heatData.Lane2 != nil {
|
|
@raceNextHeatRow(*heatData.Lane2)
|
|
}
|
|
if heatData.Lane3 != nil {
|
|
@raceNextHeatRow(*heatData.Lane3)
|
|
}
|
|
if heatData.Lane4 != nil {
|
|
@raceNextHeatRow(*heatData.Lane4)
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
}
|
|
|
|
// Helper template for displaying a row in the next heat preview
|
|
templ raceNextHeatRow(laneData models.LaneData) {
|
|
<tr>
|
|
<td>{ strconv.Itoa(laneData.Lane) }</td>
|
|
<td>{ laneData.Name }</td>
|
|
<td>{ laneData.CarNum }</td>
|
|
</tr>
|
|
} |