package api import ( "net/http" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/jmoiron/sqlx" "workorders/internal/api/handlers" "workorders/internal/config" ) func NewRouter(cfg *config.Config, db *sqlx.DB) http.Handler { r := chi.NewRouter() r.Use(middleware.Logger) r.Use(middleware.Recoverer) r.Use(middleware.RealIP) r.Use(CORS) // Serve frontend static files r.Handle("/*", http.FileServer(http.Dir("./web"))) // Public routes — uploads served without auth (paths are UUIDs, not guessable) r.Handle("/uploads/*", http.StripPrefix("/uploads/", http.FileServer(http.Dir(cfg.UploadPath)))) // Public auth routes auth := handlers.NewAuthHandler(db, cfg) r.Post("/api/auth/login", auth.Login) // Protected API routes r.Group(func(r chi.Router) { r.Use(JWTAuth(cfg.JWTSecret)) r.Post("/api/auth/refresh", auth.Refresh) r.Get("/api/auth/me", handlers.Me) wo := handlers.NewWorkOrderHandler(db, cfg) r.Get("/api/work-orders", wo.List) r.Post("/api/work-orders", wo.Create) r.Get("/api/work-orders/{id}", wo.Get) r.Put("/api/work-orders/{id}", wo.Update) r.Delete("/api/work-orders/{id}", wo.Delete) r.Put("/api/work-orders/{id}/status", wo.UpdateStatus) step := handlers.NewStepHandler(db) r.Get("/api/work-orders/{id}/steps", step.List) r.Post("/api/work-orders/{id}/steps", step.Create) r.Put("/api/work-orders/{id}/steps/{sid}", step.Update) r.Post("/api/work-orders/{id}/steps/{sid}/complete", step.Complete) r.Post("/api/work-orders/{id}/steps/{sid}/uncomplete", step.Uncomplete) r.Delete("/api/work-orders/{id}/steps/{sid}", step.Delete) res := handlers.NewResourceHandler(db) r.Get("/api/work-orders/{id}/resources", res.List) r.Post("/api/work-orders/{id}/resources", res.Assign) r.Delete("/api/work-orders/{id}/resources/{rid}", res.Remove) att := handlers.NewAttachmentHandler(db, cfg) r.Get("/api/work-orders/{id}/attachments", att.List) r.Post("/api/work-orders/{id}/attachments", att.Upload) r.Delete("/api/work-orders/{id}/attachments/{aid}", att.Delete) acc := handlers.NewAccountingHandler(db) r.Get("/api/work-orders/{id}/accounting", acc.Get) r.Put("/api/work-orders/{id}/accounting", acc.Upsert) act := handlers.NewActivityHandler(db) r.Get("/api/work-orders/{id}/activity", act.List) prof := handlers.NewProfileHandler(db) r.Get("/api/profiles", prof.List) r.Post("/api/profiles", prof.Create) r.Get("/api/profiles/{id}", prof.Get) r.Put("/api/profiles/{id}", prof.Update) r.Delete("/api/profiles/{id}", prof.Delete) r.Get("/api/profiles/{id}/steps", prof.ListSteps) r.Post("/api/profiles/{id}/steps", prof.CreateStep) r.Put("/api/profiles/{id}/steps/{sid}", prof.UpdateStep) r.Delete("/api/profiles/{id}/steps/{sid}", prof.DeleteStep) r.Post("/api/work-orders/{id}/apply-profile/{profileId}", prof.Apply) reg := handlers.NewRegistryHandler(db) r.Get("/api/registry/people", reg.ListPeople) r.Post("/api/registry/people", reg.CreatePerson) r.Put("/api/registry/people/{id}", reg.UpdatePerson) r.Delete("/api/registry/people/{id}", reg.DeletePerson) r.Get("/api/registry/vehicles", reg.ListVehicles) r.Post("/api/registry/vehicles", reg.CreateVehicle) r.Put("/api/registry/vehicles/{id}", reg.UpdateVehicle) r.Delete("/api/registry/vehicles/{id}", reg.DeleteVehicle) r.Get("/api/registry/equipment", reg.ListEquipment) r.Post("/api/registry/equipment", reg.CreateEquipment) r.Put("/api/registry/equipment/{id}", reg.UpdateEquipment) r.Delete("/api/registry/equipment/{id}", reg.DeleteEquipment) r.Get("/api/registry/materials", reg.ListMaterials) r.Post("/api/registry/materials", reg.CreateMaterial) r.Put("/api/registry/materials/{id}", reg.UpdateMaterial) r.Delete("/api/registry/materials/{id}", reg.DeleteMaterial) }) return r }