Spaces:
Paused
Paused
File size: 6,529 Bytes
c904036 a27cebe c904036 37b442c ccd71b8 37b442c c904036 ca0cd67 c904036 89a74d9 c904036 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | const mongoose = require('mongoose');
/**
* Event Schema for CampVerse
* Includes support for logo/banner images, co-hosts, and co-host requests
*/
// Event schema for CampVerse. Participants are tracked via EventParticipationLog only.
const eventSchema = new mongoose.Schema({
audienceType: { type: String, enum: ['institution', 'public'], default: 'public' },
requirements: [String],
socialLinks: {
website: { type: String },
linkedin: { type: String }
},
coHosts: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }],
coHostRequests: [
{
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
status: {
type: String,
enum: ['pending', 'approved', 'rejected'],
default: 'pending',
},
requestedBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
requestedAt: { type: Date },
approvedBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
approvedAt: { type: Date },
remarks: { type: String },
token: { type: String },
},
],
hostUserId: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
institutionId: { type: mongoose.Schema.Types.ObjectId, ref: 'Institution' },
verificationStatus: {
type: String,
enum: ['pending', 'approved', 'rejected'],
default: 'pending',
},
rejectedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
rejectedAt: {
type: Date,
},
rejectionReason: {
type: String,
},
verifiedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
verifiedAt: {
type: Date,
},
features: {
certificateEnabled: { type: Boolean, default: false },
chatEnabled: { type: Boolean, default: false },
},
certificateSettings: {
// Template selection
selectedTemplateId: { type: String },
certificateType: { type: String, enum: ['participation', 'achievement'], default: 'participation' },
// Content
awardText: { type: String },
// Signatories
leftSignatory: {
name: { type: String },
title: { type: String },
},
rightSignatory: {
name: { type: String },
title: { type: String },
},
// Uploaded assets (cloud storage URLs)
uploadedAssets: {
organizationLogo: { type: String }, // Cloud storage URL
leftSignature: { type: String }, // Cloud storage URL
rightSignature: { type: String }, // Cloud storage URL
},
// Verification status (similar to event verification)
verificationStatus: {
type: String,
enum: ['not_configured', 'pending', 'approved', 'rejected'],
default: 'not_configured',
},
submittedAt: { type: Date },
submittedBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
verifiedBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
verifiedAt: { type: Date },
rejectionReason: { type: String },
specificIssues: [String],
requestedChanges: [String],
changesRequestedBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
changesRequestedAt: { type: Date },
// Generation status
generationStatus: {
type: String,
enum: ['not_generated', 'in_progress', 'completed', 'failed'],
default: 'not_generated',
},
generatedAt: { type: Date },
totalGenerated: { type: Number, default: 0 },
// Preview configuration (client-side editor state)
previewConfig: {
previewName: { type: String },
previewRole: { type: String },
accentColor: { type: String },
assetPositions: {
orgLogo: {
x: { type: Number },
y: { type: Number },
},
campverseLogo: {
x: { type: Number },
y: { type: Number },
},
leftSignature: {
x: { type: Number },
y: { type: Number },
},
rightSignature: {
x: { type: Number },
y: { type: Number },
},
},
layers: [
{
id: { type: String },
name: { type: String },
type: { type: String, default: 'text' },
text: { type: String },
x: { type: Number },
y: { type: Number },
fontSize: { type: Number },
fontWeight: { type: Number },
color: { type: String },
align: { type: String, enum: ['left', 'center', 'right'], default: 'left' },
},
],
},
},
title: { type: String, required: true },
description: { type: String, required: true },
tags: [String],
status: { type: String, enum: ['upcoming', 'ongoing', 'completed'], default: 'upcoming' },
type: { type: String },
date: { type: Date, required: true },
organizationName: { type: String },
logoURL: { type: String },
bannerURL: { type: String }, // Made optional - not all events may have a banner
location: {
type: { type: String, enum: ['online', 'offline', 'hybrid'], required: true },
venue: { type: String }, // For offline and hybrid
link: { type: String }, // For online and hybrid
},
// participants and participantCount removed; use EventParticipationLog for tracking
capacity: { type: Number },
// Atomic registration counter for capacity enforcement
registeredCount: { type: Number, default: 0 },
waitlist: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }],
sessions: [
{
title: { type: String, required: true },
time: { type: String, required: true },
speaker: { type: String, required: true },
}
],
about: { type: String },
isPaid: { type: Boolean, default: false },
price: { type: Number },
// createdAt and updatedAt handled by timestamps option
});
// Performance indexes for common queries
eventSchema.index({ 'organizer.type': 1 });
eventSchema.index({ createdAt: -1 });
eventSchema.index({ updatedAt: -1 });
eventSchema.index({ date: 1 });
eventSchema.index({ verificationStatus: 1, date: 1 });
eventSchema.index({ hostUserId: 1 });
// Text search index for event search (exclude organizer, use organizer.name)
eventSchema.index({
title: 'text',
about: 'text',
organizationName: 'text',
tags: 'text'
}, {
weights: { title: 10, organizationName: 5, about: 3, tags: 2 },
name: 'event_text_search'
});
// Removed participants index; not needed when using EventParticipationLog
// Update timestamp on save
// Export with timestamps enabled
module.exports = mongoose.model('Event', new mongoose.Schema(eventSchema.obj, { timestamps: true }));
|