DustyP 9 months ago
parent 4385f86f23
commit 6f6a39bd7c

@ -142,111 +142,79 @@ func (db *DB) Close() error {
return db.DB.Close()
}
// SaveHeats saves a list of heats for a group
// SaveHeats saves the heats for a group, replacing any existing heats
func (db *DB) SaveHeats(groupID int64, heats []models.Heat) error {
// Start a transaction
tx, err := db.Begin()
if err != nil {
return err
return fmt.Errorf("failed to begin transaction: %w", err)
}
defer tx.Rollback()
// Delete existing heats for this group
_, err = tx.Exec("DELETE FROM heats WHERE group_id = ?", groupID)
if err != nil {
return err
return fmt.Errorf("failed to delete existing heats: %w", err)
}
// Insert new heats
stmt, err := tx.Prepare(`
INSERT INTO heats (group_id, heat_num, lane1_id, lane2_id, lane3_id, lane4_id)
VALUES (?, ?, ?, ?, ?, ?)
`)
stmt, err := tx.Prepare("INSERT INTO heats (group_id, heat_num, lane1_id, lane2_id, lane3_id, lane4_id) VALUES (?, ?, ?, ?, ?, ?)")
if err != nil {
return err
return fmt.Errorf("failed to prepare statement: %w", err)
}
defer stmt.Close()
for _, heat := range heats {
_, err = stmt.Exec(
groupID,
heat.HeatNum,
nullableInt64(heat.Lane1ID),
nullableInt64(heat.Lane2ID),
nullableInt64(heat.Lane3ID),
nullableInt64(heat.Lane4ID),
)
for i, heat := range heats {
_, err = stmt.Exec(groupID, i+1, heat.Lane1ID, heat.Lane2ID, heat.Lane3ID, heat.Lane4ID)
if err != nil {
return err
return fmt.Errorf("failed to insert heat: %w", err)
}
}
// Commit the transaction
return tx.Commit()
}
// Commit transaction
if err := tx.Commit(); err != nil {
return fmt.Errorf("failed to commit transaction: %w", err)
}
// Helper function to handle nullable int64 values
func nullableInt64(i *int64) interface{} {
if i == nil {
return nil
}
return *i
}
// GetHeats retrieves all heats for a group
// GetHeats retrieves the saved heats for a group
func (db *DB) GetHeats(groupID int64) ([]models.Heat, error) {
rows, err := db.Query(`
SELECT id, group_id, heat_num, lane1_id, lane2_id, lane3_id, lane4_id
SELECT heat_num, lane1_id, lane2_id, lane3_id, lane4_id
FROM heats
WHERE group_id = ?
ORDER BY heat_num
`, groupID)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to query heats: %w", err)
}
defer rows.Close()
var heats []models.Heat
for rows.Next() {
var heat models.Heat
var lane1, lane2, lane3, lane4 sql.NullInt64
err := rows.Scan(
&heat.ID,
&heat.GroupID,
&heat.HeatNum,
&lane1,
&lane2,
&lane3,
&lane4,
)
err := rows.Scan(&heat.HeatNum, &heat.Lane1ID, &heat.Lane2ID, &heat.Lane3ID, &heat.Lane4ID)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to scan heat: %w", err)
}
if lane1.Valid {
val := lane1.Int64
heat.Lane1ID = &val
}
if lane2.Valid {
val := lane2.Int64
heat.Lane2ID = &val
}
if lane3.Valid {
val := lane3.Int64
heat.Lane3ID = &val
}
if lane4.Valid {
val := lane4.Int64
heat.Lane4ID = &val
}
heats = append(heats, heat)
}
return heats, nil
}
// HasSavedHeats checks if a group has saved heats
func (db *DB) HasSavedHeats(groupID int64) (bool, error) {
var count int
err := db.QueryRow("SELECT COUNT(*) FROM heats WHERE group_id = ?", groupID).Scan(&count)
if err != nil {
return false, fmt.Errorf("failed to check for saved heats: %w", err)
}
return count > 0, nil
}
// DeleteHeats deletes all heats for a group
func (db *DB) DeleteHeats(groupID int64) error {
_, err := db.Exec("DELETE FROM heats WHERE group_id = ?", groupID)

@ -48,8 +48,8 @@ type Heat struct {
ID int64 `json:"id"`
GroupID int64 `json:"group_id"`
HeatNum int `json:"heat_num"`
Lane1ID *int64 `json:"lane1_id"`
Lane2ID *int64 `json:"lane2_id"`
Lane3ID *int64 `json:"lane3_id"`
Lane4ID *int64 `json:"lane4_id"`
Lane1ID int64 `json:"lane1_id"`
Lane2ID int64 `json:"lane2_id"`
Lane3ID int64 `json:"lane3_id"`
Lane4ID int64 `json:"lane4_id"`
}

@ -139,7 +139,6 @@ func (s *Server) routes() {
// Add heats API routes
s.router.Route("/api/heats", func(r chi.Router) {
r.Post("/generate", s.handleGenerateHeats())
r.Post("/save", s.handleSaveHeats())
})
@ -757,76 +756,77 @@ func (s *Server) handleHeats() http.HandlerFunc {
// handleHeatsContent renders the heats content
func (s *Server) handleHeatsContent() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Get groups from database
groups, err := s.db.GetGroups()
if err != nil {
s.logger.Error("Failed to get groups", "error", err)
http.Error(w, "Failed to get groups", http.StatusInternalServerError)
// Get selected group ID from query parameter
groupIDStr := r.URL.Query().Get("group_id")
if groupIDStr == "" {
http.Error(w, "Group ID is required", http.StatusBadRequest)
return
}
// Get selected group ID from query parameter
selectedGroupID := int64(0)
groupIDStr := r.URL.Query().Get("group_id")
if groupIDStr != "" {
groupID, err := strconv.ParseInt(groupIDStr, 10, 64)
if err == nil {
selectedGroupID = groupID
}
if err != nil {
http.Error(w, "Invalid group ID", http.StatusBadRequest)
return
}
// Render template
component := templates.HeatsContent(selectedGroupID, groups, s.db)
if err := component.Render(r.Context(), w); err != nil {
s.logger.Error("Failed to render heats template", "error", err)
http.Error(w, "Failed to render page", http.StatusInternalServerError)
}
// Check for saved heats
hasSavedHeats, err := s.db.HasSavedHeats(groupID)
if err != nil {
s.logger.Error("Failed to check for saved heats", "error", err)
http.Error(w, "Failed to check for saved heats", http.StatusInternalServerError)
return
}
}
// handleGenerateHeats generates heats for a group
func (s *Server) handleGenerateHeats() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Get group ID from query parameter
groupIDStr := r.URL.Query().Get("group_id")
groupID, err := strconv.ParseInt(groupIDStr, 10, 64)
var heats []models.Heat
if hasSavedHeats {
// Get saved heats
heats, err = s.db.GetHeats(groupID)
if err != nil {
http.Error(w, "Invalid group ID", http.StatusBadRequest)
s.logger.Error("Failed to get saved heats", "error", err)
http.Error(w, "Failed to get saved heats", http.StatusInternalServerError)
return
}
}
// Get racers for this group
allRacers, err := s.db.GetRacers()
// Get racers for the group
racers, err := s.db.GetRacersByGroup(groupID)
if err != nil {
s.logger.Error("Failed to get racers", "error", err)
http.Error(w, "Failed to get racers", http.StatusInternalServerError)
return
}
// Filter racers by group
var groupRacers []models.Racer
for _, racer := range allRacers {
if racer.GroupID == groupID {
groupRacers = append(groupRacers, racer)
// Convert models.Racer to derby.Racer
derbyRacers := make([]derby.Racer, len(racers))
for i, r := range racers {
derbyRacers[i] = derby.Racer{
ID: r.ID,
FirstName: r.FirstName,
LastName: r.LastName,
CarNumber: r.CarNumber,
}
}
// Convert to derby racers
derbyRacers := make([]derby.Racer, len(groupRacers))
for i, racer := range groupRacers {
derbyRacers[i] = derby.Racer{
ID: racer.ID,
FirstName: racer.FirstName,
LastName: racer.LastName,
CarNumber: racer.CarNumber,
// Generate and convert heats
if !hasSavedHeats && len(racers) > 0 {
derbyHeats := derby.GenerateHeats(derbyRacers)
heats = make([]models.Heat, len(derbyHeats))
for i, h := range derbyHeats {
heats[i] = models.Heat{
HeatNum: i + 1,
Lane1ID: *h.Lane1ID,
Lane2ID: *h.Lane2ID,
Lane3ID: *h.Lane3ID,
Lane4ID: *h.Lane4ID,
}
}
}
// Render the generated heats
component := templates.GeneratedHeats(groupRacers)
// Render template
component := templates.HeatsContent(heats, racers)
if err := component.Render(r.Context(), w); err != nil {
s.logger.Error("Failed to render heats", "error", err)
http.Error(w, "Failed to render heats", http.StatusInternalServerError)
s.logger.Error("Failed to render heats content", "error", err)
http.Error(w, "Failed to render content", http.StatusInternalServerError)
}
}
}
@ -834,67 +834,26 @@ func (s *Server) handleGenerateHeats() http.HandlerFunc {
// handleSaveHeats saves heats for a group
func (s *Server) handleSaveHeats() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Get group ID from query parameter
groupIDStr := r.URL.Query().Get("group_id")
groupID, err := strconv.ParseInt(groupIDStr, 10, 64)
if err != nil {
http.Error(w, "Invalid group ID", http.StatusBadRequest)
return
// Parse request body
var request struct {
GroupID int64 `json:"group_id"`
Heats []models.Heat `json:"heats"`
}
// Get racers for this group
allRacers, err := s.db.GetRacers()
if err != nil {
s.logger.Error("Failed to get racers", "error", err)
http.Error(w, "Failed to get racers", http.StatusInternalServerError)
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
http.Error(w, "Invalid request body", http.StatusBadRequest)
return
}
// Filter racers by group
var groupRacers []models.Racer
for _, racer := range allRacers {
if racer.GroupID == groupID {
groupRacers = append(groupRacers, racer)
}
}
// Convert to derby racers
derbyRacers := make([]derby.Racer, len(groupRacers))
for i, racer := range groupRacers {
derbyRacers[i] = derby.Racer{
ID: racer.ID,
FirstName: racer.FirstName,
LastName: racer.LastName,
CarNumber: racer.CarNumber,
}
}
// Generate heats
derbyHeats := derby.GenerateHeats(derbyRacers)
// Convert to database heats
dbHeats := make([]models.Heat, len(derbyHeats))
for i, heat := range derbyHeats {
dbHeats[i] = models.Heat{
GroupID: groupID,
HeatNum: heat.HeatNum,
Lane1ID: heat.Lane1ID,
Lane2ID: heat.Lane2ID,
Lane3ID: heat.Lane3ID,
Lane4ID: heat.Lane4ID,
}
}
// Save heats to database
if err := s.db.SaveHeats(groupID, dbHeats); err != nil {
// Save heats
if err := s.db.SaveHeats(request.GroupID, request.Heats); err != nil {
s.logger.Error("Failed to save heats", "error", err)
http.Error(w, "Failed to save heats", http.StatusInternalServerError)
return
}
// Return success message
w.Header().Set("Content-Type", "text/html")
w.Write([]byte(`<div class="bg-green-100 p-4 rounded-lg mb-4"><p class="text-green-800">Heats saved successfully!</p></div>`))
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{"status": "success"})
}
}

@ -4,182 +4,99 @@ import (
"strconv"
"track-gopher/models"
"track-gopher/db"
"track-gopher/derby"
)
templ Heats(groups []models.Group, selectedGroupID int64, db *db.DB) {
@Layout("Race Heats") {
<div class="container py-4">
<h1 class="mb-4">Race Heats Generator</h1>
<h1 class="mb-4">Race Heats</h1>
<div class="mb-4">
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-body">
<div class="mb-3">
<label for="group-select" class="form-label">Select Group</label>
<select
id="group-select"
class="form-select"
id="group-select"
hx-get="/heats-content"
hx-target="#heats-container"
hx-target="#heats-content"
hx-trigger="change"
hx-include="this"
name="group_id"
hx-include="[name='group_id']"
>
<option value="">Select a group</option>
for _, group := range groups {
<option value={ strconv.FormatInt(group.ID, 10) } selected?={ group.ID == selectedGroupID }>
<option
value={ strconv.FormatInt(group.ID, 10) }
selected?={ group.ID == selectedGroupID }
>
{ group.Name }
</option>
}
</select>
</div>
<div id="heats-container">
<div id="heats-content">
if selectedGroupID > 0 {
@HeatsContent(selectedGroupID, groups, db)
} else {
<div class="alert alert-info">
<p class="mb-0">Please select a group to generate heats.</p>
</div>
@HeatsContent([]models.Heat{}, []models.Racer{})
}
</div>
</div>
}
}
templ HeatsContent(groupID int64, groups []models.Group, db *db.DB) {
// Filter racers by group
{{ groupRacers, _ := db.GetRacersByGroup(groupID) }}
<div class="card">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center mb-4">
<h2 class="card-title">
Heats for { getGroupName(groups, groupID) } ({ strconv.Itoa(len(groupRacers)) } racers)
</h2>
<div>
<button
class="btn btn-primary me-2"
hx-post={ "/api/heats/generate?group_id=" + strconv.FormatInt(groupID, 10) }
hx-target="#heats-list"
hx-swap="innerHTML"
>
Regenerate Heats
</button>
<button
class="btn btn-success"
hx-post={ "/api/heats/save?group_id=" + strconv.FormatInt(groupID, 10) }
hx-target="#save-status"
>
Save Heats
</button>
</div>
</div>
<div id="save-status" class="mb-4"></div>
if len(groupRacers) == 0 {
<div class="alert alert-warning mb-4">
<p class="mb-0">No racers in this group. Add racers to generate heats.</p>
</div>
} else {
<div id="heats-list">
@GeneratedHeats(groupRacers)
</div>
}
</div>
</div>
}
templ GeneratedHeats(racers []models.Racer) {
// Convert db.Racer to derby.Racer for heat generation
{{
var derbyRacers []derby.Racer
for _, racer := range racers {
derbyRacers = append(derbyRacers, derby.CreateRacer(racer.ID, racer.FirstName, racer.LastName, racer.CarNumber))
}
var heats = derby.GenerateHeats(derbyRacers)
}}
if len(heats) == 0 {
<div class="alert alert-warning">
<p class="mb-0">No heats could be generated. Please add more racers.</p>
</div>
templ HeatsContent(heats []models.Heat, racers []models.Racer) {
if len(racers) == 0 {
<div class="alert alert-info">No racers in this group yet.</div>
} else {
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4">
for _, heat := range heats {
<div class="col">
<div class="card h-100">
<div class="card-body">
<h3 class="card-title mb-3">Heat { strconv.Itoa(heat.HeatNum) }</h3>
<table class="table table-sm">
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<th>Lane</th>
<th>Racer</th>
<th>Car #</th>
<th>Heat</th>
<th>Lane 1</th>
<th>Lane 2</th>
<th>Lane 3</th>
<th>Lane 4</th>
</tr>
</thead>
<tbody>
for i, heat := range heats {
<tr>
<td>1</td>
<td>{ strconv.Itoa(i + 1) }</td>
<td>{ getRacerName(racers, heat.Lane1ID) }</td>
<td>{ getRacerCarNumber(racers, heat.Lane1ID) }</td>
</tr>
<tr>
<td>2</td>
<td>{ getRacerName(racers, heat.Lane2ID) }</td>
<td>{ getRacerCarNumber(racers, heat.Lane2ID) }</td>
</tr>
<tr>
<td>3</td>
<td>{ getRacerName(racers, heat.Lane3ID) }</td>
<td>{ getRacerCarNumber(racers, heat.Lane3ID) }</td>
</tr>
<tr>
<td>4</td>
<td>{ getRacerName(racers, heat.Lane4ID) }</td>
<td>{ getRacerCarNumber(racers, heat.Lane4ID) }</td>
</tr>
}
</tbody>
</table>
<div class="mt-3">
<button
class="btn btn-primary"
hx-post="/api/heats"
hx-include="[name='group_id']"
hx-target="#heats-content"
>
Save Heats
</button>
</div>
</div>
</div>
}
</div>
}
}
func getGroupName(groups []models.Group, groupID int64) string {
for _, group := range groups {
if group.ID == groupID {
return group.Name
}
}
return "Unknown Group"
}
func getRacerName(racers []models.Racer, racerID *int64) string {
if racerID == nil {
return "Empty"
}
for _, racer := range racers {
if racer.ID == *racerID {
return racer.FirstName + " " + racer.LastName
}
}
return "Unknown Racer"
}
func getRacerCarNumber(racers []models.Racer, racerID *int64) string {
if racerID == nil {
return "-"
}
for _, racer := range racers {
if racer.ID == *racerID {
return racer.CarNumber
func getRacerName(racers []models.Racer, id int64) string {
for _, r := range racers {
if r.ID == id {
return r.FirstName + " " + r.LastName
}
}
return "-"
return "TBD"
}

@ -11,7 +11,6 @@ import templruntime "github.com/a-h/templ/runtime"
import (
"strconv"
"track-gopher/db"
"track-gopher/derby"
"track-gopher/models"
)
@ -48,7 +47,7 @@ func Heats(groups []models.Group, selectedGroupID int64, db *db.DB) templ.Compon
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"container py-4\"><h1 class=\"mb-4\">Race Heats Generator</h1><div class=\"mb-4\"><label for=\"group-select\" class=\"form-label\">Select Group</label> <select id=\"group-select\" class=\"form-select\" hx-get=\"/heats-content\" hx-target=\"#heats-container\" hx-trigger=\"change\" hx-include=\"this\" name=\"group_id\"><option value=\"\">Select a group</option> ")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"container py-4\"><h1 class=\"mb-4\">Race Heats</h1><div class=\"row\"><div class=\"col-md-12\"><div class=\"card\"><div class=\"card-body\"><div class=\"mb-3\"><label for=\"group-select\" class=\"form-label\">Select Group</label> <select class=\"form-select\" id=\"group-select\" hx-get=\"/heats-content\" hx-target=\"#heats-content\" hx-trigger=\"change\" hx-include=\"[name=&#39;group_id&#39;]\"><option value=\"\">Select a group</option> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -60,7 +59,7 @@ func Heats(groups []models.Group, selectedGroupID int64, db *db.DB) templ.Compon
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.FormatInt(group.ID, 10))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 28, Col: 53}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 31, Col: 50}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
@ -83,7 +82,7 @@ func Heats(groups []models.Group, selectedGroupID int64, db *db.DB) templ.Compon
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(group.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 29, Col: 19}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 34, Col: 23}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
@ -94,22 +93,17 @@ func Heats(groups []models.Group, selectedGroupID int64, db *db.DB) templ.Compon
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</select></div><div id=\"heats-container\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</select></div><div id=\"heats-content\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if selectedGroupID > 0 {
templ_7745c5c3_Err = HeatsContent(selectedGroupID, groups, db).Render(ctx, templ_7745c5c3_Buffer)
templ_7745c5c3_Err = HeatsContent([]models.Heat{}, []models.Racer{}).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<div class=\"alert alert-info\"><p class=\"mb-0\">Please select a group to generate heats.</p></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</div></div>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div></div></div></div></div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -123,7 +117,7 @@ func Heats(groups []models.Group, selectedGroupID int64, db *db.DB) templ.Compon
})
}
func HeatsContent(groupID int64, groups []models.Group, db *db.DB) templ.Component {
func HeatsContent(heats []models.Heat, racers []models.Racer) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
@ -144,252 +138,88 @@ func HeatsContent(groupID int64, groups []models.Group, db *db.DB) templ.Compone
templ_7745c5c3_Var5 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
groupRacers, _ := db.GetRacersByGroup(groupID)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<div class=\"card\"><div class=\"card-body\"><div class=\"d-flex justify-content-between align-items-center mb-4\"><h2 class=\"card-title\">Heats for ")
if len(racers) == 0 {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<div class=\"alert alert-info\">No racers in this group yet.</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<div class=\"table-responsive\"><table class=\"table table-bordered\"><thead><tr><th>Heat</th><th>Lane 1</th><th>Lane 2</th><th>Lane 3</th><th>Lane 4</th></tr></thead> <tbody>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for i, heat := range heats {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<tr><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(getGroupName(groups, groupID))
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(i + 1))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 56, Col: 46}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 71, Col: 32}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, " (")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(len(groupRacers)))
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(getRacerName(racers, heat.Lane1ID))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 56, Col: 82}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 72, Col: 47}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, " racers)</h2><div><button class=\"btn btn-primary me-2\" hx-post=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs("/api/heats/generate?group_id=" + strconv.FormatInt(groupID, 10))
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(getRacerName(racers, heat.Lane2ID))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 61, Col: 80}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 73, Col: 47}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "\" hx-target=\"#heats-list\" hx-swap=\"innerHTML\">Regenerate Heats</button> <button class=\"btn btn-success\" hx-post=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs("/api/heats/save?group_id=" + strconv.FormatInt(groupID, 10))
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(getRacerName(racers, heat.Lane3ID))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 69, Col: 76}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 74, Col: 47}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "\" hx-target=\"#save-status\">Save Heats</button></div></div><div id=\"save-status\" class=\"mb-4\"></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if len(groupRacers) == 0 {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<div class=\"alert alert-warning mb-4\"><p class=\"mb-0\">No racers in this group. Add racers to generate heats.</p></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<div id=\"heats-list\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = GeneratedHeats(groupRacers).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
func GeneratedHeats(racers []models.Racer) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var10 := templ.GetChildren(ctx)
if templ_7745c5c3_Var10 == nil {
templ_7745c5c3_Var10 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
var derbyRacers []derby.Racer
for _, racer := range racers {
derbyRacers = append(derbyRacers, derby.CreateRacer(racer.ID, racer.FirstName, racer.LastName, racer.CarNumber))
}
var heats = derby.GenerateHeats(derbyRacers)
if len(heats) == 0 {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<div class=\"alert alert-warning\"><p class=\"mb-0\">No heats could be generated. Please add more racers.</p></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<div class=\"row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, heat := range heats {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<div class=\"col\"><div class=\"card h-100\"><div class=\"card-body\"><h3 class=\"card-title mb-3\">Heat ")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var11 string
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(heat.HeatNum))
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(getRacerName(racers, heat.Lane4ID))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 112, Col: 68}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 75, Col: 47}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</h3><table class=\"table table-sm\"><thead><tr><th>Lane</th><th>Racer</th><th>Car #</th></tr></thead> <tbody><tr><td>1</td><td>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</td></tr>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var12 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(getRacerName(racers, heat.Lane1ID))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 124, Col: 50}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var13 string
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(getRacerCarNumber(racers, heat.Lane1ID))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 125, Col: 55}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</td></tr><tr><td>2</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var14 string
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(getRacerName(racers, heat.Lane2ID))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 129, Col: 50}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var15 string
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(getRacerCarNumber(racers, heat.Lane2ID))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 130, Col: 55}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</td></tr><tr><td>3</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var16 string
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(getRacerName(racers, heat.Lane3ID))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 134, Col: 50}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var17 string
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(getRacerCarNumber(racers, heat.Lane3ID))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 135, Col: 55}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</td></tr><tr><td>4</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var18 string
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(getRacerName(racers, heat.Lane4ID))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 139, Col: 50}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var19 string
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(getRacerCarNumber(racers, heat.Lane4ID))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/heats.templ`, Line: 140, Col: 55}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "</td></tr></tbody></table></div></div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "</div>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</tbody></table><div class=\"mt-3\"><button class=\"btn btn-primary\" hx-post=\"/api/heats\" hx-include=\"[name=&#39;group_id&#39;]\" hx-target=\"#heats-content\">Save Heats</button></div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -398,39 +228,13 @@ func GeneratedHeats(racers []models.Racer) templ.Component {
})
}
func getGroupName(groups []models.Group, groupID int64) string {
for _, group := range groups {
if group.ID == groupID {
return group.Name
}
}
return "Unknown Group"
}
func getRacerName(racers []models.Racer, racerID *int64) string {
if racerID == nil {
return "Empty"
}
for _, racer := range racers {
if racer.ID == *racerID {
return racer.FirstName + " " + racer.LastName
}
}
return "Unknown Racer"
}
func getRacerCarNumber(racers []models.Racer, racerID *int64) string {
if racerID == nil {
return "-"
}
for _, racer := range racers {
if racer.ID == *racerID {
return racer.CarNumber
func getRacerName(racers []models.Racer, id int64) string {
for _, r := range racers {
if r.ID == id {
return r.FirstName + " " + r.LastName
}
}
return "-"
return "TBD"
}
var _ = templruntime.GeneratedTemplate

Loading…
Cancel
Save