DustyP 9 months ago
parent bb6f3dd71f
commit 30db05945f

@ -149,6 +149,16 @@ func (db *DB) GetRacers() ([]models.Racer, error) {
return racers, nil return racers, nil
} }
// IsCarNumberUnique checks if a car number is already in use
func (db *DB) IsCarNumberUnique(carNumber string) (bool, error) {
var count int
err := db.QueryRow("SELECT COUNT(*) FROM racers WHERE car_number = ?", carNumber).Scan(&count)
if err != nil {
return false, err
}
return count == 0, nil
}
// GetRacersByGroup returns racers in a specific group // GetRacersByGroup returns racers in a specific group
func (db *DB) GetRacersByGroup(groupID int64) ([]models.Racer, error) { func (db *DB) GetRacersByGroup(groupID int64) ([]models.Racer, error) {
rows, err := db.Query(` rows, err := db.Query(`

@ -150,6 +150,9 @@ func (s *Server) routes() {
// Add admin events route // Add admin events route
s.router.Get("/api/admin-events", s.handleAdminEvents()) s.router.Get("/api/admin-events", s.handleAdminEvents())
// Add validate car number route
s.router.Get("/api/validate/car-number", s.handleValidateCarNumber())
} }
// Start starts the web server // Start starts the web server
@ -908,3 +911,27 @@ func (s *Server) handleAdminEvents() http.HandlerFunc {
} }
} }
} }
// handleValidateCarNumber handles the validate car number API endpoint
func (s *Server) handleValidateCarNumber() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
carNumber := r.URL.Query().Get("value")
if carNumber == "" {
http.Error(w, "Car number is required", http.StatusBadRequest)
return
}
isUnique, err := s.db.IsCarNumberUnique(carNumber)
if err != nil {
s.logger.Error("Failed to check car number uniqueness", "error", err)
http.Error(w, "Failed to validate car number", http.StatusInternalServerError)
return
}
if !isUnique {
w.Write([]byte("Car number is already in use"))
} else {
w.WriteHeader(http.StatusOK)
}
}
}

@ -33,6 +33,7 @@ templ RegisterForm(groups []models.Group, isAdmin bool) {
hx-post="/api/racers" hx-post="/api/racers"
hx-target="#racer-form-message" hx-target="#racer-form-message"
hx-swap="innerHTML" hx-swap="innerHTML"
hx-on::before-request="return validateForm()"
hx-on::after-request="if(event.detail.successful) { hx-on::after-request="if(event.detail.successful) {
document.getElementById('racer-form').reset(); document.getElementById('racer-form').reset();
setTimeout(function() { setTimeout(function() {
@ -55,7 +56,24 @@ templ RegisterForm(groups []models.Group, isAdmin bool) {
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="car-number" class="form-label">Car Number</label> <label for="car-number" class="form-label">Car Number</label>
<input type="text" class="form-control" id="car-number" name="car_number" required/> <input
type="text"
class="form-control"
id="car-number"
name="car_number"
required
hx-get="/api/validate/car-number"
hx-trigger="change"
hx-target="next .invalid-feedback"
hx-indicator="#car-number-indicator"
/>
<div class="invalid-feedback"></div>
<div id="car-number-indicator" class="htmx-indicator">
<div class="spinner-border spinner-border-sm text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<small>Checking availability...</small>
</div>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="car-weight" class="form-label">Car Weight (oz)</label> <label for="car-weight" class="form-label">Car Weight (oz)</label>
@ -81,4 +99,20 @@ templ RegisterForm(groups []models.Group, isAdmin bool) {
</form> </form>
</div> </div>
</div> </div>
} }
<script>
function validateForm() {
const carNumberInput = document.getElementById('car-number');
const errorDiv = carNumberInput.nextElementSibling;
if (errorDiv.textContent.trim() !== '') {
// Show error message more prominently
errorDiv.classList.add('d-block');
carNumberInput.classList.add('is-invalid');
return false;
}
return true;
}
</script>
Loading…
Cancel
Save