feat: email notifications + deadline reminder system
Database: - notification_preferences table (user_id, tenant_id, reminder days, email/digest toggles) - notifications table (type, entity link, read/sent tracking, dedup index) Backend: - NotificationService with background goroutine checking reminders hourly - CheckDeadlineReminders: finds deadlines due in N days per user prefs, creates notifications - Overdue deadline detection and notification - Daily digest at 8am: compiles pending notifications into one email - SendEmail via `m mail send` CLI command - Deduplication: same notification type + entity + day = skip - API: GET/PATCH notifications, unread count, mark read/all-read - API: GET/PUT notification-preferences with upsert Frontend: - NotificationBell in header with unread count badge (polls every 30s) - Dropdown panel with notification list, type-colored dots, time-ago, entity links - Mark individual/all as read - NotificationSettings in Einstellungen page: reminder day toggles, email toggle, digest toggle
This commit is contained in:
@@ -15,7 +15,7 @@ import (
|
||||
"mgit.msbls.de/m/KanzlAI-mGMT/internal/services"
|
||||
)
|
||||
|
||||
func New(db *sqlx.DB, authMW *auth.Middleware, cfg *config.Config, calDAVSvc *services.CalDAVService) http.Handler {
|
||||
func New(db *sqlx.DB, authMW *auth.Middleware, cfg *config.Config, calDAVSvc *services.CalDAVService, notifSvc *services.NotificationService) http.Handler {
|
||||
mux := http.NewServeMux()
|
||||
|
||||
// Services
|
||||
@@ -43,6 +43,12 @@ func New(db *sqlx.DB, authMW *auth.Middleware, cfg *config.Config, calDAVSvc *se
|
||||
noteSvc := services.NewNoteService(db)
|
||||
dashboardSvc := services.NewDashboardService(db)
|
||||
|
||||
// Notification handler (optional — nil in tests)
|
||||
var notifH *handlers.NotificationHandler
|
||||
if notifSvc != nil {
|
||||
notifH = handlers.NewNotificationHandler(notifSvc, db)
|
||||
}
|
||||
|
||||
// Handlers
|
||||
tenantH := handlers.NewTenantHandler(tenantSvc)
|
||||
caseH := handlers.NewCaseHandler(caseSvc)
|
||||
@@ -137,6 +143,16 @@ func New(db *sqlx.DB, authMW *auth.Middleware, cfg *config.Config, calDAVSvc *se
|
||||
scoped.HandleFunc("POST /api/ai/summarize-case", aiLimiter.LimitFunc(aiH.SummarizeCase))
|
||||
}
|
||||
|
||||
// Notifications
|
||||
if notifH != nil {
|
||||
scoped.HandleFunc("GET /api/notifications", notifH.List)
|
||||
scoped.HandleFunc("GET /api/notifications/unread-count", notifH.UnreadCount)
|
||||
scoped.HandleFunc("PATCH /api/notifications/{id}/read", notifH.MarkRead)
|
||||
scoped.HandleFunc("PATCH /api/notifications/read-all", notifH.MarkAllRead)
|
||||
scoped.HandleFunc("GET /api/notification-preferences", notifH.GetPreferences)
|
||||
scoped.HandleFunc("PUT /api/notification-preferences", notifH.UpdatePreferences)
|
||||
}
|
||||
|
||||
// CalDAV sync endpoints
|
||||
if calDAVSvc != nil {
|
||||
calDAVH := handlers.NewCalDAVHandler(calDAVSvc)
|
||||
|
||||
Reference in New Issue
Block a user