feat: implement notification system with Mailgun email integration

- Add notifications table with migration
- Create NotificationService with area-of-interest matching
- Integrate Mailgun for email delivery
- Add notification API endpoints (get, mark as read, unread count)
- Create scheduled jobs for event reminders and cleanup
- Build NotificationBell component for frontend
- Add notification triggers for reports and events
- Implement comprehensive test script
- Update Header with notification bell
- Add email templates with HTML formatting

Requirements satisfied:
- 10.1: Users can define areas of interest (1-50km radius)
- 10.2: Notifications sent within 10 minutes
- 10.3: Notifications for new reports/events in user area
- 10.4: Configurable notification preferences (email/in-app)

Task 33 completed
This commit is contained in:
2025-11-17 00:31:23 +00:00
parent 052ba46bdc
commit d61c21c54d
21 changed files with 1716 additions and 3 deletions

View File

@@ -27,6 +27,7 @@ model User {
reports Report[]
cleanedReports Report[] @relation("CleanedByUser")
verifications Verification[]
notifications Notification[]
@@index([clerkId], map: "idx_clerk_id")
@@index([email], map: "idx_email")
@@ -198,3 +199,39 @@ enum reports_verification_status {
verified
disputed
}
model Notification {
id String @id @default(dbgenerated("(uuid())")) @db.VarChar(36)
userId String @map("user_id") @db.VarChar(36)
type notifications_type
title String @db.VarChar(255)
message String @db.Text
relatedId String? @map("related_id") @db.VarChar(36)
relatedType notifications_related_type? @map("related_type")
latitude Decimal? @db.Decimal(10, 8)
longitude Decimal? @db.Decimal(11, 8)
read Boolean @default(false)
emailSent Boolean @default(false) @map("email_sent")
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamp(0)
user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "notifications_ibfk_1")
@@index([userId], map: "idx_user_id")
@@index([createdAt], map: "idx_created_at")
@@index([read], map: "idx_read")
@@index([type], map: "idx_type")
@@index([latitude, longitude], map: "idx_lat_lng")
@@map("notifications")
}
enum notifications_type {
new_report
new_event
event_reminder
report_verified
report_disputed
}
enum notifications_related_type {
report
event
}