feat(contact): add contact form with admin panel and navbar dropdown
Database changes: - Added ContactMessage model to Prisma schema - Fields: userId, username, firstName, lastName, email, subject, message, status, ipAddress - Status enum: new, read, resolved - Relation to User model Backend changes: - Added POST /api/public/contact endpoint for form submissions - Works for both authenticated and non-authenticated users - Validation for email, subject (3-255 chars), message (10-5000 chars) - Activity logging for submissions - Added admin endpoints: - GET /api/admin/contact-messages - list with filtering by status - GET /api/admin/contact-messages/:id - view single message (auto-marks as read) - PATCH /api/admin/contact-messages/:id/status - update status - DELETE /api/admin/contact-messages/:id - delete message Frontend changes: - Created ContactPage at /contact route - For non-logged-in users: firstName, lastName, email, subject, message fields - For logged-in users: auto-fills username, shows only email, subject, message - Character counter for message (max 5000) - Success screen with auto-redirect to homepage - Created ContactMessagesPage at /admin/contact-messages - Two-column layout: message list + detail view - Filter by status (all, new, read, resolved) - View message details with sender info and IP address - Update status and delete messages - Added admin dropdown menu to Navbar - Desktop: dropdown with Activity Logs and Contact Messages - Mobile: expandable submenu - Click outside to close on desktop - ChevronDown icon rotates when open Note: CAPTCHA integration planned for future enhancement
This commit is contained in:
@@ -77,6 +77,7 @@ model User {
|
||||
heats EventUserHeat[]
|
||||
recordingAssignments RecordingSuggestion[] @relation("RecorderAssignments")
|
||||
activityLogs ActivityLog[]
|
||||
contactMessages ContactMessage[]
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
@@ -365,3 +366,37 @@ model ActivityLog {
|
||||
|
||||
@@map("activity_logs")
|
||||
}
|
||||
|
||||
// Contact messages from users
|
||||
model ContactMessage {
|
||||
id Int @id @default(autoincrement())
|
||||
|
||||
// User identification (either logged in or anonymous)
|
||||
userId Int? @map("user_id") // NULL for non-logged-in users
|
||||
username String? @db.VarChar(50) // Username if logged in
|
||||
firstName String? @map("first_name") @db.VarChar(100) // For non-logged-in users
|
||||
lastName String? @map("last_name") @db.VarChar(100) // For non-logged-in users
|
||||
email String @db.VarChar(255) // Always required
|
||||
|
||||
// Message content
|
||||
subject String @db.VarChar(255)
|
||||
message String @db.Text
|
||||
|
||||
// Admin tracking
|
||||
status String @default("new") @db.VarChar(20) // 'new', 'read', 'resolved'
|
||||
ipAddress String? @map("ip_address") @db.VarChar(45)
|
||||
|
||||
// Timestamps
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
// Relations
|
||||
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
|
||||
|
||||
// Indexes
|
||||
@@index([status, createdAt(sort: Desc)])
|
||||
@@index([createdAt(sort: Desc)])
|
||||
@@index([userId])
|
||||
|
||||
@@map("contact_messages")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user