# Attendee Questions API Guide

## What Is It?

A customizable questionnaire system that event organizers attach to their events to collect information from attendees during registration. Think of it like Google Forms, but built specifically for events and integrated into the ticket purchase flow.

---

## The Two Sides

### Organizer Side (Building the Form)

When an organizer creates an event, they can optionally enable "Attendee Questions." The system automatically creates an empty form with one page. The organizer then builds their questionnaire by:

1. **Adding pages** - to organize questions into logical sections (e.g., "Personal Info", "Dietary Needs", "Travel Details")

2. **Adding fields to pages** - choosing from various field types like text, email, phone, dropdowns, checkboxes, ratings, file uploads, etc.

3. **Adding options** - for choice-based fields (dropdown, radio, checkbox), the organizer adds the available choices

4. **Configuring settings** - deciding when to show the form (before or after checkout), whether it's required, and if walk-in attendees should also complete it

The organizer can reorder pages, fields, and options. They can edit labels, add descriptions, set validation rules (minimum length, date ranges, file size limits), and mark fields as required or optional.

---

### Attendee Side (Filling the Form)

When someone registers for a published event, they see the questionnaire. The system works page-by-page:

1. **View a page** - attendee sees one page of questions at a time with navigation showing progress (Page 1 of 3)

2. **Fill and save** - as the attendee completes a page and moves to the next, their answers are validated and saved automatically. If any answer is invalid (wrong format, too short, invalid selection), the page won't save and they see specific error messages for each problematic field.

3. **Submit** - when ready, the attendee clicks submit. The system checks ALL pages to ensure every required field is answered and all answers are valid. If everything passes, the submission is finalized. If not, they see a summary showing which pages have problems.

The key principle: **validate before saving, never store invalid data**. This keeps the database clean and gives immediate feedback.

---

## The Analytics Side (Viewing Results)

Once attendees start submitting, the organizer can view comprehensive analytics:

- **Summary statistics** - total submissions, completion rates, average time to complete, submission trends over time, and which pages have the highest drop-off rates

- **Field-by-field breakdown** - for each question, see response rates and detailed analysis. For choice fields, see how many people selected each option with percentages. For numeric fields, see averages, ranges, and distributions. For text fields, see common words and length statistics.

- **Spreadsheet view** - all responses in a table format, like Google Forms' response spreadsheet, with each row being one submission and each column being one question

- **Export** - download all data as CSV or Excel for external analysis

---

## How Is It Useful?

### For Event Organizers

**Logistics planning:**
- Collect t-shirt sizes to order the right quantities
- Gather dietary requirements for catering
- Know arrival times for transportation planning
- Get emergency contact information for safety

**Attendee profiling:**
- Ask about interests for personalized experiences
- Collect company/role info for networking features
- Understand how attendees heard about the event for marketing

**Compliance and safety:**
- Collect required documents (ID uploads)
- Gather health declarations
- Get consent for photography/recording
- Verify age requirements

**Engagement:**
- Ask what sessions attendees plan to attend
- Collect questions for Q&A panels
- Gather song requests for performers
- Get feedback on previous events

### For Attendees

**Smoother experience:**
- Complete registration in one flow instead of separate forms
- Save progress and return later (draft mode)
- Clear validation messages prevent submission errors
- Know exactly what's required vs optional

**Personalization:**
- Their preferences are captured for a tailored experience
- Dietary needs are communicated without awkward conversations
- Special requirements are noted in advance

---

## Real-World Example

**Music Festival Scenario:**

An organizer creates a 3-day festival. They enable attendee questions with two pages:

**Page 1: Essential Info**
- Emergency contact name (required, text)
- Emergency contact phone (required, phone validation)
- T-shirt size (required, dropdown: S/M/L/XL)
- Camping or day pass? (required, radio)

**Page 2: Preferences**
- Dietary restrictions (optional, checkbox: vegetarian, vegan, gluten-free, halal, kosher)
- Other dietary notes (optional, textarea)
- Which headliner are you most excited for? (optional, dropdown with artist names)

When 500 people register, the organizer sees:
- 65% chose Medium or Large t-shirts
- 23% have dietary restrictions (42% of those are vegetarian)
- Artist X is the most anticipated headliner with 45% of votes
- Page 2 has 15% drop-off (people skipping optional questions)

They export the data to:
- Order t-shirts: 50 S, 180 M, 170 L, 100 XL
- Tell catering: 115 vegetarian meals, 45 vegan, 60 gluten-free
- Adjust sound check priority based on headliner popularity

---

## Why This Design?

**Page-by-page saves** prevent data loss. If someone fills 3 pages then loses internet, they don't lose everything.

**Strict validation before saving** means the database only contains valid, usable data. No garbage entries to clean up later.

**Empty-body submit** means the final submission is just a validation check, not a data transfer. Everything is already saved from auto-saves.

**Parallel page validation on submit** makes the final check fast even with many pages.

**Separation of draft and published** means organizers can freely edit their form while building the event, but once published and people start responding, the structure is stable.

---

## Summary

It's a form builder tailored for events. Organizers build custom questionnaires, attendees fill them page-by-page with auto-save and validation, and organizers get rich analytics to plan better events. The technical design prioritizes data integrity, user experience, and actionable insights.

## System Flow

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                           ORGANIZER FLOW                                    │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  1. Create Event Draft                                                      │
│     POST /api/v1/e-events/drafts                                           │
│                    ↓                                                        │
│  2. Enable Attendee Questions                                               │
│     PUT /api/v1/e-events/drafts/{draftId}/attendee-questions               │
│                    ↓                                                        │
│  3. Add Pages (optional - default page created automatically)               │
│     POST /api/v1/e-events/drafts/{draftId}/attendee-questions/pages        │
│                    ↓                                                        │
│  4. Add Fields to Pages                                                     │
│     POST /api/v1/e-events/drafts/{draftId}/attendee-questions/pages/{pageId}/fields │
│                    ↓                                                        │
│  5. Add Options to Choice Fields (dropdown/radio/checkbox)                  │
│     POST /api/v1/e-events/drafts/{draftId}/attendee-questions/fields/{fieldId}/options │
│                    ↓                                                        │
│  6. Publish Event                                                           │
│     POST /api/v1/e-events/drafts/{draftId}/publish                         │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                           ATTENDEE FLOW                                     │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  1. View Questionnaire (check if registration open)                         │
│     GET /api/v1/e-events/{eventId}/attendee-questions                      │
│                    ↓                                                        │
│  2. Get Each Page                                                           │
│     GET /api/v1/e-events/{eventId}/attendee-questions/pages/{pageNumber}   │
│                    ↓                                                        │
│  3. Save Page Answers (auto-save per page)                                  │
│     PATCH /api/v1/e-events/{eventId}/attendee-questions/responses/pages/{n}│
│                    ↓                                                        │
│  4. Submit Final Response                                                   │
│     POST /api/v1/e-events/{eventId}/attendee-questions/responses/submit    │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                           ANALYTICS FLOW (Organizer Only)                   │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  GET /api/v1/e-events/{eventId}/attendee-questions/analytics/summary       │
│  GET /api/v1/e-events/{eventId}/attendee-questions/analytics/fields        │
│  GET /api/v1/e-events/{eventId}/attendee-questions/analytics/fields/{id}   │
│  GET /api/v1/e-events/{eventId}/attendee-questions/analytics/responses     │
│  GET /api/v1/e-events/{eventId}/attendee-questions/analytics/export/csv    │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
```

---

## Authentication

All endpoints require JWT authentication except public event viewing.

```
Header: Authorization: Bearer {jwt_token}
```

---

# PART 1: ORGANIZER ENDPOINTS

## Base URL
```
/api/v1/e-events/drafts/{draftId}/attendee-questions
```

---

### 1.1 Enable Attendee Questions

Creates a new questionnaire for the event draft. Automatically creates an empty form with one default page.

**Endpoint:**
```
PUT /api/v1/e-events/drafts/{draftId}/attendee-questions
```

**Request:**
```json
{
  "displayTime": "BEFORE_CHECKOUT",
  "isRequiredOnline": true,
  "applyToAtDoor": false
}
```

**Request Fields:**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `displayTime` | enum | No | When to show form: `BEFORE_CHECKOUT` or `AFTER_CHECKOUT`. Default: `BEFORE_CHECKOUT` |
| `isRequiredOnline` | boolean | No | Must complete before checkout? Default: `false` |
| `applyToAtDoor` | boolean | No | Show to walk-in attendees? Default: `false` |

**Response (201 Created):**
```json
{
  "success": true,
  "httpStatus": "CREATED",
  "message": "Attendee questions enabled",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "formId": "770e8400-e29b-41d4-a716-446655440002",
    "displayTime": "BEFORE_CHECKOUT",
    "isRequiredOnline": true,
    "applyToAtDoor": false,
    "createdAt": "2025-01-23T10:30:00Z",
    "updatedAt": "2025-01-23T10:30:00Z"
  }
}
```

**Error Responses:**

| Status | Message |
|--------|---------|
| 404 | Draft not found |
| 403 | You don't have access to this draft |
| 403 | Attendee questions already enabled. Use update instead. |

---

### 1.2 Update Attendee Questions Settings

**Endpoint:**
```
PATCH /api/v1/e-events/drafts/{draftId}/attendee-questions
```

**Request:**
```json
{
  "displayTime": "AFTER_CHECKOUT",
  "isRequiredOnline": false
}
```

*All fields optional - only updates provided fields.*

**Response (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Settings updated",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "formId": "770e8400-e29b-41d4-a716-446655440002",
    "displayTime": "AFTER_CHECKOUT",
    "isRequiredOnline": false,
    "applyToAtDoor": false,
    "createdAt": "2025-01-23T10:30:00Z",
    "updatedAt": "2025-01-23T10:35:00Z"
  }
}
```

---

### 1.3 Get Attendee Questions (with full form)

**Endpoint:**
```
GET /api/v1/e-events/drafts/{draftId}/attendee-questions
```

**Response (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Attendee questions retrieved",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "formId": "770e8400-e29b-41d4-a716-446655440002",
    "displayTime": "BEFORE_CHECKOUT",
    "isRequiredOnline": true,
    "applyToAtDoor": false,
    "createdAt": "2025-01-23T10:30:00Z",
    "updatedAt": "2025-01-23T10:30:00Z",
    "form": {
      "formId": "770e8400-e29b-41d4-a716-446655440002",
      "title": "Attendee Questions - Music Festival 2025",
      "description": "Custom questions for event attendees",
      "pages": [
        {
          "pageId": "880e8400-e29b-41d4-a716-446655440003",
          "title": "Personal Information",
          "description": "Basic attendee details",
          "displayOrder": 1,
          "fields": [
            {
              "fieldId": "990e8400-e29b-41d4-a716-446655440004",
              "type": "TEXT",
              "label": "Emergency Contact Name",
              "description": "Who should we contact in case of emergency?",
              "placeholder": "Full name",
              "displayOrder": 1,
              "required": true,
              "validation": {
                "minLength": 2,
                "maxLength": 100
              },
              "options": []
            },
            {
              "fieldId": "aa0e8400-e29b-41d4-a716-446655440005",
              "type": "PHONE",
              "label": "Emergency Contact Phone",
              "displayOrder": 2,
              "required": true,
              "options": []
            },
            {
              "fieldId": "bb0e8400-e29b-41d4-a716-446655440006",
              "type": "DROPDOWN",
              "label": "T-Shirt Size",
              "displayOrder": 3,
              "required": true,
              "options": [
                {"optionId": "opt1", "label": "Small", "displayOrder": 1},
                {"optionId": "opt2", "label": "Medium", "displayOrder": 2},
                {"optionId": "opt3", "label": "Large", "displayOrder": 3},
                {"optionId": "opt4", "label": "X-Large", "displayOrder": 4}
              ]
            }
          ]
        },
        {
          "pageId": "cc0e8400-e29b-41d4-a716-446655440007",
          "title": "Dietary Requirements",
          "displayOrder": 2,
          "fields": [
            {
              "fieldId": "dd0e8400-e29b-41d4-a716-446655440008",
              "type": "CHECKBOX",
              "label": "Dietary Restrictions",
              "description": "Select all that apply",
              "displayOrder": 1,
              "required": false,
              "options": [
                {"optionId": "opt5", "label": "Vegetarian", "displayOrder": 1},
                {"optionId": "opt6", "label": "Vegan", "displayOrder": 2},
                {"optionId": "opt7", "label": "Gluten-free", "displayOrder": 3},
                {"optionId": "opt8", "label": "Halal", "displayOrder": 4},
                {"optionId": "opt9", "label": "Kosher", "displayOrder": 5}
              ]
            },
            {
              "fieldId": "ee0e8400-e29b-41d4-a716-446655440009",
              "type": "TEXTAREA",
              "label": "Other Dietary Notes",
              "placeholder": "Any allergies or special requirements?",
              "displayOrder": 2,
              "required": false
            }
          ]
        }
      ]
    }
  }
}
```

**Response when not configured (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Attendee questions not configured",
  "data": null
}
```

---

### 1.4 Disable Attendee Questions

Permanently deletes the form and all configuration.

**Endpoint:**
```
DELETE /api/v1/e-events/drafts/{draftId}/attendee-questions
```

**Response (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Attendee questions disabled"
}
```

---

## Pages Management

### 1.5 Add Page

**Endpoint:**
```
POST /api/v1/e-events/drafts/{draftId}/attendee-questions/pages
```

**Request:**
```json
{
  "title": "Travel Information",
  "description": "Help us plan your arrival"
}
```

**Response (201 Created):**
```json
{
  "success": true,
  "httpStatus": "CREATED",
  "message": "Page added",
  "data": {
    "pageId": "ff0e8400-e29b-41d4-a716-446655440010",
    "title": "Travel Information",
    "description": "Help us plan your arrival",
    "displayOrder": 3
  }
}
```

---

### 1.6 Update Page

**Endpoint:**
```
PATCH /api/v1/e-events/drafts/{draftId}/attendee-questions/pages/{pageId}
```

**Request:**
```json
{
  "title": "Travel & Accommodation",
  "description": "Updated description"
}
```

**Response (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Page updated",
  "data": {
    "pageId": "ff0e8400-e29b-41d4-a716-446655440010",
    "title": "Travel & Accommodation",
    "description": "Updated description",
    "displayOrder": 3
  }
}
```

---

### 1.7 Delete Page

**Endpoint:**
```
DELETE /api/v1/e-events/drafts/{draftId}/attendee-questions/pages/{pageId}
```

**Response (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Page deleted"
}
```

---

### 1.8 Reorder Pages

**Endpoint:**
```
POST /api/v1/e-events/drafts/{draftId}/attendee-questions/pages/reorder
```

**Request:**
```json
{
  "orderedIds": [
    "cc0e8400-e29b-41d4-a716-446655440007",
    "880e8400-e29b-41d4-a716-446655440003",
    "ff0e8400-e29b-41d4-a716-446655440010"
  ]
}
```

**Response (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Pages reordered"
}
```

---

## Fields Management

### 1.9 Add Field

**Endpoint:**
```
POST /api/v1/e-events/drafts/{draftId}/attendee-questions/pages/{pageId}/fields
```

**Request (Text Field):**
```json
{
  "type": "TEXT",
  "label": "Company Name",
  "description": "Your current employer",
  "placeholder": "Enter company name",
  "required": false,
  "validation": {
    "minLength": 2,
    "maxLength": 100
  }
}
```

**Request (Dropdown Field):**
```json
{
  "type": "DROPDOWN",
  "label": "How did you hear about us?",
  "required": true
}
```

**Request (Rating Field):**
```json
{
  "type": "RATING",
  "label": "How excited are you for this event?",
  "required": true,
  "validation": {
    "min": 1,
    "max": 5
  }
}
```

**Request (File Upload Field):**
```json
{
  "type": "FILE",
  "label": "Upload ID Document",
  "description": "Government-issued ID for verification",
  "required": true,
  "validation": {
    "maxSizeMb": 5,
    "accept": "image/*,.pdf"
  }
}
```

**Available Field Types:**

| Type | Description | Has Options |
|------|-------------|-------------|
| `TEXT` | Single line text | No |
| `TEXTAREA` | Multi-line text | No |
| `EMAIL` | Email with validation | No |
| `PHONE` | Phone number | No |
| `NUMBER` | Numeric input | No |
| `DATE` | Date picker | No |
| `TIME` | Time picker | No |
| `DATETIME` | Date and time | No |
| `DROPDOWN` | Single select dropdown | Yes |
| `RADIO` | Single select radio buttons | Yes |
| `CHECKBOX` | Multi-select checkboxes | Yes |
| `RATING` | Star rating | No |
| `SCALE` | Linear scale (1-10) | No |
| `SLIDER` | Slider input | No |
| `FILE` | File upload | No |
| `URL` | URL with validation | No |
| `CURRENCY` | Money input | No |
| `SECTION_HEADER` | Display only - section title | No |
| `PARAGRAPH` | Display only - text block | No |

**Response (201 Created):**
```json
{
  "success": true,
  "httpStatus": "CREATED",
  "message": "Field added",
  "data": {
    "fieldId": "110e8400-e29b-41d4-a716-446655440011",
    "type": "DROPDOWN",
    "label": "How did you hear about us?",
    "displayOrder": 1,
    "required": true,
    "options": []
  }
}
```

---

### 1.10 Update Field

**Endpoint:**
```
PATCH /api/v1/e-events/drafts/{draftId}/attendee-questions/fields/{fieldId}
```

**Request:**
```json
{
  "label": "How did you discover this event?",
  "required": false,
  "description": "Help us improve our marketing"
}
```

**Response (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Field updated",
  "data": {
    "fieldId": "110e8400-e29b-41d4-a716-446655440011",
    "type": "DROPDOWN",
    "label": "How did you discover this event?",
    "description": "Help us improve our marketing",
    "displayOrder": 1,
    "required": false,
    "options": []
  }
}
```

---

### 1.11 Delete Field

**Endpoint:**
```
DELETE /api/v1/e-events/drafts/{draftId}/attendee-questions/fields/{fieldId}
```

**Response (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Field deleted"
}
```

---

### 1.12 Reorder Fields

**Endpoint:**
```
POST /api/v1/e-events/drafts/{draftId}/attendee-questions/pages/{pageId}/fields/reorder
```

**Request:**
```json
{
  "orderedIds": [
    "bb0e8400-e29b-41d4-a716-446655440006",
    "990e8400-e29b-41d4-a716-446655440004",
    "aa0e8400-e29b-41d4-a716-446655440005"
  ]
}
```

**Response (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Fields reordered"
}
```

---

## Options Management (for DROPDOWN, RADIO, CHECKBOX)

### 1.13 Add Option

**Endpoint:**
```
POST /api/v1/e-events/drafts/{draftId}/attendee-questions/fields/{fieldId}/options
```

**Request:**
```json
{
  "label": "Social Media"
}
```

**Response (201 Created):**
```json
{
  "success": true,
  "httpStatus": "CREATED",
  "message": "Option added",
  "data": {
    "optionId": "220e8400-e29b-41d4-a716-446655440012",
    "label": "Social Media",
    "displayOrder": 1
  }
}
```

---

### 1.14 Update Option

**Endpoint:**
```
PATCH /api/v1/e-events/drafts/{draftId}/attendee-questions/options/{optionId}
```

**Request:**
```json
{
  "label": "Social Media (Facebook, Instagram, etc.)"
}
```

**Response (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Option updated",
  "data": {
    "optionId": "220e8400-e29b-41d4-a716-446655440012",
    "label": "Social Media (Facebook, Instagram, etc.)",
    "displayOrder": 1
  }
}
```

---

### 1.15 Delete Option

**Endpoint:**
```
DELETE /api/v1/e-events/drafts/{draftId}/attendee-questions/options/{optionId}
```

**Response (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Option deleted"
}
```

---

### 1.16 Reorder Options

**Endpoint:**
```
POST /api/v1/e-events/drafts/{draftId}/attendee-questions/fields/{fieldId}/options/reorder
```

**Request:**
```json
{
  "orderedIds": [
    "220e8400-e29b-41d4-a716-446655440012",
    "330e8400-e29b-41d4-a716-446655440013",
    "440e8400-e29b-41d4-a716-446655440014"
  ]
}
```

**Response (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Options reordered"
}
```

---

# PART 2: ATTENDEE ENDPOINTS (Public)

## Base URL
```
/api/v1/e-events/{eventId}/attendee-questions
```

*Note: These endpoints require the event to be PUBLISHED.*

---

### 2.1 Get Questionnaire (First Page)

**Endpoint:**
```
GET /api/v1/e-events/{eventId}/attendee-questions
```

**Response - No questionnaire configured:**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "No questionnaire for this event",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "eventTitle": "Music Festival 2025",
    "hasForm": false,
    "registrationOpen": false,
    "message": "No questionnaire for this event"
  }
}
```

**Response - Registration not yet open:**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Registration opens on 2025-02-01",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "eventTitle": "Music Festival 2025",
    "hasForm": true,
    "registrationOpen": false,
    "message": "Registration opens on 2025-02-01",
    "registrationOpensAt": "2025-02-01T09:00:00Z",
    "registrationClosesAt": "2025-02-15T18:00:00Z",
    "displayTime": "BEFORE_CHECKOUT",
    "isRequired": true
  }
}
```

**Response - Registration closed:**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Registration closed on 2025-02-15",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "eventTitle": "Music Festival 2025",
    "hasForm": true,
    "registrationOpen": false,
    "message": "Registration closed on 2025-02-15",
    "registrationOpensAt": "2025-02-01T09:00:00Z",
    "registrationClosesAt": "2025-02-15T18:00:00Z"
  }
}
```

**Response - Registration open (returns page 1):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Questionnaire retrieved",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "eventTitle": "Music Festival 2025",
    "hasForm": true,
    "registrationOpen": true,
    "registrationOpensAt": "2025-02-01T09:00:00Z",
    "registrationClosesAt": "2025-02-15T18:00:00Z",
    "displayTime": "BEFORE_CHECKOUT",
    "isRequired": true,
    "currentPage": 1,
    "totalPages": 2,
    "formTitle": "Attendee Questions - Music Festival 2025",
    "formDescription": "Please complete this questionnaire",
    "page": {
      "pageId": "880e8400-e29b-41d4-a716-446655440003",
      "title": "Personal Information",
      "description": "Basic attendee details",
      "displayOrder": 1,
      "fields": [
        {
          "fieldId": "990e8400-e29b-41d4-a716-446655440004",
          "type": "TEXT",
          "label": "Emergency Contact Name",
          "description": "Who should we contact in case of emergency?",
          "placeholder": "Full name",
          "displayOrder": 1,
          "required": true,
          "validation": {
            "minLength": 2,
            "maxLength": 100
          },
          "options": []
        },
        {
          "fieldId": "aa0e8400-e29b-41d4-a716-446655440005",
          "type": "PHONE",
          "label": "Emergency Contact Phone",
          "displayOrder": 2,
          "required": true,
          "options": []
        },
        {
          "fieldId": "bb0e8400-e29b-41d4-a716-446655440006",
          "type": "DROPDOWN",
          "label": "T-Shirt Size",
          "displayOrder": 3,
          "required": true,
          "options": [
            {"optionId": "opt1", "label": "Small", "displayOrder": 1},
            {"optionId": "opt2", "label": "Medium", "displayOrder": 2},
            {"optionId": "opt3", "label": "Large", "displayOrder": 3},
            {"optionId": "opt4", "label": "X-Large", "displayOrder": 4}
          ]
        }
      ]
    }
  }
}
```

---

### 2.2 Get Specific Page

**Endpoint:**
```
GET /api/v1/e-events/{eventId}/attendee-questions/pages/{pageNumber}
```

**Example:**
```
GET /api/v1/e-events/660e8400-e29b-41d4-a716-446655440001/attendee-questions/pages/2
```

**Response (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Page 2 of 2",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "eventTitle": "Music Festival 2025",
    "hasForm": true,
    "registrationOpen": true,
    "currentPage": 2,
    "totalPages": 2,
    "page": {
      "pageId": "cc0e8400-e29b-41d4-a716-446655440007",
      "title": "Dietary Requirements",
      "displayOrder": 2,
      "fields": [
        {
          "fieldId": "dd0e8400-e29b-41d4-a716-446655440008",
          "type": "CHECKBOX",
          "label": "Dietary Restrictions",
          "description": "Select all that apply",
          "displayOrder": 1,
          "required": false,
          "options": [
            {"optionId": "opt5", "label": "Vegetarian", "displayOrder": 1},
            {"optionId": "opt6", "label": "Vegan", "displayOrder": 2},
            {"optionId": "opt7", "label": "Gluten-free", "displayOrder": 3},
            {"optionId": "opt8", "label": "Halal", "displayOrder": 4},
            {"optionId": "opt9", "label": "Kosher", "displayOrder": 5}
          ]
        },
        {
          "fieldId": "ee0e8400-e29b-41d4-a716-446655440009",
          "type": "TEXTAREA",
          "label": "Other Dietary Notes",
          "placeholder": "Any allergies or special requirements?",
          "displayOrder": 2,
          "required": false
        }
      ]
    }
  }
}
```

**Error - Page not found:**
```json
{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Page not found. Valid pages: 1 to 2"
}
```

---

### 2.3 Save Page Answers (Auto-Save)

Saves answers for a single page. **Validates ALL fields on the page before saving.** If any field is invalid, nothing is saved.

**Endpoint:**
```
PATCH /api/v1/e-events/{eventId}/attendee-questions/responses/pages/{pageNumber}
```

**Request:**
```json
{
  "answers": {
    "990e8400-e29b-41d4-a716-446655440004": {
      "fieldId": "990e8400-e29b-41d4-a716-446655440004",
      "value": "John Doe"
    },
    "aa0e8400-e29b-41d4-a716-446655440005": {
      "fieldId": "aa0e8400-e29b-41d4-a716-446655440005",
      "value": "+255712345678"
    },
    "bb0e8400-e29b-41d4-a716-446655440006": {
      "fieldId": "bb0e8400-e29b-41d4-a716-446655440006",
      "value": "Large"
    }
  }
}
```

**Answer Format by Field Type:**

| Field Type | Value Format | Example |
|------------|--------------|---------|
| TEXT, TEXTAREA, EMAIL, PHONE, URL | string | `"John Doe"` |
| NUMBER, CURRENCY, RATING, SCALE, SLIDER | number | `42` or `4.5` |
| DATE | string (YYYY-MM-DD) | `"2025-02-15"` |
| TIME | string (HH:MM) | `"14:30"` |
| DATETIME | string (ISO) | `"2025-02-15T14:30:00"` |
| DROPDOWN, RADIO | string (selected label) | `"Large"` |
| CHECKBOX | array of strings | `["Vegetarian", "Gluten-free"]` |
| FILE | object | See below |

**File Upload Answer:**
```json
{
  "fieldId": "file-field-id",
  "value": null,
  "fileUrl": "https://storage.example.com/uploads/id-doc.pdf",
  "fileName": "id-doc.pdf",
  "fileSize": 1048576,
  "fileType": "application/pdf"
}
```

**Response - Success (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Page 1 saved",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "pageNumber": 1,
    "saved": true,
    "savedAt": "2025-01-23T10:45:00Z",
    "isValid": true,
    "errors": [],
    "totalFieldsOnPage": 3,
    "answeredFieldsOnPage": 3,
    "overallProgress": {
      "totalPages": 2,
      "completedPages": 1,
      "totalFields": 5,
      "answeredFields": 3,
      "completionPercentage": 60
    }
  }
}
```

**Response - Validation Failed (400 Bad Request):**
```json
{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Validation failed - page not saved",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "pageNumber": 1,
    "saved": false,
    "isValid": false,
    "errors": [
      {
        "fieldId": "aa0e8400-e29b-41d4-a716-446655440005",
        "fieldLabel": "Emergency Contact Phone",
        "errorCode": "INVALID_PHONE",
        "message": "Please enter a valid phone number"
      },
      {
        "fieldId": "bb0e8400-e29b-41d4-a716-446655440006",
        "fieldLabel": "T-Shirt Size",
        "errorCode": "INVALID_OPTION",
        "message": "Selected option is not valid"
      }
    ],
    "totalFieldsOnPage": 3,
    "answeredFieldsOnPage": 3,
    "overallProgress": {
      "totalPages": 2,
      "completedPages": 0,
      "totalFields": 5,
      "answeredFields": 0,
      "completionPercentage": 0
    }
  }
}
```

**Validation Error Codes:**

| Code | Description |
|------|-------------|
| `REQUIRED` | Required field is missing |
| `INVALID_EMAIL` | Invalid email format |
| `INVALID_PHONE` | Invalid phone number |
| `INVALID_NUMBER` | Not a valid number |
| `INVALID_DATE` | Invalid date format |
| `INVALID_TIME` | Invalid time format |
| `INVALID_DATETIME` | Invalid datetime format |
| `INVALID_URL` | Invalid URL format |
| `INVALID_OPTION` | Selected option not in list |
| `INVALID_SELECTION` | Invalid selection format |
| `TOO_SHORT` | Text too short (minLength) |
| `TOO_LONG` | Text too long (maxLength) |
| `BELOW_MIN` | Number below minimum |
| `ABOVE_MAX` | Number above maximum |
| `DATE_TOO_EARLY` | Date before minDate |
| `DATE_TOO_LATE` | Date after maxDate |
| `TOO_FEW_SELECTIONS` | Not enough checkboxes |
| `TOO_MANY_SELECTIONS` | Too many checkboxes |
| `PATTERN_MISMATCH` | Doesn't match regex |
| `FILE_TOO_LARGE` | File exceeds maxSizeMb |
| `INVALID_FILE_TYPE` | File type not accepted |

---

### 2.4 Submit Final Response

Submits the form. **No request body needed** - validates all saved pages and submits if all valid.

**Endpoint:**
```
POST /api/v1/e-events/{eventId}/attendee-questions/responses/submit
```

**Response - Success (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Submission successful",
  "data": {
    "responseId": "550e8400-e29b-41d4-a716-446655440099",
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "success": true,
    "status": "SUBMITTED",
    "submittedAt": "2025-01-23T10:50:00Z",
    "pageValidations": [
      {
        "pageNumber": 1,
        "pageTitle": "Personal Information",
        "isValid": true,
        "hasAnswers": true,
        "totalFields": 3,
        "answeredFields": 3,
        "requiredFields": 3,
        "requiredAnswered": 3,
        "errors": []
      },
      {
        "pageNumber": 2,
        "pageTitle": "Dietary Requirements",
        "isValid": true,
        "hasAnswers": true,
        "totalFields": 2,
        "answeredFields": 1,
        "requiredFields": 0,
        "requiredAnswered": 0,
        "errors": []
      }
    ],
    "totalPages": 2,
    "validPages": 2,
    "invalidPages": 0,
    "allPagesValid": true
  }
}
```

**Response - Validation Failed (400 Bad Request):**
```json
{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Validation failed - 1 page(s) have errors",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "success": false,
    "status": "DRAFT",
    "pageValidations": [
      {
        "pageNumber": 1,
        "pageTitle": "Personal Information",
        "isValid": false,
        "hasAnswers": true,
        "totalFields": 3,
        "answeredFields": 2,
        "requiredFields": 3,
        "requiredAnswered": 2,
        "errors": [
          {
            "fieldId": "bb0e8400-e29b-41d4-a716-446655440006",
            "fieldLabel": "T-Shirt Size",
            "errorCode": "REQUIRED",
            "message": "T-Shirt Size is required"
          }
        ]
      },
      {
        "pageNumber": 2,
        "pageTitle": "Dietary Requirements",
        "isValid": true,
        "hasAnswers": false,
        "totalFields": 2,
        "answeredFields": 0,
        "requiredFields": 0,
        "requiredAnswered": 0,
        "errors": []
      }
    ],
    "totalPages": 2,
    "validPages": 1,
    "invalidPages": 1,
    "allPagesValid": false
  }
}
```

**Error - No draft found:**
```json
{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "No draft found. Please save your answers first."
}
```

---

### 2.5 Get Submission Status

**Endpoint:**
```
GET /api/v1/e-events/{eventId}/attendee-questions/responses/status
```

**Response - No submission started:**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "No submission started",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "success": false,
    "status": null,
    "totalPages": 2,
    "validPages": 0,
    "invalidPages": 0,
    "allPagesValid": false
  }
}
```

**Response - Draft in progress:**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Status: DRAFT",
  "data": {
    "responseId": "550e8400-e29b-41d4-a716-446655440099",
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "success": false,
    "status": "DRAFT",
    "submittedAt": null,
    "pageValidations": [
      {
        "pageNumber": 1,
        "pageTitle": "Personal Information",
        "isValid": true,
        "hasAnswers": true,
        "totalFields": 3,
        "answeredFields": 3,
        "requiredFields": 3,
        "requiredAnswered": 3,
        "errors": []
      },
      {
        "pageNumber": 2,
        "pageTitle": "Dietary Requirements",
        "isValid": true,
        "hasAnswers": false,
        "totalFields": 2,
        "answeredFields": 0,
        "requiredFields": 0,
        "requiredAnswered": 0,
        "errors": []
      }
    ],
    "totalPages": 2,
    "validPages": 2,
    "invalidPages": 0,
    "allPagesValid": true
  }
}
```

**Response - Already submitted:**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Status: SUBMITTED",
  "data": {
    "responseId": "550e8400-e29b-41d4-a716-446655440099",
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "success": true,
    "status": "SUBMITTED",
    "submittedAt": "2025-01-23T10:50:00Z",
    "totalPages": 2,
    "validPages": 2,
    "invalidPages": 0,
    "allPagesValid": true
  }
}
```

---

### 2.6 Withdraw Submission

**Endpoint:**
```
DELETE /api/v1/e-events/{eventId}/attendee-questions/responses
```

**Response (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Submission withdrawn"
}
```

---

# PART 3: ANALYTICS ENDPOINTS (Organizer Only)

## Base URL
```
/api/v1/e-events/{eventId}/attendee-questions/analytics
```

*Note: Only the event organizer can access analytics.*

---

### 3.1 Get Summary Statistics

**Endpoint:**
```
GET /api/v1/e-events/{eventId}/attendee-questions/analytics/summary
```

**Response (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Summary retrieved",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "eventTitle": "Music Festival 2025",
    "totalStarted": 250,
    "totalDrafts": 45,
    "totalSubmitted": 180,
    "totalWithdrawn": 25,
    "completionRate": 72.0,
    "dropOffRate": 28.0,
    "averageCompletionTimeSeconds": 185.5,
    "fastestCompletionSeconds": 45,
    "slowestCompletionSeconds": 890,
    "submissionTrend": [
      {"date": "2025-01-01", "count": 0},
      {"date": "2025-01-02", "count": 5},
      {"date": "2025-01-03", "count": 12},
      {"date": "2025-01-04", "count": 8},
      {"date": "2025-01-05", "count": 15},
      {"date": "2025-01-06", "count": 22},
      {"date": "2025-01-07", "count": 18}
    ],
    "pageDropOff": [
      {
        "pageNumber": 1,
        "pageTitle": "Personal Information",
        "started": 250,
        "completed": 220,
        "dropOffRate": 12.0
      },
      {
        "pageNumber": 2,
        "pageTitle": "Dietary Requirements",
        "started": 220,
        "completed": 180,
        "dropOffRate": 18.2
      }
    ],
    "firstSubmissionAt": "2025-01-02T09:15:00",
    "lastSubmissionAt": "2025-01-23T10:50:00",
    "generatedAt": "2025-01-23T11:00:00"
  }
}
```

---

### 3.2 Get All Fields Analytics

**Endpoint:**
```
GET /api/v1/e-events/{eventId}/attendee-questions/analytics/fields
```

**Response (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Fields analytics retrieved",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "totalResponses": 180,
    "fields": [
      {
        "fieldId": "990e8400-e29b-41d4-a716-446655440004",
        "label": "Emergency Contact Name",
        "type": "TEXT",
        "pageNumber": 1,
        "required": true,
        "responseCount": 180,
        "skippedCount": 0,
        "responseRate": 100.0,
        "textStats": {
          "averageLength": 15,
          "minLength": 5,
          "maxLength": 45,
          "commonWords": ["john", "jane", "mary", "james", "david"]
        }
      },
      {
        "fieldId": "bb0e8400-e29b-41d4-a716-446655440006",
        "label": "T-Shirt Size",
        "type": "DROPDOWN",
        "pageNumber": 1,
        "required": true,
        "responseCount": 180,
        "skippedCount": 0,
        "responseRate": 100.0,
        "optionBreakdown": [
          {"value": "Medium", "count": 65, "percentage": 36.1},
          {"value": "Large", "count": 58, "percentage": 32.2},
          {"value": "Small", "count": 35, "percentage": 19.4},
          {"value": "X-Large", "count": 22, "percentage": 12.2}
        ]
      },
      {
        "fieldId": "dd0e8400-e29b-41d4-a716-446655440008",
        "label": "Dietary Restrictions",
        "type": "CHECKBOX",
        "pageNumber": 2,
        "required": false,
        "responseCount": 95,
        "skippedCount": 85,
        "responseRate": 52.8,
        "optionBreakdown": [
          {"value": "Vegetarian", "count": 42, "percentage": 44.2},
          {"value": "Gluten-free", "count": 28, "percentage": 29.5},
          {"value": "Vegan", "count": 18, "percentage": 18.9},
          {"value": "Halal", "count": 12, "percentage": 12.6},
          {"value": "Kosher", "count": 5, "percentage": 5.3}
        ]
      }
    ]
  }
}
```

---

### 3.3 Get Single Field Analytics

**Endpoint:**
```
GET /api/v1/e-events/{eventId}/attendee-questions/analytics/fields/{fieldId}?page=0&size=20
```

**Response (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Field analytics retrieved",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "fieldId": "bb0e8400-e29b-41d4-a716-446655440006",
    "label": "T-Shirt Size",
    "type": "DROPDOWN",
    "required": true,
    "totalResponses": 180,
    "responseCount": 180,
    "skippedCount": 0,
    "responseRate": 100.0,
    "optionBreakdown": [
      {"value": "Medium", "count": 65, "percentage": 36.1},
      {"value": "Large", "count": 58, "percentage": 32.2},
      {"value": "Small", "count": 35, "percentage": 19.4},
      {"value": "X-Large", "count": 22, "percentage": 12.2}
    ],
    "responses": [
      {
        "responseId": "resp-001",
        "value": "Large",
        "submittedAt": "2025-01-23T10:50:00"
      },
      {
        "responseId": "resp-002",
        "value": "Medium",
        "submittedAt": "2025-01-23T10:48:00"
      }
    ],
    "totalResponseCount": 180,
    "page": 0,
    "pageSize": 20
  }
}
```

---

### 3.4 Get All Responses (Spreadsheet View)

**Endpoint:**
```
GET /api/v1/e-events/{eventId}/attendee-questions/analytics/responses?page=0&size=20
```

**Response (200 OK):**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Responses retrieved",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "totalResponses": 180,
    "page": 0,
    "pageSize": 20,
    "totalPages": 9,
    "columns": [
      {"fieldId": "990e8400-e29b-41d4-a716-446655440004", "label": "Emergency Contact Name", "type": "TEXT", "pageNumber": 1},
      {"fieldId": "aa0e8400-e29b-41d4-a716-446655440005", "label": "Emergency Contact Phone", "type": "PHONE", "pageNumber": 1},
      {"fieldId": "bb0e8400-e29b-41d4-a716-446655440006", "label": "T-Shirt Size", "type": "DROPDOWN", "pageNumber": 1},
      {"fieldId": "dd0e8400-e29b-41d4-a716-446655440008", "label": "Dietary Restrictions", "type": "CHECKBOX", "pageNumber": 2},
      {"fieldId": "ee0e8400-e29b-41d4-a716-446655440009", "label": "Other Dietary Notes", "type": "TEXTAREA", "pageNumber": 2}
    ],
    "responses": [
      {
        "responseId": "resp-001",
        "submittedById": "user-001",
        "submittedByName": "kibuti",
        "submittedByEmail": "kibuti@example.com",
        "status": "SUBMITTED",
        "startedAt": "2025-01-23T10:40:00",
        "submittedAt": "2025-01-23T10:50:00",
        "completionTimeSeconds": 600,
        "answers": {
          "990e8400-e29b-41d4-a716-446655440004": "John Doe",
          "aa0e8400-e29b-41d4-a716-446655440005": "+255712345678",
          "bb0e8400-e29b-41d4-a716-446655440006": "Large",
          "dd0e8400-e29b-41d4-a716-446655440008": ["Vegetarian", "Gluten-free"],
          "ee0e8400-e29b-41d4-a716-446655440009": "No nuts please"
        }
      },
      {
        "responseId": "resp-002",
        "submittedById": "user-002",
        "submittedByName": "john_doe",
        "submittedByEmail": "john@example.com",
        "status": "SUBMITTED",
        "startedAt": "2025-01-23T10:30:00",
        "submittedAt": "2025-01-23T10:45:00",
        "completionTimeSeconds": 900,
        "answers": {
          "990e8400-e29b-41d4-a716-446655440004": "Jane Smith",
          "aa0e8400-e29b-41d4-a716-446655440005": "+255798765432",
          "bb0e8400-e29b-41d4-a716-446655440006": "Medium",
          "dd0e8400-e29b-41d4-a716-446655440008": null,
          "ee0e8400-e29b-41d4-a716-446655440009": null
        }
      }
    ]
  }
}
```

---

### 3.5 Export to CSV

**Endpoint:**
```
GET /api/v1/e-events/{eventId}/attendee-questions/analytics/export/csv
```

**Response:** Downloads a CSV file

**CSV Content:**
```csv
Response ID,Submitted By,Email,Submitted At,Completion Time (seconds),Emergency Contact Name,Emergency Contact Phone,T-Shirt Size,Dietary Restrictions,Other Dietary Notes
resp-001,kibuti,kibuti@example.com,2025-01-23T10:50:00,600,John Doe,+255712345678,Large,Vegetarian; Gluten-free,No nuts please
resp-002,john_doe,john@example.com,2025-01-23T10:45:00,900,Jane Smith,+255798765432,Medium,,
```

---

### 3.6 Export to Excel

**Endpoint:**
```
GET /api/v1/e-events/{eventId}/attendee-questions/analytics/export/excel
```

**Response:** Downloads an Excel (.xlsx) file

---

# PART 4: COMPLETE ENDPOINTS REFERENCE

## Organizer Endpoints (Draft Events)

| Method | Endpoint | Description |
|--------|----------|-------------|
| PUT | `/drafts/{draftId}/attendee-questions` | Enable questionnaire |
| PATCH | `/drafts/{draftId}/attendee-questions` | Update settings |
| GET | `/drafts/{draftId}/attendee-questions` | Get with full form |
| DELETE | `/drafts/{draftId}/attendee-questions` | Disable (delete) |
| POST | `/drafts/{draftId}/attendee-questions/pages` | Add page |
| PATCH | `/drafts/{draftId}/attendee-questions/pages/{pageId}` | Update page |
| DELETE | `/drafts/{draftId}/attendee-questions/pages/{pageId}` | Delete page |
| POST | `/drafts/{draftId}/attendee-questions/pages/reorder` | Reorder pages |
| POST | `/drafts/{draftId}/attendee-questions/pages/{pageId}/fields` | Add field |
| PATCH | `/drafts/{draftId}/attendee-questions/fields/{fieldId}` | Update field |
| DELETE | `/drafts/{draftId}/attendee-questions/fields/{fieldId}` | Delete field |
| POST | `/drafts/{draftId}/attendee-questions/pages/{pageId}/fields/reorder` | Reorder fields |
| POST | `/drafts/{draftId}/attendee-questions/fields/{fieldId}/options` | Add option |
| PATCH | `/drafts/{draftId}/attendee-questions/options/{optionId}` | Update option |
| DELETE | `/drafts/{draftId}/attendee-questions/options/{optionId}` | Delete option |
| POST | `/drafts/{draftId}/attendee-questions/fields/{fieldId}/options/reorder` | Reorder options |

## Attendee Endpoints (Published Events)

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/{eventId}/attendee-questions` | Get form (page 1) |
| GET | `/{eventId}/attendee-questions/pages/{n}` | Get specific page |
| PATCH | `/{eventId}/attendee-questions/responses/pages/{n}` | Save page (auto-save) |
| POST | `/{eventId}/attendee-questions/responses/submit` | Submit (no body) |
| GET | `/{eventId}/attendee-questions/responses/status` | Get my status |
| DELETE | `/{eventId}/attendee-questions/responses` | Withdraw |

## Analytics Endpoints (Organizer Only)

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/{eventId}/attendee-questions/analytics/summary` | Overall stats |
| GET | `/{eventId}/attendee-questions/analytics/fields` | All fields breakdown |
| GET | `/{eventId}/attendee-questions/analytics/fields/{fieldId}` | Single field detail |
| GET | `/{eventId}/attendee-questions/analytics/responses` | Spreadsheet view |
| GET | `/{eventId}/attendee-questions/analytics/export/csv` | Download CSV |
| GET | `/{eventId}/attendee-questions/analytics/export/excel` | Download Excel |

---

# PART 5: INSOMNIA TESTING GUIDE

## Setup Environment Variables

```
base_url: http://localhost:8080/api/v1
jwt_token: <your_token>
draft_id: <your_draft_id>
event_id: <your_published_event_id>
page_id: <page_uuid>
field_id: <field_uuid>
option_id: <option_uuid>
```

## Testing Flow

### Step 1: Create Event Draft
```
POST {{base_url}}/e-events/drafts
Authorization: Bearer {{jwt_token}}
Content-Type: application/json

{
  "title": "Test Music Festival 2025",
  "categoryId": "{{category_id}}",
  "eventFormat": "IN_PERSON",
  "description": "Test event for questionnaire"
}
```

### Step 2: Enable Attendee Questions
```
PUT {{base_url}}/e-events/drafts/{{draft_id}}/attendee-questions
Authorization: Bearer {{jwt_token}}
Content-Type: application/json

{
  "displayTime": "BEFORE_CHECKOUT",
  "isRequiredOnline": true,
  "applyToAtDoor": false
}
```

### Step 3: Get Questionnaire (see default page)
```
GET {{base_url}}/e-events/drafts/{{draft_id}}/attendee-questions
Authorization: Bearer {{jwt_token}}
```

### Step 4: Add Text Field
```
POST {{base_url}}/e-events/drafts/{{draft_id}}/attendee-questions/pages/{{page_id}}/fields
Authorization: Bearer {{jwt_token}}
Content-Type: application/json

{
  "type": "TEXT",
  "label": "Emergency Contact Name",
  "placeholder": "Full name",
  "required": true,
  "validation": {
    "minLength": 2,
    "maxLength": 100
  }
}
```

### Step 5: Add Dropdown Field
```
POST {{base_url}}/e-events/drafts/{{draft_id}}/attendee-questions/pages/{{page_id}}/fields
Authorization: Bearer {{jwt_token}}
Content-Type: application/json

{
  "type": "DROPDOWN",
  "label": "T-Shirt Size",
  "required": true
}
```

### Step 6: Add Options to Dropdown
```
POST {{base_url}}/e-events/drafts/{{draft_id}}/attendee-questions/fields/{{field_id}}/options
Authorization: Bearer {{jwt_token}}
Content-Type: application/json

{"label": "Small"}
```
Repeat for: Medium, Large, X-Large

### Step 7: Publish Event
```
POST {{base_url}}/e-events/drafts/{{draft_id}}/publish
Authorization: Bearer {{jwt_token}}
```

### Step 8: (As Attendee) Get Questionnaire
```
GET {{base_url}}/e-events/{{event_id}}/attendee-questions
Authorization: Bearer {{attendee_token}}
```

### Step 9: (As Attendee) Save Page 1
```
PATCH {{base_url}}/e-events/{{event_id}}/attendee-questions/responses/pages/1
Authorization: Bearer {{attendee_token}}
Content-Type: application/json

{
  "answers": {
    "{{text_field_id}}": {
      "fieldId": "{{text_field_id}}",
      "value": "John Doe"
    },
    "{{dropdown_field_id}}": {
      "fieldId": "{{dropdown_field_id}}",
      "value": "Large"
    }
  }
}
```

### Step 10: (As Attendee) Submit
```
POST {{base_url}}/e-events/{{event_id}}/attendee-questions/responses/submit
Authorization: Bearer {{attendee_token}}
```

### Step 11: (As Organizer) View Analytics
```
GET {{base_url}}/e-events/{{event_id}}/attendee-questions/analytics/summary
Authorization: Bearer {{jwt_token}}
```

### Step 12: (As Organizer) Export CSV
```
GET {{base_url}}/e-events/{{event_id}}/attendee-questions/analytics/export/csv
Authorization: Bearer {{jwt_token}}
```

---

This guide covers the complete Attendee Questions API. Ready to implement and test!