> ## Documentation Index
> Fetch the complete documentation index at: https://docs.azalt.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Form

> The container that defines structure, behavior, and deployment for data collection

Forms define what data is collected, how it is validated and shown, and where it is deployed. A form contains elements (fields), settings, and metadata, and is deployed to sites and years to collect submissions.

## Form Architecture

Forms consist of five closely related parts:

* **Form**: Container with metadata and settings (including workflow overrides)
* **FormElement**: Individual fields and UI components within the form
* **FormSite**: Deployment link connecting a form to a specific site and year
* **FormSubmission**: Submission container for a form at a site/year
* **FormElementSubmission**: Individual field values inside a submission

## Form Settings

Every form stores behavioral controls inside a `settings` object that is validated by `updateForm`. Fields are optional—if you omit one, the form falls back to the organization default or the existing persisted value.

### Public submission options

* `allowPublicSubmissionEdits`: When `true`, public contributors can reopen an existing submission (or draft) and change their answers without staff intervention. When omitted, the platform’s default editing policy is applied.
* `allowPublicSubmissionSupportingDocuments`: Enables the supporting-document drawer for unauthenticated contributors so they can upload evidence while filling out public forms. Leaving it undefined preserves the default document policy.
* `publicSupportingDocumentsMode`: Controls how broadly attachments are allowed once `allowPublicSubmissionSupportingDocuments` is turned on. Accepted values:
  * `all` (default): Every element that supports attachments exposes the public drawer.
  * `opt-in`: Only elements with metadata `allowSupportingDocumentsUpload: true` will expose the drawer. Admins toggle this per element in the builder next to the **Required** switch.

All three fields are optional. If you omit a key the existing value is preserved.

### Workflow override

`workflowOverride` is an optional object with a single `type` key. Accepted values are `DIRECT_APPROVAL` and `REQUIRE_APPROVAL`, matching the workflow states described below. Supplying `null` or omitting the object makes the form inherit the organization-level workflow rules.

### Scheduling and reminders

Use `defaultSchedules` to configure due dates and reminder behavior for data entry and approval phases across different period types.

#### Form-level default schedules

The `defaultSchedules` object is keyed by period type (`MONTHLY`, `QUARTERLY`, `YEARLY`) and contains schedules for each workflow phase:

* `dataEntry`: Controls contributor deadlines
* `approval`: Controls reviewer deadlines

Each schedule contains:

* `dueDate`: A flexible due date specification (see types below)
* `reminders`: Optional reminder configuration block:
  * `enabled`: Boolean to enable/disable reminders
  * `offsets`: Array of `{ type: "days-before"; days: number }` objects specifying how many days before the due date to send reminders. The `days` value must be between 1-30. Required when `enabled` is `true`; ignored when `enabled` is `false`.

#### Due date specification types

The `dueDate` field supports six flexible formats:

| Type                 | Description                                               | Example                                                                      |
| -------------------- | --------------------------------------------------------- | ---------------------------------------------------------------------------- |
| `fixed-day`          | Specific day of the period (1-31, capped to month length) | `{ type: "fixed-day", day: 15 }`                                             |
| `weekday-occurrence` | Nth weekday of the period (weekday: 0=Sun to 6=Sat)       | `{ type: "weekday-occurrence", weekday: 1, occurrence: 2 }` (2nd Monday)     |
| `last-weekday`       | Last occurrence of a weekday in the period                | `{ type: "last-weekday", weekday: 5 }` (last Friday)                         |
| `relative-days`      | N days after period end (0-60)                            | `{ type: "relative-days", daysAfterPeriodEnd: 15 }`                          |
| `relative-weekday`   | Nth weekday after period end                              | `{ type: "relative-weekday", weekday: 5, occurrence: 1 }` (1st Friday after) |
| `specific-date`      | Fixed calendar date (YEARLY only)                         | `{ type: "specific-date", month: 4, day: 15 }` (April 15)                    |

**Notes**:

* `specific-date` can only be used with YEARLY periods. The `month` value is 1-12 (1 = January). Days that exceed the month length (e.g., day 31 in February) are automatically capped to the last valid day.
* `relative-days` supports `daysAfterPeriodEnd` values from 0-60 (0 = on period end date).
* Due date and reminder calculations use UTC for consistency.

#### Element-level schedule overrides

Individual form elements can override form-level defaults by storing a schedule in the `FormElement.schedule` column. Overrides are applied per-phase: the element's schedule can specify `dataEntry` and/or `approval` independently. Any phase not present in the element's schedule falls back to the form-level default schedule for that period type. This enables elements to override only one phase (e.g., a custom approval deadline) while inheriting the form's default for the other (e.g., dataEntry).

```ts theme={null}
// Example payload supplied to updateForm
{
  settings: {
    allowPublicSubmissionSupportingDocuments: true,
    workflowOverride: { type: "REQUIRE_APPROVAL" },
    defaultSchedules: {
      MONTHLY: {
        dataEntry: {
          dueDate: { type: "fixed-day", day: 15 },
          reminders: { enabled: true, offsets: [{ type: "days-before", days: 3 }, { type: "days-before", days: 7 }] }
        },
        approval: {
          dueDate: { type: "last-weekday", weekday: 5 }, // Last Friday
          reminders: { enabled: true, offsets: [{ type: "days-before", days: 1 }] }
        }
      },
      QUARTERLY: {
        dataEntry: {
          dueDate: { type: "relative-days", daysAfterPeriodEnd: 15 }, // 15 days after quarter end
          reminders: { enabled: true, offsets: [{ type: "days-before", days: 7 }] }
        }
        // approval omitted → no approval schedule for quarterly periods
      },
      YEARLY: {
        dataEntry: {
          dueDate: { type: "specific-date", month: 3, day: 31 }, // March 31
          reminders: { enabled: true, offsets: [{ type: "days-before", days: 14 }] }
        }
        // approval omitted → no approval schedule for yearly periods
      }
    }
  }
}
```

## Form Types & Deployment

**Internal forms (private)**

* One submission per FormSite (site + year) is enforced while not deleted
* Team members enter data directly in the platform
* CSV bulk import/export and API integration for automation
* Auto-save UX depending on the view (create/update on change)

**External forms (public)**

* Public endpoints per FormSite (no authentication)
* Multiple submissions per site/year are allowed
* Optional review via per-field approvals (see Workflow)
* Optional branded header via form metadata (logo, colors)

## Smart Form Features

**Conditional logic**: Dynamic behavior based on other elements

```javascript theme={null}
// Example: Show energy source details only if renewable energy is selected
{
  type: "CONDITION",
  field: "energy-type",
  operator: "equals",
  value: "renewable",
  action: "show"
}
```

**Time Period Configuration**: Flexible data collection cycles

* **YEARLY**: One period unit (1)
* **MONTHLY**: 12 period units (1–12)
* **QUARTERLY**: 4 period units (1–4)
* **TIMESTAMP**: Point-in-time entries with a `recordedAt` UTC timestamp (periodUnit derived from recorded month)

**Distribution mode (NUMBER elements)**

* **total**: Values represent totals that roll up over time (e.g., emissions)
* **snapshot**: Point-in-time values that should not be distributed (e.g., factors)

**Units**: Associate measurement units with elements for clear labeling and validation

## Advanced Form Builder

**Visual editor**: Drag-and-drop interface for form construction

* Real-time preview
* Element reordering and nesting
* Copy/paste elements across forms
* Create from CSV or duplicate existing forms

**Create forms via**:

* CSV import (bulk)
* Duplicate & customize
* Manual builder

**Conditional logic builder**: Visual interface for complex branching

* Drag-and-drop condition creation
* Multiple condition types (equals, contains, greater than, etc.)
* Nested condition groups with AND/OR logic
* Real-time validation and preview

## Data Collection Workflow

**1. Form Design**: Build form structure with elements and logic

**2. Deployment**: Assign to specific sites and years

```
Manufacturing Plant A - 2024
Regional Office B - 2024, 2025
Supplier Network - 2024 (External)
```

**3. Data collection**: Multiple input methods

* Direct platform entry
* CSV import with validation
* API integration
* Public form submissions (if enabled)

**4. Validation**: Real-time and batch validation

* Required field enforcement
* Type/format validation
* Conditional logic
* Unit compatibility checks

**5. Export & analysis**: Flexible data extraction

* CSV/XLSX export
* API endpoints
* Dashboard integration
* Summary statistics

## Workflow and Approvals

Forms inherit the organization’s default workflow and can optionally override it per form via settings:

* **DIRECT\_APPROVAL**: New values are saved as APPROVED
* **REQUIRE\_APPROVAL**: New values are saved as COMPLETED and require approval

Status is tracked on each FormElementSubmission (COMPLETED, APPROVED, REJECTED). In `REQUIRE_APPROVAL` mode, the submission interface exposes:

* **Inline approval controls**: Each period row shows Approve, Reject, and Revert buttons with live status badges. Values that are rejected automatically revert to COMPLETED once edited again.
* **Bulk actions**: For monthly or quarterly NUMBER/SINGLE\_CHOICE/MULTIPLE\_CHOICE/LONG\_TEXT/SHORT\_TEXT elements, approvers can approve or reject every populated period in one click. ACTIVITY elements continue to support bulk approvals for all rows within the same period.
* **Status persistence**: Status changes update immediately in the UI (no refresh required) and are reflected in downstream reporting.

When a form is in `DIRECT_APPROVAL`, approval buttons are hidden and newly saved data is marked as APPROVED automatically.

## Supporting Documents

Each element row can open a supporting-document drawer:

* **Private submissions**: Files are attached directly to the underlying FormElementSubmission. Users can upload new evidence, download existing files, and (with permission) delete attachments.
* **Public submissions**: Opening the drawer creates (or reuses) a draft submission so public contributors can upload files without logging in. The drawer lists previously uploaded documents and exposes download links; deletes are limited to authenticated staff.
* **Counters and indicators**: Attachment buttons show a badge with the number of linked files, and upload/delete operations refresh immediately.

These files remain associated with the element, period unit, and (if applicable) timestamp sequence for full auditability.

## Developer Mode

Submission pages expose a **Copy cURL** control when developer mode is enabled. The action copies a ready-to-run `curl` command that mirrors the current element identifier, site, year, period unit, and latest value. Teams use this to bootstrap API integrations quickly or to test REST submissions without manually crafting payloads.

## Task Progress Tracking

While users enter data, the renderer emits optimistic task-progress metrics:

* **Data entry progress**: Counts remaining vs. total period/element combinations up to the current month, highlighting overdue months based on schedule due days.
* **Approval progress**: When approvals are required, approvers see remaining vs. total items awaiting review, plus overdue counts.

Consumers (dashboards, widgets, or custom pages) can subscribe to these callbacks to surface live completion rings, overdue badges, or workflow summaries next to the form.

## Public Form Settings

For public forms, additional settings exist on the form:

* `allowPublicSubmissionEdits`
* `allowPublicSubmissionSupportingDocuments`

## Constraints and Notes

* FormElement keys are unique within a form
* ACTIVITY elements cannot use the TIMESTAMP period
* Private forms enforce one active FormSubmission per FormSite (non-deleted)

## Real-World Examples

**Energy Tracking Form**:

* Monthly electricity consumption (NUMBER with kWh unit)
* Energy source selection (SINGLE\_CHOICE: Grid/Solar/Wind)
* Conditional renewable details (shown only if renewable selected)
* Supporting documentation upload (FILE\_UPLOAD)

**Waste Management Form**:

* Quarterly waste streams (GROUP with multiple NUMBER fields)
* Waste treatment method (MULTIPLE\_CHOICE)
* Diversion rate calculation (ACTIVITY with custom formula)
* Site-specific disposal procedures (LONG\_TEXT)

**Supplier Assessment Form** (External):

* Company information (SHORT\_TEXT fields)
* Scope 1, 2, 3 emissions (NUMBER with tCO2e units)
* Activity-based calculations (ACTIVITY for complex emissions)
* Monthly data collection (MONTHLY period setting)

## Operational Benefits

* **Consistency**: Same form structure across all sites and time periods
* **Efficiency**: Auto-save, bulk operations, and template reuse
* **Compliance**: Built-in validation and audit trails
* **Scalability**: Handle hundreds of sites and thousands of submissions
* **Flexibility**: Adapt forms without losing historical data
