Documentation
¶
Overview ¶
Package form provides domain models and repository interfaces for form management.
Index ¶
- Constants
- Variables
- func GetFieldTypes() []string
- func ValidFieldType(fieldType string) bool
- func ValidStatus(status string) bool
- func ValidSubmissionStatus(status string) bool
- func ValidateSubmission(fields []FormField, data map[string]any) (map[string]any, map[string]string)
- type CreateFormInput
- type CreateSubmissionInput
- type FieldOption
- type FieldValidation
- type Form
- type FormField
- type FormSettings
- type FormSubmission
- type ListSubmissionsParams
- type PostgresRepository
- func (r *PostgresRepository) CreateForm(ctx context.Context, input *CreateFormInput) (*Form, error)
- func (r *PostgresRepository) CreateSubmission(ctx context.Context, formID uuid.UUID, input *CreateSubmissionInput) (*FormSubmission, error)
- func (r *PostgresRepository) DeleteForm(ctx context.Context, id uuid.UUID) error
- func (r *PostgresRepository) DeleteSubmission(ctx context.Context, id uuid.UUID) error
- func (r *PostgresRepository) GetFormByID(ctx context.Context, id uuid.UUID) (*Form, error)
- func (r *PostgresRepository) GetFormBySlug(ctx context.Context, slug string) (*Form, error)
- func (r *PostgresRepository) GetSubmissionByID(ctx context.Context, id uuid.UUID) (*FormSubmission, error)
- func (r *PostgresRepository) GetSubmissionCount(ctx context.Context, formID uuid.UUID) (int, error)
- func (r *PostgresRepository) ListForms(ctx context.Context, status string) ([]*Form, error)
- func (r *PostgresRepository) ListSubmissions(ctx context.Context, formID uuid.UUID, params *ListSubmissionsParams) ([]*FormSubmission, int, error)
- func (r *PostgresRepository) UpdateForm(ctx context.Context, id uuid.UUID, input *UpdateFormInput) (*Form, error)
- func (r *PostgresRepository) UpdateSubmission(ctx context.Context, id uuid.UUID, input *UpdateSubmissionInput) (*FormSubmission, error)
- type Repository
- type Service
- func (s *Service) CreateForm(ctx context.Context, input *CreateFormInput) (*Form, error)
- func (s *Service) CreateSubmission(ctx context.Context, formID uuid.UUID, input *CreateSubmissionInput) (*FormSubmission, error)
- func (s *Service) DeleteForm(ctx context.Context, id uuid.UUID) error
- func (s *Service) DeleteSubmission(ctx context.Context, id uuid.UUID) error
- func (s *Service) GetForm(ctx context.Context, id uuid.UUID) (*Form, error)
- func (s *Service) GetFormBySlug(ctx context.Context, slug string) (*Form, error)
- func (s *Service) GetSubmission(ctx context.Context, id uuid.UUID) (*FormSubmission, error)
- func (s *Service) GetSubmissionCount(ctx context.Context, formID uuid.UUID) (int, error)
- func (s *Service) ListForms(ctx context.Context, status string) ([]*Form, error)
- func (s *Service) ListSubmissions(ctx context.Context, formID uuid.UUID, params *ListSubmissionsParams) ([]*FormSubmission, int, error)
- func (s *Service) UpdateForm(ctx context.Context, id uuid.UUID, input *UpdateFormInput) (*Form, error)
- func (s *Service) UpdateSubmission(ctx context.Context, id uuid.UUID, input *UpdateSubmissionInput) (*FormSubmission, error)
- type SubmissionCursor
- type SubmissionMetadata
- type UpdateFormInput
- type UpdateSubmissionInput
Constants ¶
const ( StatusActive = "active" StatusInactive = "inactive" StatusArchived = "archived" )
Form status constants.
const ( SubmissionStatusNew = "new" SubmissionStatusRead = "read" SubmissionStatusArchived = "archived" SubmissionStatusSpam = "spam" )
Submission status constants.
const ( FieldTypeText = "text" FieldTypeEmail = "email" FieldTypePhone = "phone" FieldTypeTextarea = "textarea" FieldTypeSelect = "select" FieldTypeRadio = "radio" FieldTypeCheckbox = "checkbox" FieldTypeDate = "date" FieldTypeNumber = "number" FieldTypeURL = "url" )
Field type constants.
Variables ¶
var ( ErrFormNotFound = errors.New("form not found") ErrSubmissionNotFound = errors.New("submission not found") ErrSlugAlreadyExists = errors.New("form slug already exists") ErrInvalidStatus = errors.New("invalid form status") ErrInvalidFieldType = errors.New("invalid field type") )
Common errors.
Functions ¶
func ValidFieldType ¶
ValidFieldType checks if a field type is valid.
func ValidStatus ¶
ValidStatus checks if a form status is valid.
func ValidSubmissionStatus ¶
ValidSubmissionStatus checks if a submission status is valid.
func ValidateSubmission ¶
func ValidateSubmission(fields []FormField, data map[string]any) (map[string]any, map[string]string)
ValidateSubmission checks a public submission against the form's fields. It is the one validator behind the JSON and the urlencoded submit endpoints.
Only answers to fields the form defines are returned: unknown keys are ignored (never stored). Empty optional answers are dropped. The errors are keyed by field name; the returned data is nil when there is any error.
Types ¶
type CreateFormInput ¶
type CreateFormInput struct {
Name string `json:"name"`
Slug string `json:"slug,omitempty"`
Description *string `json:"description,omitempty"`
Fields []FormField `json:"fields"`
Settings FormSettings `json:"settings"`
}
CreateFormInput represents input for creating a new form.
type CreateSubmissionInput ¶
type CreateSubmissionInput struct {
Data map[string]any `json:"data"`
Metadata SubmissionMetadata `json:"metadata"`
// Status is the initial status; empty means SubmissionStatusNew. Set by
// the server (spam pipeline), never read from a request body.
Status string `json:"-"`
}
CreateSubmissionInput represents input for creating a form submission.
type FieldOption ¶
FieldOption represents an option for select, radio, or checkbox fields.
type FieldValidation ¶
type FieldValidation struct {
MinLength *int `json:"min_length,omitempty"`
MaxLength *int `json:"max_length,omitempty"`
Min *int `json:"min,omitempty"`
Max *int `json:"max,omitempty"`
Pattern *string `json:"pattern,omitempty"`
Message *string `json:"message,omitempty"`
}
FieldValidation represents validation rules for a field.
type Form ¶
type Form struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Slug string `json:"slug"`
Description *string `json:"description,omitempty"`
Fields []FormField `json:"fields"`
Settings FormSettings `json:"settings"`
Status string `json:"status"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Form represents a form definition.
type FormField ¶
type FormField struct {
ID string `json:"id"`
Type string `json:"type"`
Label string `json:"label"`
Name string `json:"name"`
Placeholder string `json:"placeholder,omitempty"`
Required bool `json:"required"`
Options []FieldOption `json:"options,omitempty"`
Validation *FieldValidation `json:"validation,omitempty"`
DefaultValue string `json:"default_value,omitempty"`
HelpText string `json:"help_text,omitempty"`
Width string `json:"width,omitempty"` // "full", "half", "third"
Position int `json:"position"`
Attributes map[string]string `json:"attributes,omitempty"`
}
FormField represents a single field in a form.
type FormSettings ¶
type FormSettings struct {
SubmitButtonText string `json:"submit_button_text,omitempty"`
SuccessMessage string `json:"success_message,omitempty"`
SuccessRedirectURL string `json:"success_redirect_url,omitempty"`
EnableCaptcha bool `json:"enable_captcha"`
NotifyEmail *string `json:"notify_email,omitempty"`
ConfirmationEmail bool `json:"confirmation_email"`
// ConfirmationMessage is the body of the submitter's confirmation email;
// SuccessMessage is used when it is empty.
ConfirmationMessage string `json:"confirmation_message,omitempty"`
StoreSubmissions bool `json:"store_submissions"`
}
FormSettings represents form-level settings.
type FormSubmission ¶
type FormSubmission struct {
ID uuid.UUID `json:"id"`
FormID uuid.UUID `json:"form_id"`
Data map[string]any `json:"data"`
Metadata SubmissionMetadata `json:"metadata"`
Status string `json:"status"`
CreatedAt time.Time `json:"created_at"`
// Populated on read
FormName *string `json:"form_name,omitempty"`
}
FormSubmission represents a submitted form entry.
type ListSubmissionsParams ¶
type ListSubmissionsParams struct {
Status string `json:"status,omitempty"`
Limit int `json:"limit,omitempty"`
Offset int `json:"offset,omitempty"`
// After continues a listing after this submission (keyset paging, newest
// first): rows are neither repeated nor skipped when new ones arrive. It
// replaces Offset and skips the total count.
After *SubmissionCursor `json:"-"`
}
ListSubmissionsParams represents parameters for listing submissions.
type PostgresRepository ¶
type PostgresRepository struct {
// contains filtered or unexported fields
}
PostgresRepository implements Repository using PostgreSQL.
func NewPostgresRepository ¶
func NewPostgresRepository(db *database.DB) *PostgresRepository
NewPostgresRepository creates a new PostgreSQL form repository.
func (*PostgresRepository) CreateForm ¶
func (r *PostgresRepository) CreateForm(ctx context.Context, input *CreateFormInput) (*Form, error)
CreateForm inserts a new form.
func (*PostgresRepository) CreateSubmission ¶
func (r *PostgresRepository) CreateSubmission(ctx context.Context, formID uuid.UUID, input *CreateSubmissionInput) (*FormSubmission, error)
CreateSubmission inserts a new form submission.
func (*PostgresRepository) DeleteForm ¶
DeleteForm removes a form and all its submissions.
func (*PostgresRepository) DeleteSubmission ¶
DeleteSubmission removes a submission.
func (*PostgresRepository) GetFormByID ¶
GetFormByID retrieves a form by ID.
func (*PostgresRepository) GetFormBySlug ¶
GetFormBySlug retrieves a form by slug.
func (*PostgresRepository) GetSubmissionByID ¶
func (r *PostgresRepository) GetSubmissionByID(ctx context.Context, id uuid.UUID) (*FormSubmission, error)
GetSubmissionByID retrieves a submission by ID.
func (*PostgresRepository) GetSubmissionCount ¶
GetSubmissionCount returns the count of submissions for a form.
func (*PostgresRepository) ListSubmissions ¶
func (r *PostgresRepository) ListSubmissions(ctx context.Context, formID uuid.UUID, params *ListSubmissionsParams) ([]*FormSubmission, int, error)
ListSubmissions retrieves submissions for a form with pagination.
func (*PostgresRepository) UpdateForm ¶
func (r *PostgresRepository) UpdateForm(ctx context.Context, id uuid.UUID, input *UpdateFormInput) (*Form, error)
UpdateForm modifies a form.
func (*PostgresRepository) UpdateSubmission ¶
func (r *PostgresRepository) UpdateSubmission(ctx context.Context, id uuid.UUID, input *UpdateSubmissionInput) (*FormSubmission, error)
UpdateSubmission modifies a submission.
type Repository ¶
type Repository interface {
// Form operations
CreateForm(ctx context.Context, input *CreateFormInput) (*Form, error)
GetFormByID(ctx context.Context, id uuid.UUID) (*Form, error)
GetFormBySlug(ctx context.Context, slug string) (*Form, error)
ListForms(ctx context.Context, status string) ([]*Form, error)
UpdateForm(ctx context.Context, id uuid.UUID, input *UpdateFormInput) (*Form, error)
DeleteForm(ctx context.Context, id uuid.UUID) error
// Submission operations
CreateSubmission(ctx context.Context, formID uuid.UUID, input *CreateSubmissionInput) (*FormSubmission, error)
GetSubmissionByID(ctx context.Context, id uuid.UUID) (*FormSubmission, error)
ListSubmissions(ctx context.Context, formID uuid.UUID, params *ListSubmissionsParams) ([]*FormSubmission, int, error)
UpdateSubmission(ctx context.Context, id uuid.UUID, input *UpdateSubmissionInput) (*FormSubmission, error)
DeleteSubmission(ctx context.Context, id uuid.UUID) error
GetSubmissionCount(ctx context.Context, formID uuid.UUID) (int, error)
}
Repository defines the interface for form data operations.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service provides business logic for form management.
func NewService ¶
func NewService(repo Repository, logger *slog.Logger) *Service
NewService creates a new form service.
func (*Service) CreateForm ¶
CreateForm creates a new form.
func (*Service) CreateSubmission ¶
func (s *Service) CreateSubmission(ctx context.Context, formID uuid.UUID, input *CreateSubmissionInput) (*FormSubmission, error)
CreateSubmission creates a new form submission.
func (*Service) DeleteForm ¶
DeleteForm removes a form.
func (*Service) DeleteSubmission ¶
DeleteSubmission removes a submission.
func (*Service) GetFormBySlug ¶
GetFormBySlug retrieves a form by slug.
func (*Service) GetSubmission ¶
GetSubmission retrieves a submission by ID.
func (*Service) GetSubmissionCount ¶
GetSubmissionCount returns the count of submissions for a form.
func (*Service) ListSubmissions ¶
func (s *Service) ListSubmissions(ctx context.Context, formID uuid.UUID, params *ListSubmissionsParams) ([]*FormSubmission, int, error)
ListSubmissions retrieves submissions for a form.
func (*Service) UpdateForm ¶
func (s *Service) UpdateForm(ctx context.Context, id uuid.UUID, input *UpdateFormInput) (*Form, error)
UpdateForm modifies a form.
func (*Service) UpdateSubmission ¶
func (s *Service) UpdateSubmission(ctx context.Context, id uuid.UUID, input *UpdateSubmissionInput) (*FormSubmission, error)
UpdateSubmission modifies a submission.
type SubmissionCursor ¶
SubmissionCursor is the position of the last submission of a page.
type SubmissionMetadata ¶
type SubmissionMetadata struct {
IPAddress string `json:"ip_address,omitempty"`
UserAgent string `json:"user_agent,omitempty"`
Referrer string `json:"referrer,omitempty"`
PageURL string `json:"page_url,omitempty"`
}
SubmissionMetadata contains metadata about the submission.
type UpdateFormInput ¶
type UpdateFormInput struct {
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
Fields []FormField `json:"fields,omitempty"`
Settings *FormSettings `json:"settings,omitempty"`
Status *string `json:"status,omitempty"`
}
UpdateFormInput represents input for updating a form.
type UpdateSubmissionInput ¶
type UpdateSubmissionInput struct {
Status *string `json:"status,omitempty"`
}
UpdateSubmissionInput represents input for updating a submission.