package inquiry import ( "tm/pkg/response" "tm/pkg/security" "github.com/asaskevich/govalidator" ) // Inquiry DTOs // CreateInquiryForm represents the data required to create a new inquiry type CreateInquiryForm struct { FullName string `json:"full_name" valid:"required,length(2|100)" example:"John Doe"` // Full name of the inquirer CompanyName string `json:"company_name" valid:"required,length(2|100)" example:"Opplens"` // Company name WorkEmail string `json:"work_email" valid:"required,email" example:"info@opplens.com"` // Work email address PhoneNumber string `json:"phone_number" valid:"required,length(10|20)" example:"+1234567890"` // Phone number HCaptchaToken string `json:"hcaptcha_token" valid:"required" example:"P0_eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..."` } // UpdateInquiryStatusForm represents the data required to update inquiry status type UpdateInquiryStatusForm struct { Status string `json:"status" valid:"required,in(pending|reviewed|approved|rejected)" example:"reviewed"` // New status Reason string `json:"reason" valid:"required,length(5|500)" example:"Initial review completed"` // Reason for status change Description string `json:"description" valid:"optional,length(0|1000)" example:"Additional notes about the review"` // Optional description } // SearchInquiriesForm represents search and filter parameters for inquiries type SearchInquiriesForm struct { Search *string `query:"q" valid:"optional"` // Search term for full name, company name, or email Status *string `query:"status" valid:"optional,in(pending|reviewed|approved|rejected)"` // Filter by status Limit *int `query:"limit" valid:"optional,range(1|100)"` // Limit results Offset *int `query:"offset" valid:"optional,range(0|1000000)"` // Offset results SortBy *string `query:"sort_by" valid:"optional,in(full_name|company_name|work_email|status|created_at)"` // Sort field SortOrder *string `query:"sort_order" valid:"optional,in(asc|desc)"` // Sort order } // Response DTOs // StatusHistoryResponse represents status history in API responses type StatusHistoryResponse struct { Status string `json:"status"` Reason string `json:"reason"` ChangedAt int64 `json:"changed_at"` Description string `json:"description"` } // InquiryResponse represents the inquiry data in API responses type InquiryResponse struct { ID string `json:"id"` FullName string `json:"full_name"` CompanyName string `json:"company_name"` WorkEmail string `json:"work_email"` PhoneNumber string `json:"phone_number"` Status string `json:"status"` StatusHistory []StatusHistoryResponse `json:"status_history"` CreatedAt int64 `json:"created_at"` UpdatedAt int64 `json:"updated_at"` } // InquiryListResponse represents a paginated list of inquiries type InquiryListResponse struct { Inquiries []*InquiryResponse `json:"inquiries"` Meta *response.Meta `json:"meta"` } // Helper function to convert Inquiry to InquiryResponse func (i *Inquiry) ToResponse() *InquiryResponse { // Convert status history var statusHistoryResponses []StatusHistoryResponse for _, history := range i.StatusHistory { statusHistoryResponses = append(statusHistoryResponses, StatusHistoryResponse{ Status: history.Status, Reason: history.Reason, ChangedAt: history.ChangedAt, Description: history.Description, }) } return &InquiryResponse{ ID: i.ID.Hex(), FullName: i.FullName, CompanyName: i.CompanyName, WorkEmail: i.WorkEmail, PhoneNumber: i.PhoneNumber, Status: i.Status, StatusHistory: statusHistoryResponses, CreatedAt: i.CreatedAt, UpdatedAt: i.UpdatedAt, } } // ValidateAndSanitize validates and sanitizes the form func (f *CreateInquiryForm) ValidateAndSanitize(xssPolicy *security.XSSPolicy) error { var err error // Sanitize and validate FullName f.FullName, err = xssPolicy.ValidateAndSanitizeInput(f.FullName, "text") if err != nil { return err } // Sanitize and validate CompanyName f.CompanyName, err = xssPolicy.ValidateAndSanitizeInput(f.CompanyName, "text") if err != nil { return err } // Sanitize and validate WorkEmail (email validation is separate) f.WorkEmail, err = xssPolicy.ValidateAndSanitizeInput(f.WorkEmail, "email") if err != nil { return err } // Sanitize and validate PhoneNumber f.PhoneNumber, err = xssPolicy.ValidateAndSanitizeInput(f.PhoneNumber, "phone") if err != nil { return err } // Standard govalidator validation _, err = govalidator.ValidateStruct(f) return err } // ValidateAndSanitize validates and sanitizes the status update form func (f *UpdateInquiryStatusForm) ValidateAndSanitize(xssPolicy *security.XSSPolicy) error { var err error // Sanitize Reason f.Reason, err = xssPolicy.ValidateAndSanitizeInput(f.Reason, "text") if err != nil { return err } // Sanitize Description f.Description, err = xssPolicy.ValidateAndSanitizeInput(f.Description, "html") if err != nil { return err } // Standard govalidator validation _, err = govalidator.ValidateStruct(f) return err } // ValidateAndSanitize validates and sanitizes the search form func (f *SearchInquiriesForm) ValidateAndSanitize(xssPolicy *security.XSSPolicy) error { if f.Search != nil { sanitized, err := xssPolicy.ValidateAndSanitizeInput(*f.Search, "text") if err != nil { return err } *f.Search = sanitized } // Standard govalidator validation _, err := govalidator.ValidateStruct(f) return err }