mirror of
https://github.com/Dvorinka/Trackeep.git
synced 2026-06-04 12:32:58 +00:00
first test
This commit is contained in:
@@ -0,0 +1,303 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/trackeep/backend/config"
|
||||
"github.com/trackeep/backend/models"
|
||||
)
|
||||
|
||||
// GetCourses handles GET /api/v1/courses
|
||||
func GetCourses(c *gin.Context) {
|
||||
db := config.GetDB()
|
||||
var courses []models.Course
|
||||
|
||||
// Parse query parameters
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "20"))
|
||||
category := c.Query("category")
|
||||
level := c.Query("level")
|
||||
isZTM := c.Query("is_ztm")
|
||||
|
||||
// Validate pagination
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if limit < 1 || limit > 100 {
|
||||
limit = 20
|
||||
}
|
||||
|
||||
offset := (page - 1) * limit
|
||||
|
||||
// Build query
|
||||
query := db.Where("is_active = ?", true)
|
||||
|
||||
if category != "" {
|
||||
query = query.Where("category = ?", category)
|
||||
}
|
||||
|
||||
if level != "" {
|
||||
query = query.Where("level = ?", level)
|
||||
}
|
||||
|
||||
if isZTM == "true" {
|
||||
query = query.Where("is_ztm_course = ?", true)
|
||||
}
|
||||
|
||||
// Get total count
|
||||
var total int64
|
||||
query.Model(&models.Course{}).Count(&total)
|
||||
|
||||
// Get courses with pagination
|
||||
if err := query.Order("is_featured DESC, rating DESC, students_count DESC").
|
||||
Offset(offset).Limit(limit).Find(&courses).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Failed to fetch courses",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Calculate pagination info
|
||||
totalPages := (total + int64(limit) - 1) / int64(limit)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"courses": courses,
|
||||
"pagination": gin.H{
|
||||
"current_page": page,
|
||||
"total_pages": totalPages,
|
||||
"total_count": total,
|
||||
"limit": limit,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// GetCourse handles GET /api/v1/courses/:id
|
||||
func GetCourse(c *gin.Context) {
|
||||
db := config.GetDB()
|
||||
id := c.Param("id")
|
||||
|
||||
var course models.Course
|
||||
if err := db.Where("id = ? AND is_active = ?", id, true).First(&course).Error; err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"error": "Course not found",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, course)
|
||||
}
|
||||
|
||||
// GetCourseBySlug handles GET /api/v1/courses/slug/:slug
|
||||
func GetCourseBySlug(c *gin.Context) {
|
||||
db := config.GetDB()
|
||||
slug := c.Param("slug")
|
||||
|
||||
var course models.Course
|
||||
if err := db.Where("slug = ? AND is_active = ?", slug, true).First(&course).Error; err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"error": "Course not found",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, course)
|
||||
}
|
||||
|
||||
// GetFeaturedCourses handles GET /api/v1/courses/featured
|
||||
func GetFeaturedCourses(c *gin.Context) {
|
||||
db := config.GetDB()
|
||||
var courses []models.Course
|
||||
|
||||
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))
|
||||
if limit < 1 || limit > 20 {
|
||||
limit = 10
|
||||
}
|
||||
|
||||
if err := db.Where("is_active = ? AND is_featured = ?", true, true).
|
||||
Order("rating DESC, students_count DESC").
|
||||
Limit(limit).Find(&courses).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Failed to fetch featured courses",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"courses": courses,
|
||||
"count": len(courses),
|
||||
})
|
||||
}
|
||||
|
||||
// GetZTMCourses handles GET /api/v1/courses/ztm
|
||||
func GetZTMCourses(c *gin.Context) {
|
||||
db := config.GetDB()
|
||||
var courses []models.Course
|
||||
|
||||
// Parse query parameters
|
||||
category := c.Query("category")
|
||||
level := c.Query("level")
|
||||
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "20"))
|
||||
if limit < 1 || limit > 50 {
|
||||
limit = 20
|
||||
}
|
||||
|
||||
// Build query
|
||||
query := db.Where("is_active = ? AND is_ztm_course = ?", true, true)
|
||||
|
||||
if category != "" {
|
||||
query = query.Where("category = ?", category)
|
||||
}
|
||||
|
||||
if level != "" {
|
||||
query = query.Where("level = ?", level)
|
||||
}
|
||||
|
||||
if err := query.Order("is_featured DESC, rating DESC, students_count DESC").
|
||||
Limit(limit).Find(&courses).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Failed to fetch ZTM courses",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"courses": courses,
|
||||
"count": len(courses),
|
||||
})
|
||||
}
|
||||
|
||||
// GetCourseCategories handles GET /api/v1/courses/categories
|
||||
func GetCourseCategories(c *gin.Context) {
|
||||
db := config.GetDB()
|
||||
|
||||
var categories []struct {
|
||||
Category string `json:"category"`
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
if err := db.Model(&models.Course{}).
|
||||
Where("is_active = ?", true).
|
||||
Select("category, COUNT(*) as count").
|
||||
Group("category").
|
||||
Order("count DESC").
|
||||
Find(&categories).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Failed to fetch course categories",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"categories": categories,
|
||||
})
|
||||
}
|
||||
|
||||
// SearchCourses handles POST /api/v1/courses/search
|
||||
func SearchCourses(c *gin.Context) {
|
||||
db := config.GetDB()
|
||||
|
||||
type SearchRequest struct {
|
||||
Query string `json:"query" binding:"required"`
|
||||
Category string `json:"category"`
|
||||
Level string `json:"level"`
|
||||
Limit int `json:"limit"`
|
||||
Page int `json:"page"`
|
||||
}
|
||||
|
||||
var req SearchRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Invalid request body",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Set defaults
|
||||
if req.Limit <= 0 || req.Limit > 50 {
|
||||
req.Limit = 20
|
||||
}
|
||||
if req.Page <= 0 {
|
||||
req.Page = 1
|
||||
}
|
||||
|
||||
offset := (req.Page - 1) * req.Limit
|
||||
|
||||
// Build search query
|
||||
query := db.Where("is_active = ? AND (title ILIKE ? OR description ILIKE ? OR topics::text ILIKE ?)",
|
||||
true, "%"+req.Query+"%", "%"+req.Query+"%", "%"+req.Query+"%")
|
||||
|
||||
if req.Category != "" {
|
||||
query = query.Where("category = ?", req.Category)
|
||||
}
|
||||
|
||||
if req.Level != "" {
|
||||
query = query.Where("level = ?", req.Level)
|
||||
}
|
||||
|
||||
// Get total count
|
||||
var total int64
|
||||
query.Model(&models.Course{}).Count(&total)
|
||||
|
||||
// Get courses
|
||||
var courses []models.Course
|
||||
if err := query.Order("is_featured DESC, rating DESC, students_count DESC").
|
||||
Offset(offset).Limit(req.Limit).Find(&courses).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Failed to search courses",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Calculate pagination info
|
||||
totalPages := (total + int64(req.Limit) - 1) / int64(req.Limit)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"courses": courses,
|
||||
"query": req.Query,
|
||||
"pagination": gin.H{
|
||||
"current_page": req.Page,
|
||||
"total_pages": totalPages,
|
||||
"total_count": total,
|
||||
"limit": req.Limit,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// GetLearningPathCourses handles GET /api/v1/learning-paths/:id/courses
|
||||
func GetLearningPathCourses(c *gin.Context) {
|
||||
db := config.GetDB()
|
||||
learningPathID := c.Param("id")
|
||||
|
||||
var learningPathCourses []models.LearningPathCourse
|
||||
if err := db.Where("learning_path_id = ?", learningPathID).
|
||||
Preload("Course").
|
||||
Order("order ASC").
|
||||
Find(&learningPathCourses).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Failed to fetch learning path courses",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Extract courses
|
||||
courses := make([]models.Course, 0)
|
||||
for _, lpc := range learningPathCourses {
|
||||
if lpc.Course.IsActive {
|
||||
courses = append(courses, lpc.Course)
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"courses": courses,
|
||||
"count": len(courses),
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user