package dto import ( "bytes" "encoding/json" ) // JSON:API User DTOs type UserResource struct { Type string `json:"type" example:"user"` ID string `json:"id" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"` Attributes UserAttributes `json:"attributes"` } type UserListResponse struct { Data []UserResource `json:"data"` Meta struct { PageNumber int `json:"page_number" example:"1"` PageSize int `json:"page_size" example:"20"` Total int64 `json:"total" example:"120"` } `json:"meta"` } type UserDataTableResponse struct { Data []UserResource `json:"data"` Meta struct { Draw int `json:"draw" example:"1"` RecordsTotal int64 `json:"records_total" example:"120"` RecordsFiltered int64 `json:"records_filtered" example:"12"` } `json:"meta"` } // Create type UserCreateAttributes struct { Email string `json:"email" validate:"required,email" example:"user@example.com"` Username string `json:"username" validate:"required,min=3,max=100" example:"john.doe"` FirstName string `json:"first_name" validate:"required" example:"John"` LastName string `json:"last_name" validate:"required" example:"Doe"` MobilePhone string `json:"mobile_phone,omitempty" example:"+628123456789"` Timezone *string `json:"timezone,omitempty" example:"Asia/Jakarta"` ImageUUID *string `json:"image_uuid,omitempty" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e90"` RoleID string `json:"role_id" validate:"required" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"` RoleIDs []string `json:"role_ids,omitempty" example:"[\"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d\",\"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9e\"]"` } type UserCreateData struct { Type string `json:"type" validate:"required,oneof=user_create user" example:"user_create"` Attributes UserCreateAttributes `json:"attributes" validate:"required"` } type UserCreateRequest struct { Data UserCreateData `json:"data" validate:"required"` } // Update type UserUpdateAttributes struct { Email *string `json:"email,omitempty" validate:"omitempty,email" example:"user@example.com"` FirstName *string `json:"first_name,omitempty" example:"John"` LastName *string `json:"last_name,omitempty" example:"Doe"` MobilePhone *string `json:"mobile_phone,omitempty" example:"+628123456789"` Timezone *string `json:"timezone,omitempty" example:"Asia/Jakarta"` ImageUUID NullString `json:"image_uuid,omitempty" swaggertype:"string" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e90"` } // NullString allows PATCH semantics: // - field omitted => Set=false (no change) // - value null => Set=true, Valid=false (clear value) // - value string => Set=true, Valid=true, Value= type NullString struct { Set bool Valid bool Value string } func (n *NullString) UnmarshalJSON(data []byte) error { n.Set = true trimmed := bytes.TrimSpace(data) if bytes.Equal(trimmed, []byte("null")) { n.Valid = false n.Value = "" return nil } var v string if err := json.Unmarshal(trimmed, &v); err != nil { return err } n.Valid = true n.Value = v return nil } type UserUpdateData struct { Type string `json:"type" validate:"required,oneof=user_update user" example:"user_update"` ID string `json:"id" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"` Attributes UserUpdateAttributes `json:"attributes" validate:"required"` } type UserUpdateRequest struct { Data UserUpdateData `json:"data" validate:"required"` }