// routes/routes.go package routes import ( "net/http" "github.com/go-chi/chi/v5" "gorm.io/gorm" "api_bb/internal/config" "api_bb/internal/handlers" "api_bb/internal/repository" "api_bb/internal/service" "api_bb/pkg/logger" "api_bb/pkg/middleware" ) func SetupRouter(db *gorm.DB, config *config.Config) http.Handler { r := chi.NewRouter() // Apply common middleware for _, m := range middleware.CommonMiddleware() { r.Use(m) } // handler h := handlers.NewHandler(db, config) // Serve static files (avatars) r.Handle("/uploads/*", http.StripPrefix("/uploads/", http.FileServer(http.Dir("./uploads")))) // Initialize repositories userRepo := repository.NewUserRepository(db) // Initialize logger baseLogger := logger.NewWrapper(logger.Get()) // Initialize services with logger jwtService := service.NewJWTService(config.JWTSecret) // Email service initialization with fallback var emailHandler *handlers.EmailHandler if h.EmailHandler() != nil { emailHandler = h.EmailHandler() } // Health routes r.Route("/api", func(r chi.Router) { r.Get("/health", h.HealthHandler().HealthCheck) r.Get("/check", h.HealthHandler().Check) }) // API v1 routes r.Route("/v1", func(r chi.Router) { // Email verification (public) - только если доступен if emailHandler != nil { r.Get("/verify-email", emailHandler.VerifyEmail) } // Public auth routes r.Route("/auth", func(r chi.Router) { r.Post("/register", h.AuthHandler().Register) r.Post("/login", h.AuthHandler().Login) r.Post("/logout", h.AuthHandler().Logout) // Email routes (only if email handler is available) if emailHandler != nil { r.Post("/verify-email/resend", emailHandler.ResendVerification) r.Post("/password-reset/request", emailHandler.RequestPasswordReset) r.Post("/password-reset/confirm", emailHandler.ConfirmPasswordReset) } }) // Публичные маршруты для достижений (если нужны) r.Route("/achievements", func(r chi.Router) { // Публичные маршруты для просмотра достижений других пользователей r.Get("/user/{userID}", h.UserAchievementHandler().GetPublicUserAchievements) r.Get("/user/{userID}/summary", h.UserAchievementHandler().GetPublicUserAchievementsSummary) r.Get("/user/{userID}/recent", h.UserAchievementHandler().GetPublicRecentAchievements) }) // Protected routes r.Route("/user", func(r chi.Router) { r.Use(middleware.AuthMiddleware(jwtService, userRepo)) r.Use(middleware.RequireAuth) // user profile routes r.Get("/profile", h.UserHandler().GetProfile) r.Post("/editProfile", h.UserHandler().UpdateProfile) r.Get("/", h.UserHandler().GetUsers) // Все операции с аватарами теперь через AvatarHandler r.Route("/avatars", func(r chi.Router) { r.Post("/upload", h.AvatarHandler().UploadAvatar) r.Delete("/delete", h.AvatarHandler().DeleteAvatar) r.Get("/{filename}", h.AvatarHandler().GetAvatar) }) r.Route("/stats", func(r chi.Router) { r.Get("/", h.UserStatsHandler().GetUserStats) r.Get("/{userID}", h.UserStatsHandler().GetUserStatsByID) r.Post("/workout", h.UserStatsHandler().IncrementWorkout) r.Put("/personal-best", h.UserStatsHandler().UpdatePersonalBest) r.Post("/weekly/reset", h.UserStatsHandler().ResetWeeklyDistance) r.Post("/monthly/reset", h.UserStatsHandler().ResetMonthlyDistance) }) // Маршруты для тренировок r.Route("/workouts", func(r chi.Router) { r.Post("/", h.UserWorkoutHandler().CreateWorkout) r.Get("/", h.UserWorkoutHandler().GetWorkouts) r.Get("/stats", h.UserWorkoutHandler().GetWorkoutStats) r.Get("/type/{type}", h.UserWorkoutHandler().GetWorkoutsByType) r.Route("/{id}", func(r chi.Router) { r.Get("/", h.UserWorkoutHandler().GetWorkoutByID) r.Put("/", h.UserWorkoutHandler().UpdateWorkout) r.Delete("/", h.UserWorkoutHandler().DeleteWorkout) }) }) // Маршруты для достижений (achievements) r.Route("/achievements", func(r chi.Router) { // Создание нового достижения r.Post("/", h.UserAchievementHandler().CreateAchievement) // Получение всех достижений пользователя r.Get("/", h.UserAchievementHandler().GetUserAchievements) // Получение сводки по достижениям r.Get("/summary", h.UserAchievementHandler().GetUserAchievementsSummary) // Получение последних достижений (с опциональным лимитом) r.Get("/recent", h.UserAchievementHandler().GetRecentAchievements) // Получение достижений по типу r.Get("/type/{type}", h.UserAchievementHandler().GetAchievementsByType) // Операции с конкретным достижением r.Route("/{id}", func(r chi.Router) { // Получение достижения по ID r.Get("/", h.UserAchievementHandler().GetAchievementByID) // Обновление достижения r.Put("/", h.UserAchievementHandler().UpdateAchievement) // Удаление достижения r.Delete("/", h.UserAchievementHandler().DeleteAchievement) // Подтверждение достижения r.Patch("/verify", h.UserAchievementHandler().VerifyAchievement) }) }) // Personal Best routes r.Route("/personal-bests", func(r chi.Router) { // CRUD operations r.Post("/", h.PersonalBestHandler().CreatePersonalBest) r.Get("/", h.PersonalBestHandler().GetUserPersonalBests) r.Get("/recent", h.PersonalBestHandler().GetRecentPersonalBests) r.Get("/summary", h.PersonalBestHandler().GetPersonalBestsSummary) r.Post("/calculate-pace", h.PersonalBestHandler().CalculatePace) // Distance-specific routes r.Route("/distance/{distanceType}", func(r chi.Router) { r.Get("/", h.PersonalBestHandler().GetPersonalBestsByDistance) r.Get("/best", h.PersonalBestHandler().GetBestByDistance) }) // Individual personal best routes r.Route("/{id}", func(r chi.Router) { r.Get("/", h.PersonalBestHandler().GetPersonalBest) r.Put("/", h.PersonalBestHandler().UpdatePersonalBest) r.Delete("/", h.PersonalBestHandler().DeletePersonalBest) r.Patch("/verify", h.PersonalBestHandler().VerifyPersonalBest) }) }) // Маршруты для тренировочных планов (Training Plans) r.Route("/training-plans", func(r chi.Router) { // Создание нового тренировочного плана r.Post("/", h.TrainingPlanHandler().CreateTrainingPlan) // Получение всех тренировочных планов пользователя r.Get("/", h.TrainingPlanHandler().GetTrainingPlans) // Получение активного тренировочного плана r.Get("/active", h.TrainingPlanHandler().GetActiveTrainingPlan) // Обновление текущей недели плана r.Patch("/current-week", h.TrainingPlanHandler().UpdateCurrentWeek) // Операции с конкретным тренировочным планом r.Route("/{id}", func(r chi.Router) { // Получение тренировочного плана по ID r.Get("/", h.TrainingPlanHandler().GetTrainingPlanByID) // Обновление тренировочного плана r.Put("/", h.TrainingPlanHandler().UpdateTrainingPlan) // Удаление тренировочного плана r.Delete("/", h.TrainingPlanHandler().DeleteTrainingPlan) // Пометить план как завершенный r.Patch("/complete", h.TrainingPlanHandler().MarkTrainingPlanAsCompleted) }) }) }) r.Route("/news", func(r chi.Router) { // Публичные маршруты r.Get("/", h.NewsHandler().GetNews) r.Get("/{id}", h.NewsHandler().GetNewsByID) r.Get("/{id}/comments", h.NewsHandler().GetComments) r.Get("/check", h.HealthHandler().Check) // Защищенные маршруты r.Group(func(r chi.Router) { r.Use(middleware.AuthMiddleware(jwtService, userRepo)) r.Use(middleware.RequireAuth) // News EndPoints r.Post("/", h.NewsHandler().CreateNews) r.Put("/{id}", h.NewsHandler().UpdateNews) r.Delete("/{id}", h.NewsHandler().DeleteNews) r.Get("/my/news", h.NewsHandler().GetUserNews) r.Post("/{id}/comments", h.NewsHandler().CreateComment) r.Delete("/comments/{commentId}", h.NewsHandler().DeleteComment) r.Get("/check", h.HealthHandler().Check) }) }) // Маршруты для отзывов r.Route("/reviews", func(r chi.Router) { // Публичные маршруты r.Get("/", h.ReviewHandler().GetReviews) r.Get("/stats", h.ReviewHandler().GetReviewsStats) r.Get("/{id}", h.ReviewHandler().GetReviewByID) // Защищенные маршруты r.Group(func(r chi.Router) { r.Use(middleware.AuthMiddleware(jwtService, userRepo)) r.Use(middleware.RequireAuth) r.Post("/", h.ReviewHandler().CreateReview) r.Get("/my", h.ReviewHandler().GetMyReviews) r.Put("/{id}", h.ReviewHandler().UpdateReview) r.Delete("/{id}", h.ReviewHandler().DeleteReview) }) }) // Events r.Route("/events", func(r chi.Router) { // Публичные маршруты r.Get("/", h.EventHandler().GetAllEvents) r.Get("/upcoming", h.EventHandler().GetUpcomingEvents) r.Get("/type/{type}", h.EventHandler().GetEventsByType) r.Get("/{id}", h.EventHandler().GetEvent) r.Get("/{eventId}/availability", h.EventRegistrationHandler().CheckEventAvailability) // Защищенные маршруты (требуют аутентификации) r.Group(func(r chi.Router) { r.Use(middleware.AuthMiddleware(jwtService, userRepo)) r.Use(middleware.RequireAuth) // Регистрации пользователя r.Post("/register", h.EventRegistrationHandler().RegisterForEvent) r.Get("/my/registrations", h.EventRegistrationHandler().GetUserRegistrations) r.Delete("/registrations/{id}", h.EventRegistrationHandler().CancelRegistration) r.Get("/registrations/{id}", h.EventRegistrationHandler().GetRegistration) }) // Админские маршруты r.Group(func(r chi.Router) { r.Use(middleware.AuthMiddleware(jwtService, userRepo)) r.Use(middleware.RequireAuth) r.Use(middleware.AdminMiddleware) // Управление событиями r.Post("/", h.EventHandler().CreateEvent) r.Put("/{id}", h.EventHandler().UpdateEvent) r.Delete("/{id}", h.EventHandler().DeleteEvent) r.Patch("/{id}/registration-status", h.EventHandler().ToggleRegistrationStatus) // Управление регистрациями r.Get("/{eventId}/registrations", h.EventRegistrationHandler().GetEventRegistrations) r.Patch("/registrations/{id}/status", h.EventRegistrationHandler().UpdateRegistrationStatus) r.Patch("/registrations/{id}/result-time", h.EventRegistrationHandler().UpdateResultTime) }) }) }) // Логируем все зарегистрированные маршруты routeLogger := logger.NewRouteLogger(baseLogger) routeLogger.LogRoutes(r) return r }