From 11c511bde28ebc83e7f5b238d654408439a3cc16 Mon Sep 17 00:00:00 2001 From: Tanuja Pansare Date: Wed, 8 Jul 2026 10:23:59 +0530 Subject: [PATCH] Update WebCheck-in --- src/config/constants.js | 2 +- src/controllers/participant.controller.js | 2 +- src/models/Event.js | 1 + src/models/Form.js | 2 +- src/models/Participant.js | 1 + src/routes/event.routes.js | 25 ++++++++++++++++------- src/routes/participant.routes.js | 2 ++ 7 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/config/constants.js b/src/config/constants.js index cb727b0..3e2c2b8 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -4,7 +4,7 @@ const EVENT_STATUS = ['draft', 'upcoming', 'live', 'completed']; const PARTICIPANT_STATUS = ['pending', 'confirmed', 'checked_in', 'cancelled']; const SESSION_TYPES = ['keynote', 'workshop', 'panel', 'breakout', 'networking']; const SESSION_STATUS = ['scheduled', 'ongoing', 'completed', 'cancelled']; -const FORM_TYPES = ['registration', 'feedback', 'survey', 'custom', 'other']; +const FORM_TYPES = ['registration', 'feedback', 'survey', 'custom', 'other', 'web-check-in']; const FIELD_TYPES = ['text', 'textarea', 'email', 'phone', 'select', 'stars', 'radio', 'checkbox', 'checkboxes', 'file']; /** Registration field → Participant property mapping (or `custom` + customMapsKey). */ const FORM_FIELD_MAPS_TO = [ diff --git a/src/controllers/participant.controller.js b/src/controllers/participant.controller.js index 0eba7fc..a6d08c3 100644 --- a/src/controllers/participant.controller.js +++ b/src/controllers/participant.controller.js @@ -671,7 +671,7 @@ const update = async (request, h) => { const tags = payload.tags; delete payload.tags; - const assignable = ['email', 'firstName', 'lastName', 'phone', 'organization', 'designation', 'notes']; + const assignable = ['email', 'firstName', 'lastName', 'phone', 'organization', 'designation', 'accommodation', 'notes']; for (const key of assignable) { if (Object.prototype.hasOwnProperty.call(payload, key) && payload[key] !== undefined) { participant[key] = payload[key]; diff --git a/src/models/Event.js b/src/models/Event.js index d05a692..20a3f17 100644 --- a/src/models/Event.js +++ b/src/models/Event.js @@ -56,6 +56,7 @@ const eventSchema = new mongoose.Schema( registrationDeadline: Date, enableFeedback: { type: Boolean, default: true }, enableRatings: { type: Boolean, default: false }, + webCheckInEnabled: { type: Boolean, default: false }, /** otp_email | link_email | none */ authenticationType: String, /** name_email | email_only | name_email_phone | anonymous_name | anonymous */ diff --git a/src/models/Form.js b/src/models/Form.js index b6df9f4..816c6de 100644 --- a/src/models/Form.js +++ b/src/models/Form.js @@ -31,7 +31,7 @@ const formSchema = new mongoose.Schema( description: { type: String, default: '' }, type: { type: String, - enum: ['registration', 'feedback', 'survey', 'custom', 'other'], + enum: ['registration', 'feedback', 'survey', 'custom', 'other', 'web-check-in'], required: true, }, fields: [formFieldSchema], diff --git a/src/models/Participant.js b/src/models/Participant.js index 01d8ddb..258a752 100644 --- a/src/models/Participant.js +++ b/src/models/Participant.js @@ -38,6 +38,7 @@ const participantSchema = new mongoose.Schema( /** Employer / company (string). Not the tenant org id. */ organization: String, designation: String, + accommodation: { type: Boolean, default: false }, customFields: { type: Map, of: mongoose.Schema.Types.Mixed }, payment: { amount: Number, diff --git a/src/routes/event.routes.js b/src/routes/event.routes.js index 7bf741b..1a54a82 100644 --- a/src/routes/event.routes.js +++ b/src/routes/event.routes.js @@ -35,11 +35,11 @@ const rewardRulesPayload = Joi.object({ ratingSubmitted: Joi.number().min(0).allow(null), }).allow(null); -const eventPayload = Joi.object({ - name: Joi.string().min(3).max(100).required(), +const baseEventPayload = { + name: Joi.string().min(3).max(100), subtitle: Joi.string().allow('', null), description: Joi.string().allow('', null), - type: Joi.string().valid(...EVENT_TYPES).required(), + type: Joi.string().valid(...EVENT_TYPES), recordKind: Joi.string().valid('event', 'activity'), activitySubtype: Joi.when('recordKind', { is: 'activity', @@ -48,8 +48,8 @@ const eventPayload = Joi.object({ }), status: Joi.string().valid(...EVENT_STATUS), category: Joi.string().allow('', null), - startDate: Joi.date().iso().required(), - endDate: Joi.date().iso().required(), + startDate: Joi.date().iso(), + endDate: Joi.date().iso(), location: Joi.string().allow('', null), locationType: Joi.string().valid('physical', 'virtual', 'hybrid'), virtualLink: Joi.string().allow('', null), @@ -66,6 +66,7 @@ const eventPayload = Joi.object({ registrationDeadline: Joi.date().iso().allow(null), enableFeedback: Joi.boolean(), enableRatings: Joi.boolean(), + webCheckInEnabled: Joi.boolean(), authenticationType: Joi.string().valid(...AUTHENTICATION_TYPES).allow('', null), registrationBaseFields: Joi.string().valid(...REGISTRATION_BASE_FIELDS).allow('', null), inviteCode: Joi.string().allow('', null), @@ -80,7 +81,17 @@ const eventPayload = Joi.object({ rewardRules: rewardRulesPayload, /** When true on POST /events (non-activity), server creates default track + opening session (AI-style). */ bootstrapAgenda: Joi.boolean().default(false), -}); +}; + +const eventPayload = Joi.object({ + ...baseEventPayload, + name: baseEventPayload.name.required(), + type: baseEventPayload.type.required(), + startDate: baseEventPayload.startDate.required(), + endDate: baseEventPayload.endDate.required(), +}).options({ allowUnknown: true }); + +const eventUpdatePayload = Joi.object(baseEventPayload).min(1).options({ allowUnknown: true }); const generateFromAiPayload = Joi.object({ description: Joi.string().min(10).max(8000).required(), @@ -118,7 +129,7 @@ module.exports = [ }, { method: 'POST', path: '/api/events', options: { validate: { payload: eventPayload }, handler: controller.create } }, { method: 'GET', path: '/api/events/{id}', options: { handler: controller.get } }, - { method: 'PUT', path: '/api/events/{id}', options: { validate: { payload: eventPayload }, handler: controller.update } }, + { method: 'PUT', path: '/api/events/{id}', options: { validate: { payload: eventUpdatePayload }, handler: controller.update } }, { method: 'DELETE', path: '/api/events/{id}', options: { handler: controller.remove } }, { method: 'GET', path: '/api/events/{id}/analytics', options: { handler: controller.analytics } }, { diff --git a/src/routes/participant.routes.js b/src/routes/participant.routes.js index 01785e7..738c221 100644 --- a/src/routes/participant.routes.js +++ b/src/routes/participant.routes.js @@ -8,6 +8,7 @@ const participantPayload = Joi.object({ phone: Joi.string(), organization: Joi.string(), designation: Joi.string(), + accommodation: Joi.boolean(), tags: Joi.array().items(Joi.string()), notes: Joi.string(), }); @@ -19,6 +20,7 @@ const participantUpdatePayload = Joi.object({ phone: Joi.string().allow('', null), organization: Joi.string().allow('', null), designation: Joi.string().allow('', null), + accommodation: Joi.boolean(), tags: Joi.array().items(Joi.string()), notes: Joi.string().allow('', null), }).min(1);