package bookings import ( "log" "net/http" "crussell/db" "crussell/mw" ) // AdminCancelReservationHandler releases the authenticated admin's active // reservation (walk-in or call-in) by deleting their RESERVATION:admin entries // from time_blockers. It does NOT create a booking — it only releases the // temporary slot hold. // // Mirrors CancelReservationHandler but targets RESERVATION:admin:% (created by // AdminReserveSlotHandler). The user-facing DELETE /api/bookings/reserve only // matches RESERVATION:user:% — it cannot release admin reservations, which // would otherwise leak the slot for the full 15-min TTL. // // DELETE /api/admin/bookings/reserve func AdminCancelReservationHandler(w http.ResponseWriter, r *http.Request) { adminID, ok := r.Context().Value(mw.UserIDKey).(string) if !ok || adminID == "" { log.Printf("AdminCancelReservationHandler: admin ID not found in context") http.Error(w, "Authentication required", http.StatusUnauthorized) return } _, err := db.Conn.Exec(r.Context(), ` DELETE FROM time_blockers WHERE created_by = $1 AND description LIKE 'RESERVATION:admin:%' `, adminID) if err != nil { log.Printf("AdminCancelReservationHandler: failed to delete reservation for admin %s: %v", adminID, err) http.Error(w, "Internal server error", http.StatusInternalServerError) return } mw.RespondJSON(w, http.StatusOK, map[string]string{"status": "reservation cancelled"}) }