package handlers import ( "net/http" "strings" "time" "github.com/google/uuid" "github.com/travelswitch/travelhub/backend/internal/models" ) // SearchFlights handles GET /api/flights. // // Query parameters: origin, destination (IATA codes), date (YYYY-MM-DD), // cabin, passengers, sort (price|duration|departure), limit, offset. func (h *Handler) SearchFlights(w http.ResponseWriter, r *http.Request) { id, ok := h.identity(w, r) if !ok { return } q := r.URL.Query() search := models.FlightSearch{ Origin: strings.ToUpper(strings.TrimSpace(q.Get("origin"))), Destination: strings.ToUpper(strings.TrimSpace(q.Get("destination"))), CabinClass: strings.TrimSpace(q.Get("cabin")), Passengers: intParam(r, "passengers", 1, 1, 9), SortBy: q.Get("sort"), Limit: intParam(r, "limit", 25, 1, 100), Offset: intParam(r, "offset", 0, 0, 100000), } if raw := strings.TrimSpace(q.Get("date")); raw != "" { // Parsed in the server's local zone, which is what an agent selling // from a desk in that zone means by "flights on the 12th". d, err := time.ParseInLocation("2006-01-02", raw, time.Local) if err != nil { writeError(w, http.StatusBadRequest, "date must be in YYYY-MM-DD format") return } search.DepartDate = &d } if search.CabinClass != "" && !validCabin(search.CabinClass) { writeError(w, http.StatusBadRequest, "cabin must be one of economy, premium_economy, business, first") return } flights, total, err := h.Repo.SearchFlights(r.Context(), id.Tenant.ID, search) if err != nil { h.fail(w, err, "search flights") return } writeJSON(w, http.StatusOK, page[models.Flight]{ Items: flights, Total: total, Limit: search.Limit, Offset: search.Offset, }) } // GetFlight handles GET /api/flights/{id}. func (h *Handler) GetFlight(w http.ResponseWriter, r *http.Request) { id, ok := h.identity(w, r) if !ok { return } flightID, err := uuid.Parse(r.PathValue("id")) if err != nil { writeError(w, http.StatusBadRequest, "invalid flight id") return } flight, err := h.Repo.FlightByID(r.Context(), id.Tenant.ID, flightID) if err != nil { h.fail(w, err, "get flight") return } writeJSON(w, http.StatusOK, flight) } // ListAirports handles GET /api/airports. func (h *Handler) ListAirports(w http.ResponseWriter, r *http.Request) { id, ok := h.identity(w, r) if !ok { return } airports, err := h.Repo.ListAirports(r.Context(), id.Tenant.ID) if err != nil { h.fail(w, err, "list airports") return } writeJSON(w, http.StatusOK, airports) } // ListAirlines handles GET /api/airlines. func (h *Handler) ListAirlines(w http.ResponseWriter, r *http.Request) { id, ok := h.identity(w, r) if !ok { return } airlines, err := h.Repo.ListAirlines(r.Context(), id.Tenant.ID) if err != nil { h.fail(w, err, "list airlines") return } writeJSON(w, http.StatusOK, airlines) } func validCabin(c string) bool { switch c { case "economy", "premium_economy", "business", "first": return true } return false }