package handlers import ( "net/http" "strings" "gauth-central/internal/services" "github.com/gin-gonic/gin" "github.com/google/uuid" ) type ExperienceHandler struct { experienceService *services.ExperienceService } func NewExperienceHandler(experienceService *services.ExperienceService) *ExperienceHandler { return &ExperienceHandler{experienceService: experienceService} } type CreateExperienceRequest struct { BetweenYears string `json:"between_years"` Title string `json:"title"` Content string `json:"content"` ResumeID string `json:"resume_id"` IsActive *bool `json:"is_active"` } type UpdateExperienceRequest struct { BetweenYears *string `json:"between_years"` Title *string `json:"title"` Content *string `json:"content"` ResumeID *string `json:"resume_id"` IsActive *bool `json:"is_active"` } // GetAllExperiences godoc // @Summary Get all active experiences // @Description Retrieve a list of active experience entries // @Tags resume // @Produce json // @Param resume_id query string false "Resume ID" // @Success 200 {array} models.Experience // @Failure 400 {object} map[string]string // @Failure 500 {object} map[string]string // @Router /experiences [get] func (h *ExperienceHandler) GetAllExperiences(c *gin.Context) { resumeID := strings.TrimSpace(c.Query("resume_id")) var resumeIDPtr *string if resumeID != "" { resumeIDPtr = &resumeID } items, err := h.experienceService.GetAllExperiences(resumeIDPtr, true) if err != nil { status := http.StatusInternalServerError c.JSON(status, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, items) } // AdminGetAllExperiences godoc // @Summary Get all experiences (Admin) // @Description Retrieve a list of all experience entries including inactive ones // @Tags admin // @Security ApiKeyAuth // @Produce json // @Param resume_id query string false "Resume ID" // @Success 200 {array} models.Experience // @Failure 400 {object} map[string]string // @Failure 500 {object} map[string]string // @Router /admin/experiences [get] func (h *ExperienceHandler) AdminGetAllExperiences(c *gin.Context) { resumeID := strings.TrimSpace(c.Query("resume_id")) var resumeIDPtr *string if resumeID != "" { resumeIDPtr = &resumeID } items, err := h.experienceService.GetAllExperiences(resumeIDPtr, false) if err != nil { status := http.StatusInternalServerError c.JSON(status, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, items) } // AdminGetExperienceByID godoc // @Summary Get an experience by ID (Admin) // @Description Retrieve details of a specific experience entry // @Tags admin // @Security ApiKeyAuth // @Produce json // @Param id path string true "Experience ID" // @Success 200 {object} models.Experience // @Failure 404 {object} map[string]string // @Router /admin/experiences/{id} [get] func (h *ExperienceHandler) AdminGetExperienceByID(c *gin.Context) { id := c.Param("id") item, err := h.experienceService.GetExperienceByID(id) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, item) } // CreateExperience godoc // @Summary Create a new experience (Admin) // @Description Create a new experience entry // @Tags admin // @Security ApiKeyAuth // @Accept json // @Produce json // @Param request body CreateExperienceRequest true "Experience Request" // @Success 201 {object} models.Experience // @Failure 400 {object} map[string]string // @Router /admin/experiences [post] func (h *ExperienceHandler) CreateExperience(c *gin.Context) { var req CreateExperienceRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } req.BetweenYears = strings.TrimSpace(req.BetweenYears) req.Title = strings.TrimSpace(req.Title) req.Content = strings.TrimSpace(req.Content) if req.BetweenYears == "" || req.Title == "" || req.Content == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "between_years, title, and content are required"}) return } isActive := false if req.IsActive != nil { isActive = *req.IsActive } resumeUUID, parseErr := parseUUIDPtr(req.ResumeID) if parseErr != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid resume id"}) return } item, err := h.experienceService.CreateExperience(req.BetweenYears, req.Title, req.Content, resumeUUID, isActive) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusCreated, item) } // UpdateExperience godoc // @Summary Update an experience (Admin) // @Description Update an existing experience entry // @Tags admin // @Security ApiKeyAuth // @Accept json // @Produce json // @Param id path string true "Experience ID" // @Param request body UpdateExperienceRequest true "Experience Request" // @Success 200 {object} models.Experience // @Failure 400 {object} map[string]string // @Failure 404 {object} map[string]string // @Router /admin/experiences/{id} [put] func (h *ExperienceHandler) UpdateExperience(c *gin.Context) { id := c.Param("id") var req UpdateExperienceRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if req.BetweenYears != nil { trimmed := strings.TrimSpace(*req.BetweenYears) req.BetweenYears = &trimmed } if req.Title != nil { trimmed := strings.TrimSpace(*req.Title) req.Title = &trimmed } if req.Content != nil { trimmed := strings.TrimSpace(*req.Content) req.Content = &trimmed } if req.ResumeID != nil { trimmed := strings.TrimSpace(*req.ResumeID) req.ResumeID = &trimmed } var resumeUUIDPtr *uuid.UUID if req.ResumeID != nil { parsed, parseErr := parseUUIDPtr(*req.ResumeID) if parseErr != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid resume id"}) return } resumeUUIDPtr = parsed } item, err := h.experienceService.UpdateExperience(id, req.BetweenYears, req.Title, req.Content, resumeUUIDPtr, req.IsActive) if err != nil { status := http.StatusInternalServerError if err.Error() == "experience not found" { status = http.StatusNotFound } c.JSON(status, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, item) } // DeleteExperience godoc // @Summary Delete an experience (Admin) // @Description Delete an experience by ID // @Tags admin // @Security ApiKeyAuth // @Param id path string true "Experience ID" // @Success 200 {object} map[string]string // @Failure 404 {object} map[string]string // @Router /admin/experiences/{id} [delete] func (h *ExperienceHandler) DeleteExperience(c *gin.Context) { id := c.Param("id") if err := h.experienceService.DeleteExperience(id); err != nil { c.JSON(http.StatusNotFound, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "Experience deleted successfully"}) }