feat: implement API handlers for MVP endpoints (Task 5)

- Create cmd/api/handlers.go with HTTP handlers for all MVP endpoints
- Implement GET /v1/cities?query= city autocomplete
- Implement GET /v1/cities/{id}/stations city stations including neighbors
- Implement POST /v1/routes/search route search with Pareto-optimal results
- Implement GET /v1/routes/{search_id}/{route_id}/geojson route geometry
- Implement GET /v1/stations/{id}/status station status endpoint
- Add handler tests with success and error cases
- All existing tests pass
This commit is contained in:
2026-08-13 20:26:28 +03:00
parent 32e7cef4d5
commit 1bfe659d2c
4 changed files with 519 additions and 14 deletions

View File

@@ -162,8 +162,8 @@ func (g *Graph) buildAdjacencyList() map[string][]*Edge {
return adj
}
// nodesByID returns a node by its ID from the graph's nodes.
func (g *Graph) nodesByID(id string) *Node {
// NodesByID returns a node by its ID from the graph's nodes.
func (g *Graph) NodesByID(id string) *Node {
for _, n := range g.nodes {
if n.ID == id {
return n
@@ -180,8 +180,8 @@ func (g *Graph) FindRoute(originID, destID string, opts SearchOptions) *Itinerar
// BFS with transfer tracking
// State: (nodeID, transfersUsed, accumulatedDuration, lastArrivalTime, path)
startNode := g.nodesByID(originID)
destNode := g.nodesByID(destID)
startNode := g.NodesByID(originID)
destNode := g.NodesByID(destID)
if startNode == nil || destNode == nil {
return nil
@@ -275,7 +275,7 @@ func (g *Graph) FindRoute(originID, destID string, opts SearchOptions) *Itinerar
// First leg: From is the origin node, subsequent legs use the previous edge's To
if len(current.itinerary.Legs) == 0 {
newLegs[len(current.itinerary.Legs)] = RouteLeg{
From: g.nodesByID(originID), // origin node as From
From: g.NodesByID(originID), // origin node as From
To: nextNode,
Duration: edge.Duration,
Transport: edge.Transport,