-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add CRUD survey apis. #22
base: dev
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// api/http/dto/create_survey.go | ||
package dto | ||
|
||
import "time" | ||
|
||
type CreateSurveyRequest struct { | ||
Title string `json:"title" validate:"required,min=3,max=100"` | ||
CreationTime time.Time `json:"creation_time" validate:"required"` | ||
StartTime *time.Time `json:"start_time" validate:"required"` | ||
EndTime *time.Time `json:"end_time" validate:"required,gtfield=StartTime"` | ||
RandomOrder bool `json:"random_order"` | ||
AllowReturn bool `json:"allow_return"` | ||
NumParticipationAttempts int `json:"num_participation_attempts" validate:"gte=1,lte=10"` | ||
ResponseTime int `json:"response_time" validate:"gte=60,lte=86400"` // Between 1 minute and 1 day | ||
AnonymityLevel string `json:"anonymity_level" validate:"required,oneof=visible_to_creator visible_to_creator_and_admins anonymous"` | ||
DemographicRestrictions string `json:"demographic_restrictions" validate:"omitempty,json"` | ||
ResponseModification bool `json:"response_modification"` | ||
} | ||
|
||
type CreateSurveyResponse struct { | ||
ID uint `json:"id"` | ||
Title string `json:"title"` | ||
OwnerID uint `json:"owner_id"` | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// api/http/dto/get_survey.go | ||
package dto | ||
|
||
import "time" | ||
|
||
type GetSurveyResponse struct { | ||
ID uint `json:"id"` | ||
Title string `json:"title"` | ||
CreationTime time.Time `json:"creation_time"` | ||
StartTime *time.Time `json:"start_time"` | ||
EndTime *time.Time `json:"end_time"` | ||
RandomOrder bool `json:"random_order"` | ||
AllowReturn bool `json:"allow_return"` | ||
NumParticipationAttempts int `json:"num_participation_attempts"` | ||
ResponseTime int `json:"response_time"` | ||
AnonymityLevel string `json:"anonymity_level"` | ||
DemographicRestrictions string `json:"demographic_restrictions"` | ||
ResponseModification bool `json:"response_modification"` | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// api/http/dto/update_survey.go | ||
package dto | ||
|
||
import "time" | ||
|
||
type UpdateSurveyRequest struct { | ||
Title *string `json:"title,omitempty"` | ||
StartTime *time.Time `json:"start_time,omitempty"` | ||
EndTime *time.Time `json:"end_time,omitempty"` | ||
RandomOrder *bool `json:"random_order,omitempty"` | ||
AllowReturn *bool `json:"allow_return,omitempty"` | ||
NumParticipationAttempts *int `json:"num_participation_attempts,omitempty"` | ||
ResponseTime *int `json:"response_time,omitempty"` | ||
AnonymityLevel *string `json:"anonymity_level,omitempty"` | ||
DemographicRestrictions *string `json:"demographic_restrictions,omitempty"` | ||
ResponseModification *bool `json:"response_modification,omitempty"` | ||
} | ||
|
||
type UpdateSurveyResponse struct { | ||
ID uint `json:"id"` | ||
Title string `json:"title"` | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
// api/http/handlers/survey.go | ||
package handlers | ||
|
||
import ( | ||
"fmt" | ||
"golipors/api/http/dto" | ||
"golipors/api/http/mapper" | ||
"golipors/internal/survey/port" | ||
"net/http" | ||
"strconv" | ||
|
||
"github.com/go-playground/validator/v10" | ||
|
||
"github.com/gofiber/fiber/v2" | ||
) | ||
|
||
var validate = validator.New() | ||
|
||
type SurveyHandler struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. این چیه ؟ |
||
service port.Service | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. پورت توی هندلر چیکار میکنه. مگه پورت ریپو توی سرویس ها استفاده نمیشد؟ سرویس ها هم از طریق appContainer اینجکت میشد تو هندلر ها؟ |
||
} | ||
|
||
func NewSurveyHandler(service port.Service) *SurveyHandler { | ||
return &SurveyHandler{ | ||
service: service, | ||
} | ||
} | ||
|
||
func (h *SurveyHandler) RegisterRoutes(api fiber.Router) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. api group? accountGroup := router.Group("/account")
accountGroup.Post("/login", Login(appContainer, cfg))
accountGroup.Post("/register", Register)
accountGroup.Post("/verify-otp", VerifyOtp(appContainer, cfg))
accountGroup.Post("/reset-password", ResetPassword)
accountGroup.Post("/reset-password/verify", ResetPasswordVerify) |
||
api.Post("/surveys", h.CreateSurvey) | ||
api.Get("/surveys/:id", h.GetSurveyByID) | ||
api.Put("/surveys/:id", h.UpdateSurvey) | ||
api.Delete("/surveys/:id", h.DeleteSurvey) | ||
} | ||
|
||
// CreateSurvey handles POST /api/surveys | ||
func (h *SurveyHandler) CreateSurvey(c *fiber.Ctx) error { | ||
var req dto.CreateSurveyRequest | ||
|
||
// Parse request body | ||
if err := c.BodyParser(&req); err != nil { | ||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{ | ||
"error": "Invalid request body", | ||
}) | ||
} | ||
|
||
// Validate request body | ||
if err := validate.Struct(req); err != nil { | ||
// Extract validation errors | ||
validationErrors := make(map[string]string) | ||
for _, err := range err.(validator.ValidationErrors) { | ||
validationErrors[err.Field()] = fmt.Sprintf("Validation failed on '%s' with tag '%s'", err.Field(), err.Tag()) | ||
} | ||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{ | ||
"error": "Validation failed", | ||
"details": validationErrors, | ||
}) | ||
} | ||
|
||
// Assuming owner ID is retrieved from context (e.g., after authentication) | ||
ownerID := uint(1) // Placeholder | ||
|
||
// Convert DTO to domain model | ||
survey := mapper.CreateSurveyRequestToDomain(req, ownerID) | ||
|
||
// Create survey | ||
surveyID, err := h.service.CreateSurvey(c.Context(), survey) | ||
if err != nil { | ||
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ | ||
"error": err.Error(), | ||
}) | ||
} | ||
|
||
// Build response | ||
response := dto.CreateSurveyResponse{ | ||
ID: surveyID, | ||
Title: survey.Title, | ||
OwnerID: ownerID, | ||
} | ||
|
||
return c.Status(http.StatusCreated).JSON(response) | ||
} | ||
|
||
// GetSurveyByID handles GET /api/surveys/:id | ||
func (h *SurveyHandler) GetSurveyByID(c *fiber.Ctx) error { | ||
idParam := c.Params("id") | ||
id, err := strconv.ParseUint(idParam, 10, 32) | ||
if err != nil { | ||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{ | ||
"error": "Invalid survey ID", | ||
}) | ||
} | ||
|
||
survey, err := h.service.GetSurveyByID(c.Context(), uint(id)) | ||
if err != nil { | ||
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ | ||
"error": err.Error(), | ||
}) | ||
} | ||
if survey == nil { | ||
return c.Status(http.StatusNotFound).JSON(fiber.Map{ | ||
"error": "Survey not found", | ||
}) | ||
} | ||
|
||
response := mapper.DomainSurveyToGetSurveyResponse(*survey) | ||
return c.Status(http.StatusOK).JSON(response) | ||
} | ||
|
||
// UpdateSurvey handles PUT /api/surveys/:id | ||
func (h *SurveyHandler) UpdateSurvey(c *fiber.Ctx) error { | ||
idParam := c.Params("id") | ||
id, err := strconv.ParseUint(idParam, 10, 32) | ||
if err != nil { | ||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{ | ||
"error": "Invalid survey ID", | ||
}) | ||
} | ||
|
||
var req dto.UpdateSurveyRequest | ||
if err := c.BodyParser(&req); err != nil { | ||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{ | ||
"error": "Invalid request body", | ||
}) | ||
} | ||
|
||
survey := mapper.UpdateSurveyRequestToDomain(req) | ||
survey.ID = uint(id) | ||
|
||
if err := h.service.UpdateSurvey(c.Context(), survey); err != nil { | ||
if err.Error() == "survey not found" { | ||
return c.Status(http.StatusNotFound).JSON(fiber.Map{ | ||
"error": "Survey not found", | ||
}) | ||
} | ||
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ | ||
"error": err.Error(), | ||
}) | ||
} | ||
|
||
updatedSurvey, _ := h.service.GetSurveyByID(c.Context(), uint(id)) | ||
response := mapper.DomainSurveyToUpdateSurveyResponse(*updatedSurvey) | ||
return c.Status(http.StatusOK).JSON(response) | ||
} | ||
|
||
// DeleteSurvey handles DELETE /api/surveys/:id | ||
func (h *SurveyHandler) DeleteSurvey(c *fiber.Ctx) error { | ||
idParam := c.Params("id") | ||
id, err := strconv.ParseUint(idParam, 10, 32) | ||
if err != nil { | ||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{ | ||
"error": "Invalid survey ID", | ||
}) | ||
} | ||
|
||
if err := h.service.DeleteSurvey(c.Context(), uint(id)); err != nil { | ||
if err.Error() == "survey not found" { | ||
return c.Status(http.StatusNotFound).JSON(fiber.Map{ | ||
"error": "Survey not found", | ||
}) | ||
} | ||
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ | ||
"error": err.Error(), | ||
}) | ||
} | ||
|
||
return c.SendStatus(http.StatusOK) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
// api/http/mapper/survey_mapper.go | ||
package mapper | ||
|
||
import ( | ||
"golipors/api/http/dto" | ||
"golipors/internal/survey/domain" | ||
) | ||
|
||
func CreateSurveyRequestToDomain(req dto.CreateSurveyRequest, ownerID uint) domain.Survey { | ||
return domain.Survey{ | ||
Title: req.Title, | ||
CreationTime: req.CreationTime, | ||
StartTime: req.StartTime, | ||
EndTime: req.EndTime, | ||
RandomOrder: req.RandomOrder, | ||
AllowReturn: req.AllowReturn, | ||
NumParticipationAttempts: req.NumParticipationAttempts, | ||
ResponseTime: req.ResponseTime, | ||
AnonymityLevel: req.AnonymityLevel, | ||
DemographicRestrictions: req.DemographicRestrictions, | ||
ResponseModification: req.ResponseModification, | ||
OwnerID: ownerID, | ||
} | ||
} | ||
|
||
func DomainSurveyToCreateSurveyResponse(survey domain.Survey) dto.CreateSurveyResponse { | ||
return dto.CreateSurveyResponse{ | ||
ID: survey.ID, | ||
Title: survey.Title, | ||
OwnerID: survey.OwnerID, | ||
} | ||
} | ||
|
||
func DomainSurveyToGetSurveyResponse(survey domain.Survey) dto.GetSurveyResponse { | ||
return dto.GetSurveyResponse{ | ||
ID: survey.ID, | ||
Title: survey.Title, | ||
CreationTime: survey.CreationTime, | ||
StartTime: survey.StartTime, | ||
EndTime: survey.EndTime, | ||
RandomOrder: survey.RandomOrder, | ||
AllowReturn: survey.AllowReturn, | ||
NumParticipationAttempts: survey.NumParticipationAttempts, | ||
ResponseTime: survey.ResponseTime, | ||
AnonymityLevel: survey.AnonymityLevel, | ||
DemographicRestrictions: survey.DemographicRestrictions, | ||
ResponseModification: survey.ResponseModification, | ||
} | ||
} | ||
|
||
func UpdateSurveyRequestToDomain(req dto.UpdateSurveyRequest) domain.Survey { | ||
survey := domain.Survey{} | ||
|
||
if req.Title != nil { | ||
survey.Title = *req.Title | ||
} | ||
if req.StartTime != nil { | ||
survey.StartTime = req.StartTime | ||
} | ||
if req.EndTime != nil { | ||
survey.EndTime = req.EndTime | ||
} | ||
if req.RandomOrder != nil { | ||
survey.RandomOrder = *req.RandomOrder | ||
} | ||
if req.AllowReturn != nil { | ||
survey.AllowReturn = *req.AllowReturn | ||
} | ||
if req.NumParticipationAttempts != nil { | ||
survey.NumParticipationAttempts = *req.NumParticipationAttempts | ||
} | ||
if req.ResponseTime != nil { | ||
survey.ResponseTime = *req.ResponseTime | ||
} | ||
if req.AnonymityLevel != nil { | ||
survey.AnonymityLevel = *req.AnonymityLevel | ||
} | ||
if req.DemographicRestrictions != nil { | ||
survey.DemographicRestrictions = *req.DemographicRestrictions | ||
} | ||
if req.ResponseModification != nil { | ||
survey.ResponseModification = *req.ResponseModification | ||
} | ||
|
||
return survey | ||
} | ||
|
||
func DomainSurveyToUpdateSurveyResponse(survey domain.Survey) dto.UpdateSurveyResponse { | ||
return dto.UpdateSurveyResponse{ | ||
ID: survey.ID, | ||
Title: survey.Title, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implement this part using presenter arch
https://github.com/babyhando/sample-service/tree/main/api/http/handlers/presenter