Add onboarding email campaign system with post-verification welcome email
Implements automated onboarding emails to encourage user engagement: - Post-verification welcome email with 5 tips (sent after email verification) - "No Residence" email (2+ days after registration with no property) - "No Tasks" email (5+ days after first residence with no tasks) Key features: - Each onboarding email type sent only once per user (enforced by unique constraint) - Email open tracking via tracking pixel endpoint - Daily scheduled job at 10:00 AM UTC to process eligible users - Admin panel UI for viewing sent emails, stats, and manual sending - Admin can send any email type to users from the user detail Testing section New files: - internal/models/onboarding_email.go - Database model with tracking - internal/services/onboarding_email_service.go - Business logic and eligibility queries - internal/handlers/tracking_handler.go - Email open tracking endpoint - internal/admin/handlers/onboarding_handler.go - Admin API endpoints - admin/src/app/(dashboard)/onboarding-emails/ - Admin UI pages 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -68,6 +68,13 @@ func SetupRouter(deps *Dependencies) *gin.Engine {
|
||||
// Health check endpoint (no auth required)
|
||||
r.GET("/api/health/", healthCheck)
|
||||
|
||||
// Initialize onboarding email service for tracking handler
|
||||
onboardingService := services.NewOnboardingEmailService(deps.DB, deps.EmailService, cfg.Server.BaseURL)
|
||||
|
||||
// Email tracking endpoint (no auth required - used by email tracking pixels)
|
||||
trackingHandler := handlers.NewTrackingHandler(onboardingService)
|
||||
r.GET("/api/track/open/:trackingID", trackingHandler.TrackEmailOpen)
|
||||
|
||||
// NOTE: Public static file serving removed for security.
|
||||
// All uploaded media is now served through authenticated proxy endpoints:
|
||||
// - GET /api/media/document/:id
|
||||
@@ -132,8 +139,9 @@ func SetupRouter(deps *Dependencies) *gin.Engine {
|
||||
|
||||
// Set up admin routes (separate auth system)
|
||||
adminDeps := &admin.Dependencies{
|
||||
EmailService: deps.EmailService,
|
||||
PushClient: deps.PushClient,
|
||||
EmailService: deps.EmailService,
|
||||
PushClient: deps.PushClient,
|
||||
OnboardingService: onboardingService,
|
||||
}
|
||||
admin.SetupRoutes(r, deps.DB, cfg, adminDeps)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user