Spaces:
Runtime error
Runtime error
| """ | |
| Pydantic schemas for form-related operations | |
| """ | |
| from pydantic import BaseModel, Field, field_validator | |
| from typing import Optional, List, Dict, Any, Union | |
| from datetime import datetime | |
| from ..models import QuestionType, ConditionType | |
| # Question schemas | |
| class QuestionSettings(BaseModel): | |
| """Settings for different question types""" | |
| choices: Optional[List[str]] = None # For multiple choice, checkboxes, dropdown | |
| min_value: Optional[int] = None # For number, linear scale | |
| max_value: Optional[int] = None | |
| min_length: Optional[int] = None # For text inputs | |
| max_length: Optional[int] = None | |
| placeholder: Optional[str] = None | |
| scale_min_label: Optional[str] = None # For linear scale | |
| scale_max_label: Optional[str] = None | |
| rows: Optional[Union[int, List[str]]] = None # For matrix questions - accepts int or list | |
| columns: Optional[Union[int, List[str]]] = None # For matrix questions - accepts int or list | |
| file_types: Optional[List[str]] = None # For file upload | |
| max_file_size: Optional[int] = None | |
| payment_amount: Optional[float] = None # For payment questions | |
| currency: Optional[str] = None | |
| ranking_items: Optional[Union[int, List[str]]] = None # For ranking questions - accepts int or list | |
| class Config: | |
| extra = "allow" # Allow additional fields | |
| class QuestionBase(BaseModel): | |
| question_text: str | |
| question_type: QuestionType | |
| description: Optional[str] = None | |
| required: bool = False | |
| settings: Optional[QuestionSettings] = None | |
| class QuestionCreate(QuestionBase): | |
| question_order: int | |
| form_id: int | |
| class QuestionUpdate(BaseModel): | |
| question_text: Optional[str] = None | |
| question_type: Optional[QuestionType] = None | |
| description: Optional[str] = None | |
| required: Optional[bool] = None | |
| question_order: Optional[int] = None | |
| settings: Optional[QuestionSettings] = None | |
| class QuestionResponse(QuestionBase): | |
| id: int | |
| form_id: int | |
| question_order: int | |
| created_at: datetime | |
| updated_at: datetime | |
| class Config: | |
| from_attributes = True | |
| # Conditional logic schemas | |
| class ConditionalRuleBase(BaseModel): | |
| trigger_question_id: int | |
| target_question_id: int | |
| condition_type: ConditionType | |
| condition_value: Optional[str] = None | |
| action: str = "show" # "show" or "hide" | |
| def validate_action(cls, v): | |
| if v not in ["show", "hide"]: | |
| raise ValueError('Action must be "show" or "hide"') | |
| return v | |
| class ConditionalRuleCreate(ConditionalRuleBase): | |
| form_id: int | |
| class ConditionalRuleResponse(ConditionalRuleBase): | |
| id: int | |
| form_id: int | |
| created_at: datetime | |
| class Config: | |
| from_attributes = True | |
| # Form schemas | |
| class FormSettings(BaseModel): | |
| """Form-level settings""" | |
| background_color: str = "#ffffff" | |
| text_color: str = "#000000" | |
| accent_color: str = "#9333ea" # Purple | |
| bold_text_color: Optional[str] = "#9333ea" # Bold text and buttons | |
| submit_button_text: str = "Submit" | |
| show_progress_bar: bool = True | |
| class Config: | |
| extra = "allow" | |
| class FormBase(BaseModel): | |
| title: str | |
| description: Optional[str] = None | |
| settings: Optional[FormSettings] = None | |
| class FormCreate(BaseModel): | |
| """Schema for creating a form from AI generation""" | |
| user_query: str # The natural language description | |
| title: Optional[str] = None # Optional - will be generated by AI if not provided | |
| description: Optional[str] = None # Optional - will be generated by AI if not provided | |
| settings: Optional[FormSettings] = None # Optional - defaults applied if not provided | |
| class FormUpdate(BaseModel): | |
| title: Optional[str] = None | |
| description: Optional[str] = None | |
| settings: Optional[FormSettings] = None | |
| class FormResponse(FormBase): | |
| id: int | |
| user_id: int | |
| created_at: datetime | |
| updated_at: datetime | |
| questions: List[QuestionResponse] = [] | |
| conditional_rules: List[ConditionalRuleResponse] = [] | |
| class Config: | |
| from_attributes = True | |
| # Form generation response | |
| class FormGenerationResponse(BaseModel): | |
| """Response from AI form generation""" | |
| form: FormResponse | |
| message: str = "Form generated successfully" | |
| # Answer and submission schemas | |
| class AnswerValue(BaseModel): | |
| """Answer value for different question types""" | |
| text: Optional[str] = None # For text inputs | |
| number: Optional[float] = None # For number inputs | |
| date: Optional[str] = None # For date/time | |
| choices: Optional[List[str]] = None # For multiple choice, checkboxes | |
| file_url: Optional[str] = None # For file uploads | |
| files: Optional[List[Dict[str, Any]]] = None # For file uploads | |
| rating: Optional[int] = None # For ratings | |
| signature: Optional[str] = None # Base64 signature image | |
| wallet_address: Optional[str] = None # For wallet connect | |
| matrix_answers: Optional[Dict[str, str]] = None # For matrix questions | |
| ranked_items: Optional[List[str]] = None # For ranking questions | |
| class Config: | |
| extra = "allow" | |
| class SubmitAnswer(BaseModel): | |
| question_id: int | |
| answer_value: AnswerValue | |
| class SubmissionCreate(BaseModel): | |
| """Schema for submitting a form response""" | |
| answers: List[SubmitAnswer] | |
| metadata: Optional[Dict[str, Any]] = None | |
| session_id: Optional[str] = None | |
| form_version: Optional[int] = None | |
| utm_source: Optional[str] = None | |
| utm_medium: Optional[str] = None | |
| utm_campaign: Optional[str] = None | |
| class SubmissionResponse(BaseModel): | |
| """Response after successful submission""" | |
| id: int | |
| form_id: int | |
| submitted_at: datetime | |
| message: str = "Form submitted successfully" | |
| class Config: | |
| from_attributes = True | |
| class ResponseAnswerDetail(BaseModel): | |
| """Detailed answer in a response""" | |
| question_id: int | |
| question_text: str | |
| question_type: QuestionType | |
| answer_value: Dict[str, Any] | |
| class Config: | |
| from_attributes = True | |
| class FormResponseDetail(BaseModel): | |
| """Detailed view of a single form response""" | |
| id: int | |
| form_id: int | |
| status: Optional[str] = None | |
| submitted_at: datetime | |
| ip_address: Optional[str] | |
| answers: List[ResponseAnswerDetail] | |
| class Config: | |
| from_attributes = True | |
| class FormResponsesList(BaseModel): | |
| """List of form responses with summary""" | |
| total_count: int | |
| responses: List[FormResponseDetail] | |
| # Public form schemas | |
| class PublicFormCreate(BaseModel): | |
| form_id: int | |
| expires_at: Optional[datetime] = None | |
| allow_multiple_submissions: bool = True | |
| collect_email: bool = False | |
| custom_thank_you_message: Optional[str] = None | |
| class PublicFormResponse(BaseModel): | |
| id: int | |
| form_id: int | |
| share_token: str | |
| is_public: bool | |
| expires_at: Optional[datetime] | |
| allow_multiple_submissions: bool | |
| collect_email: bool | |
| custom_thank_you_message: Optional[str] | |
| og_image_url: Optional[str] = None | |
| created_at: datetime | |
| class Config: | |
| from_attributes = True | |
| class PublicFormDetail(BaseModel): | |
| """Public form structure for submissions""" | |
| form: FormResponse | |
| public_settings: PublicFormResponse | |
| class Config: | |
| from_attributes = True | |
| # Export schemas | |
| class ExportFormat(BaseModel): | |
| format: str = Field(..., pattern="^(csv|json)$") | |
| class ExportResponse(BaseModel): | |
| download_url: str | |
| format: str | |
| total_responses: int | |
| # Chat editing schemas | |
| class ChatMessage(BaseModel): | |
| """Schema for chat-based form editing""" | |
| message: str = Field(..., min_length=1, max_length=1000) | |
| class ChatResponse(BaseModel): | |
| """Response from chat-based form editing""" | |
| route: str # add_component, edit_component, general_form_query, need_more_clarity | |
| response: Dict[str, Any] # Updated component or form structure or answer text | |
| changes_made: Optional[str] = None # Summary of changes if applicable | |
| class Config: | |
| from_attributes = True | |