DustyP 9 months ago
parent 7834ceb883
commit 67889dc595

@ -142,6 +142,9 @@ func (s *Server) routes() {
// Main page // Main page
s.router.Get("/", s.handleIndex()) s.router.Get("/", s.handleIndex())
// Add racers list route
s.router.Get("/admin/racers/list", s.handleRacersList())
} }
// Start starts the web server // Start starts the web server
@ -602,9 +605,11 @@ func (s *Server) handleCreateRacer() http.HandlerFunc {
return return
} }
// Return success s.logger.Info("Racer created", "id", id)
w.WriteHeader(http.StatusCreated)
fmt.Fprintf(w, `{"id":%d}`, id) // Return success message
w.Header().Set("Content-Type", "text/html")
w.Write([]byte(`<div class="alert alert-success">Racer added successfully!</div>`))
} }
} }
@ -840,3 +845,31 @@ func (s *Server) handleSaveHeats() http.HandlerFunc {
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.Write([]byte(`<div class="bg-green-100 p-4 rounded-lg mb-4"><p class="text-green-800">Heats saved successfully!</p></div>`))
} }
} }
// handleRacersList renders the racers list component
func (s *Server) handleRacersList() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Get racers and groups
racers, 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)
return
}
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)
return
}
// Render just the racers list component
component := templates.RacersList(racers, groups)
if err := component.Render(r.Context(), w); err != nil {
s.logger.Error("Failed to render racers list", "error", err)
http.Error(w, "Failed to render racers list", http.StatusInternalServerError)
return
}
}
}

@ -199,4 +199,53 @@ func getGroupNameForRacer(groups []models.Group, groupID int64) string {
} }
} }
return "Unknown Group" return "Unknown Group"
}
templ RacersList(racers []models.Racer, groups []models.Group) {
if len(racers) == 0 {
<div class="alert alert-info">
<p class="mb-0">No racers added yet.</p>
</div>
} else {
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Name</th>
<th>Car #</th>
<th>Group</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
for _, racer := range racers {
<tr>
<td>{ racer.FirstName + " " + racer.LastName }</td>
<td>{ racer.CarNumber }</td>
<td>{ getGroupNameForRacer(groups, racer.GroupID) }</td>
<td>
<div class="btn-group btn-group-sm">
<button
class="btn btn-outline-primary"
hx-get={ "/admin/racers/edit/" + strconv.FormatInt(racer.ID, 10) }
hx-target="#racer-form-container"
>
Edit
</button>
<button
class="btn btn-outline-danger"
hx-delete={ "/api/racers/" + strconv.FormatInt(racer.ID, 10) }
hx-target="#racers-list"
hx-confirm={ "Are you sure you want to delete " + racer.FirstName + " " + racer.LastName + "?" }
>
Delete
</button>
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
}
} }

@ -259,4 +259,128 @@ func getGroupNameForRacer(groups []models.Group, groupID int64) string {
return "Unknown Group" return "Unknown Group"
} }
func RacersList(racers []models.Racer, groups []models.Group) 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_Var13 := templ.GetChildren(ctx)
if templ_7745c5c3_Var13 == nil {
templ_7745c5c3_Var13 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
if len(racers) == 0 {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "<div class=\"alert alert-info\"><p class=\"mb-0\">No racers added yet.</p></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "<div class=\"table-responsive\"><table class=\"table table-striped table-hover\"><thead><tr><th>Name</th><th>Car #</th><th>Group</th><th>Actions</th></tr></thead> <tbody>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, racer := range racers {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<tr><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var14 string
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(racer.FirstName + " " + racer.LastName)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/admin.templ`, Line: 223, Col: 51}
}
_, 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, 27, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var15 string
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(racer.CarNumber)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/admin.templ`, Line: 224, Col: 28}
}
_, 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, 28, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var16 string
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(getGroupNameForRacer(groups, racer.GroupID))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/admin.templ`, Line: 225, Col: 56}
}
_, 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, 29, "</td><td><div class=\"btn-group btn-group-sm\"><button class=\"btn btn-outline-primary\" hx-get=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var17 string
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs("/admin/racers/edit/" + strconv.FormatInt(racer.ID, 10))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/admin.templ`, Line: 230, Col: 74}
}
_, 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, 30, "\" hx-target=\"#racer-form-container\">Edit</button> <button class=\"btn btn-outline-danger\" hx-delete=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var18 string
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs("/api/racers/" + strconv.FormatInt(racer.ID, 10))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/admin.templ`, Line: 237, Col: 70}
}
_, 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, 31, "\" hx-target=\"#racers-list\" hx-confirm=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var19 string
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs("Are you sure you want to delete " + racer.FirstName + " " + racer.LastName + "?")
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/admin.templ`, Line: 239, Col: 104}
}
_, 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, 32, "\">Delete</button></div></td></tr>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "</tbody></table></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
return nil
})
}
var _ = templruntime.GeneratedTemplate var _ = templruntime.GeneratedTemplate

@ -134,11 +134,19 @@ templ RegisterForm(groups []models.Group) {
<h3 class="h6 mb-0">Add New Racer</h3> <h3 class="h6 mb-0">Add New Racer</h3>
</div> </div>
<div class="card-body"> <div class="card-body">
<div id="racer-form-message"></div>
<form <form
id="racer-form"
hx-post="/api/racers" hx-post="/api/racers"
hx-target="#racers-list" hx-target="#racer-form-message"
hx-swap="innerHTML" hx-swap="innerHTML"
hx-on::after-request="this.reset(); document.getElementById('racer-form-container').style.display = 'none';" hx-on::after-request="if(event.detail.successful) {
document.getElementById('racer-form').reset();
setTimeout(function() {
document.getElementById('racer-form-message').innerHTML = '';
loadRacersList();
}, 3000);
}"
> >
<!-- Form fields for racer registration --> <!-- Form fields for racer registration -->
<div class="mb-3"> <div class="mb-3">
@ -173,4 +181,10 @@ templ RegisterForm(groups []models.Group) {
</form> </form>
</div> </div>
</div> </div>
<script>
function loadRacersList() {
htmx.ajax('GET', '/admin/racers/list', {target: '#racers-list'});
}
</script>
} }

@ -100,7 +100,7 @@ func RegisterForm(groups []models.Group) templ.Component {
templ_7745c5c3_Var4 = templ.NopComponent templ_7745c5c3_Var4 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<div class=\"card\"><div class=\"card-header\"><h3 class=\"h6 mb-0\">Add New Racer</h3></div><div class=\"card-body\"><form hx-post=\"/api/racers\" hx-target=\"#racers-list\" hx-swap=\"innerHTML\" hx-on::after-request=\"this.reset(); document.getElementById(&#39;racer-form-container&#39;).style.display = &#39;none&#39;;\"><!-- Form fields for racer registration --><div class=\"mb-3\"><label for=\"first-name\" class=\"form-label\">First Name</label> <input type=\"text\" class=\"form-control\" id=\"first-name\" name=\"first_name\" required></div><div class=\"mb-3\"><label for=\"last-name\" class=\"form-label\">Last Name</label> <input type=\"text\" class=\"form-control\" id=\"last-name\" name=\"last_name\" required></div><div class=\"mb-3\"><label for=\"car-number\" class=\"form-label\">Car Number</label> <input type=\"text\" class=\"form-control\" id=\"car-number\" name=\"car_number\" required></div><div class=\"mb-3\"><label for=\"car-weight\" class=\"form-label\">Car Weight (oz)</label> <input type=\"number\" step=\"0.01\" class=\"form-control\" id=\"car-weight\" name=\"car_weight\" required></div><div class=\"mb-3\"><label for=\"group-id\" class=\"form-label\">Group</label> <select class=\"form-select\" id=\"group-id\" name=\"group_id\" required><option value=\"\">Select a group</option> ") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<div class=\"card\"><div class=\"card-header\"><h3 class=\"h6 mb-0\">Add New Racer</h3></div><div class=\"card-body\"><div id=\"racer-form-message\"></div><form id=\"racer-form\" hx-post=\"/api/racers\" hx-target=\"#racer-form-message\" hx-swap=\"innerHTML\" hx-on::after-request=\"if(event.detail.successful) { \r\n\t\t\t\t\tdocument.getElementById(&#39;racer-form&#39;).reset(); \r\n\t\t\t\t\tsetTimeout(function() {\r\n\t\t\t\t\t\tdocument.getElementById(&#39;racer-form-message&#39;).innerHTML = &#39;&#39;;\r\n\t\t\t\t\t\tloadRacersList();\r\n\t\t\t\t\t}, 3000);\r\n\t\t\t\t}\"><!-- Form fields for racer registration --><div class=\"mb-3\"><label for=\"first-name\" class=\"form-label\">First Name</label> <input type=\"text\" class=\"form-control\" id=\"first-name\" name=\"first_name\" required></div><div class=\"mb-3\"><label for=\"last-name\" class=\"form-label\">Last Name</label> <input type=\"text\" class=\"form-control\" id=\"last-name\" name=\"last_name\" required></div><div class=\"mb-3\"><label for=\"car-number\" class=\"form-label\">Car Number</label> <input type=\"text\" class=\"form-control\" id=\"car-number\" name=\"car_number\" required></div><div class=\"mb-3\"><label for=\"car-weight\" class=\"form-label\">Car Weight (oz)</label> <input type=\"number\" step=\"0.01\" class=\"form-control\" id=\"car-weight\" name=\"car_weight\" required></div><div class=\"mb-3\"><label for=\"group-id\" class=\"form-label\">Group</label> <select class=\"form-select\" id=\"group-id\" name=\"group_id\" required><option value=\"\">Select a group</option> ")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -112,7 +112,7 @@ func RegisterForm(groups []models.Group) templ.Component {
var templ_7745c5c3_Var5 string var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.FormatInt(group.ID, 10)) templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.FormatInt(group.ID, 10))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/register.templ`, Line: 165, Col: 54} return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/register.templ`, Line: 173, Col: 54}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -125,7 +125,7 @@ func RegisterForm(groups []models.Group) templ.Component {
var templ_7745c5c3_Var6 string var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(group.Name) templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(group.Name)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/register.templ`, Line: 165, Col: 69} return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/register.templ`, Line: 173, Col: 69}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -136,7 +136,7 @@ func RegisterForm(groups []models.Group) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</select></div><div class=\"d-flex justify-content-end\"><button type=\"button\" class=\"btn btn-secondary me-2\" onclick=\"document.getElementById(&#39;racer-form-container&#39;).style.display = &#39;none&#39;;\">Cancel</button> <button type=\"submit\" class=\"btn btn-primary\">Save Racer</button></div></form></div></div>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</select></div><div class=\"d-flex justify-content-end\"><button type=\"button\" class=\"btn btn-secondary me-2\" onclick=\"document.getElementById(&#39;racer-form-container&#39;).style.display = &#39;none&#39;;\">Cancel</button> <button type=\"submit\" class=\"btn btn-primary\">Save Racer</button></div></form></div></div><script>\r\n\t\tfunction loadRacersList() {\r\n\t\t\thtmx.ajax('GET', '/admin/racers/list', {target: '#racers-list'});\r\n\t\t}\r\n\t</script>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }

Loading…
Cancel
Save