Prashikshak / API /src /model /form.model.ts
Abhisingh-18's picture
Initial commit: Prashikshak - disaster management training platform
9a92a42
Raw
History Blame Contribute Delete
4.25 kB
import { Schema, model, Document, Types } from 'mongoose';
// Field types supported in forms
type FieldType =
| 'short_text'
| 'long_text'
| 'multiple_choice'
| 'checkboxes'
| 'dropdown'
| 'linear_scale'
| 'date'
| 'time'
| 'email'
| 'phone'
| 'number'
| 'file_upload';
interface IFormField {
id: string; // Unique field ID
type: FieldType;
label: string;
description?: string;
required: boolean;
options?: string[]; // For multiple_choice, checkboxes, dropdown
validation?: {
min?: number; // For number, linear_scale
max?: number;
pattern?: string; // For text fields (regex)
maxLength?: number;
minLength?: number;
fileTypes?: string[]; // For file uploads
maxFileSize?: number; // In bytes
};
order: number; // Display order
}
export interface IForm extends Document {
// Basic Info
title: string;
description?: string;
// Association
event?: Types.ObjectId; // If attached to an event
organization: Types.ObjectId; // Template forms belong to organization
createdBy: Types.ObjectId; // Trainer who created it
// Form Structure
fields: IFormField[];
// Access Control
accessType: 'event_attendees' | 'verified_users' | 'public'; // Who can submit
restrictToAttendees: boolean; // Only event participants can submit
oneResponsePerUser: boolean; // Enforce single response
// Sharing
shortCode: string; // Short join code (e.g., FORM-ABC123)
shareToken: string; // Secret token for share links
qrCode?: string; // QR code image URL/data
// Settings
acceptingResponses: boolean;
showResponseSummary: boolean; // Show summary to respondents
allowEditing: boolean; // Allow users to edit their responses
// Metadata
responseCount: number;
status: 'draft' | 'active' | 'closed';
createdAt: Date;
updatedAt: Date;
}
const FormSchema = new Schema<IForm>({
title: {
type: String,
required: true,
trim: true,
index: 'text'
},
description: {
type: String,
trim: true
},
event: {
type: Schema.Types.ObjectId,
ref: 'Event',
index: true
},
organization: {
type: Schema.Types.ObjectId,
ref: 'User',
required: false,
index: true
},
createdBy: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true,
index: true
},
fields: [{
id: {
type: String,
required: true
},
type: {
type: String,
enum: [
'short_text',
'long_text',
'multiple_choice',
'checkboxes',
'dropdown',
'linear_scale',
'date',
'time',
'email',
'phone',
'number',
'file_upload'
],
required: true
},
label: {
type: String,
required: true
},
description: String,
required: {
type: Boolean,
default: false
},
options: [String],
validation: {
min: Number,
max: Number,
pattern: String,
maxLength: Number,
minLength: Number,
fileTypes: [String],
maxFileSize: Number
},
order: {
type: Number,
required: true
}
}],
accessType: {
type: String,
enum: ['event_attendees', 'verified_users', 'public'],
default: 'verified_users'
},
restrictToAttendees: {
type: Boolean,
default: false
},
oneResponsePerUser: {
type: Boolean,
default: true
},
shortCode: {
type: String,
required: true,
unique: true,
uppercase: true,
trim: true,
index: true
},
shareToken: {
type: String,
required: true,
index: true
},
qrCode: String,
acceptingResponses: {
type: Boolean,
default: true
},
showResponseSummary: {
type: Boolean,
default: false
},
allowEditing: {
type: Boolean,
default: false
},
responseCount: {
type: Number,
default: 0
},
status: {
type: String,
enum: ['draft', 'active', 'closed'],
default: 'draft',
index: true
}
}, {
timestamps: true
});
// Indexes
FormSchema.index({ event: 1, status: 1 });
FormSchema.index({ organization: 1, createdBy: 1 });
FormSchema.index({ shortCode: 1, shareToken: 1 });
export default model<IForm>('Form', FormSchema);