Files
cms.techvanguard.vn/models/submission.js
T
Tống Thành Đạt f6f2e0e03b feat(admin): implement unified submission and newsletter management
Introduce a centralized system to manage all website form submissions and newsletter subscriptions.
- Add `Submission` and `NewsletterSubscription` models with MongoDB schema validation
- Implement `submissionController` and `newsletterSubscriptionController` for CRUD operations and filtering
- Create a unified admin UI for reviewing submissions across different sources (home, request, contact, partnership, newsletter)
- Add database migration scripts for creating collections and indexes
- Refactor partnership inquiry forms to use a fixed field structure
- Update admin navigation and server CORS settings to support PATCH requests
2026-04-24 17:11:23 +07:00

86 lines
1.8 KiB
JavaScript

const mongoose = require("mongoose");
const SOURCES = ["home", "request", "contact", "partnership"];
const STATUSES = ["new", "contacted", "info_provided", "closed"];
const emailPattern = /^\S+@\S+\.\S+$/;
const phonePattern = /^[+()\d\s.-]{7,20}$/;
const submissionSchema = new mongoose.Schema(
{
source: {
type: String,
enum: SOURCES,
required: [true, "Source is required"],
},
pageUrl: {
type: String,
trim: true,
default: "",
},
name: {
type: String,
required: [true, "Name is required"],
trim: true,
maxlength: [160, "Name cannot exceed 160 characters"],
},
email: {
type: String,
default: "",
trim: true,
lowercase: true,
validate: {
validator(value) {
return !value || emailPattern.test(value);
},
message: "Please enter a valid email",
},
},
phone: {
type: String,
trim: true,
default: "",
validate: {
validator(value) {
return !value || phonePattern.test(value);
},
message: "Please enter a valid phone number",
},
},
payload: {
type: mongoose.Schema.Types.Mixed,
default: {},
},
status: {
type: String,
enum: STATUSES,
default: "new",
},
internalNote: {
type: String,
trim: true,
default: "",
maxlength: [2000, "Internal note cannot exceed 2000 characters"],
},
ipAddress: {
type: String,
default: "",
},
userAgent: {
type: String,
default: "",
},
},
{
collection: "submissions",
timestamps: true,
autoCreate: false,
autoIndex: false,
},
);
submissionSchema.statics.SOURCES = SOURCES;
submissionSchema.statics.STATUSES = STATUSES;
module.exports = mongoose.model("Submission", submissionSchema);