Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 24 additions & 33 deletions bruno/form-fields/createFields.bru
Original file line number Diff line number Diff line change
Expand Up @@ -35,30 +35,30 @@ settings {
docs {
# Create Field

Adds a new field to a form. This endpoint handles the **linked-list ordering** logic automatically. You can insert a field at the very beginning (Head) or after a specific existing field.
Adds a new field to a form. This endpoint handles the linked-list ordering logic automatically. You can insert a field at the very beginning (Head) or after a specific existing field.

* **URL:** `/forms/:formId/fields`
* **Method:** `POST`
* **Auth Required:** Yes
- **URL:** `/forms/:formId/fields`
- **Method:** `POST`
- **Auth Required:** Yes

### Path Parameters
## Path Parameters

| Parameter | Type | Description |
| :--- | :--- | :--- |
|---|---|---|
| `formId` | `string` (UUID) | The ID of the form to add the field to. |

### Request Body
## Request Body

| Field | Type | Required | Description |
| :--- | :--- | :--- | :--- |
|---|---|---|---|
| `fieldName` | `string` | Yes | Internal unique name for the field (e.g., "user_email"). |
| `label` | `string` | Yes | The question text shown to users. |
| `fieldValueType` | `string` | Yes | Data type (e.g., "string", "number", "boolean"). |
| `fieldType` | `string` | Yes | UI Component type (e.g., "text", "select", "radio"). |
| `prevFieldId` | `string` | No | The ID of the field *after which* this new field should be inserted. Send `null` or omit to insert at the top (as the first question). |
| `fieldType` | `string` | Yes | UI component type (e.g., "text", "select", "radio"). |
| `prevFieldId` | `string \| null` | No | ID of the field after which the new field should be inserted. Omit or send `null` to insert at the beginning. |
| `validation` | `object` | No | JSON object for validation rules (e.g., `{ "required": true }`). |

**Sample Input (Insert at Top/Head):**
## Sample Input (Insert at Top)

```json
{
Expand All @@ -71,24 +71,25 @@ docs {
"required": true
}
}
```

Sample Input (Insert after an existing field):
JSON
## Sample Input (Insert After Another Field)

```json
{
"fieldName": "age",
"label": "How old are you?",
"fieldValueType": "number",
"fieldType": "number",
"prevFieldId": "uuid-of-previous-field-123"
}
```

Responses
✅ 200 OK: Created
## Responses

Returns the newly created field object.
JSON
### 200 OK — Created

```json
{
"success": true,
"message": "Field created successfully",
Expand All @@ -102,28 +103,18 @@ docs {
"required": true
},
"formId": "form_xyz_789",
"prevFieldId": null,
"createdAt": "2023-10-27T10:00:00.000Z"
"prevFieldId": null
}
}
```

❌ 400 Bad Request: Invalid Position

Occurs if prevFieldId is provided but that field does not exist in this form (meaning you are trying to insert after a field that doesn't exist).
JSON

{
"success": false,
"message": "Previous field not found in the specified form"
}

❌ 404 Not Found: Form Missing

Occurs if the form does not exist or the user does not have permission to edit it.
JSON
### 404 Not Found — Form Missing

```json
{
"success": false,
"message": "Form not found"
}
```

}
2 changes: 1 addition & 1 deletion bruno/forms/publishForm.bru
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ docs {

Changes the status of a form to **Published**. Once published, the form becomes accessible to respondents for submission.

* **URL:** `/forms/:formId/publish`
* **URL:** `/forms/publish/:formId`
* **Method:** `PATCH`
* **Auth Required:** Yes

Expand Down
4 changes: 2 additions & 2 deletions bruno/forms/unPublishForm.bru
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ meta {
}

post {
url: http://localhost:8000/forms/publish/:formId
url: http://localhost:8000/forms/unpublish/:formId
body: none
auth: inherit
}
Expand All @@ -24,7 +24,7 @@ docs {

Reverts the status of a form to **Unpublished**. This hides the form from the public, preventing any new submissions until it is published again.

* **URL:** `/forms/:formId/unpublish`
* **URL:** `/forms/unpublish/:formId`
* **Method:** `PATCH`
* **Auth Required:** Yes

Expand Down
102 changes: 39 additions & 63 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init

generator client {
provider = "prisma-client-js"
}
Expand All @@ -13,18 +7,17 @@ datasource db {
}

model User {
id String @id @default(uuid())
email String @unique
id String @id @default(uuid())
email String @unique
name String?
emailVerified Boolean @default(false)
emailVerified Boolean @default(false)
image String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

sessions Session[]
accounts Account[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
forms Form[]
accounts Account[]
formResponses FormResponse[]
sessions Session[]

@@map("user")
}
Expand All @@ -38,8 +31,7 @@ model Session {
userAgent String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

user User @relation(fields: [userId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)

@@map("session")
}
Expand All @@ -51,25 +43,22 @@ model Account {
providerId String
accessToken String?
refreshToken String?
idToken String?
scope String?
accessTokenExpiresAt DateTime?
expiresAt DateTime?
password String?

createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

user User @relation(fields: [userId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
accessTokenExpiresAt DateTime?
idToken String?
scope String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)

@@map("account")
}

// You will need this table for "Forgot Password" or "Verify Email" flows
model Verification {
id String @id @default(uuid())
identifier String
value String // The token itself
value String
expiresAt DateTime
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
Expand All @@ -78,60 +67,47 @@ model Verification {
}

model Form {
id String @id @default(uuid())
title String
description String?
isPublished Boolean @default(false)
formUrl String?

ownerId String
owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade)

id String @id @default(uuid())
title String
description String?
isPublished Boolean @default(false)
formUrl String?
ownerId String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade)
formFields FormFields[]
formResponses FormResponse[]
}

model FormFields {
id String @id @default(uuid())
id String @id @default(uuid())
fieldName String
label String?
fieldValueType String // e.g., "string", "number", "boolean"
fieldType String // e.g., "MCQ", "Radio", "Input"
validation Json? // e.g., { "required": true, "min": 5 }

createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

// 1. Link to the parent Form
formId String
form Form @relation(fields: [formId], references: [id], onDelete: Cascade)

// 2. Doubly Linked List Logic (Self-Relations)

// The "Previous" Field (Parent)
// This field stores the ID of the field passing control to this one
prevFieldId String?
fieldValueType String
fieldType String
validation Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
formId String
prevFieldId String?
form Form @relation(fields: [formId], references: [id], onDelete: Cascade)

@@index([formId])
@@index([formId, prevFieldId])
@@map("form_fields")
}

model FormResponse {
id String @id @default(uuid())

formId String
form Form @relation(fields: [formId], references: [id], onDelete: Cascade)

id String @id @default(uuid())
formId String
respondentId String?
respondent User? @relation(fields: [respondentId], references: [id], onDelete: SetNull)

answers Json
isSubmitted Boolean @default(false)
submittedAt DateTime?
updatedAt DateTime @updatedAt
answers Json
submittedAt DateTime?
updatedAt DateTime @updatedAt
isSubmitted Boolean @default(false)
form Form @relation(fields: [formId], references: [id], onDelete: Cascade)
respondent User? @relation(fields: [respondentId], references: [id])

@@unique([formId, respondentId])
@@index([formId])
Expand Down
Loading