diff --git a/apps/api/src/services/ActivityService.ts b/apps/api/src/services/ActivityService.ts index 2e5ed4d..0d88508 100644 --- a/apps/api/src/services/ActivityService.ts +++ b/apps/api/src/services/ActivityService.ts @@ -480,6 +480,21 @@ export class ActivityService { }, }); } + + // Email complaint + if (email.complainedAt && (!types || types.includes(ActivityType.EMAIL_COMPLAINT))) { + activities.push({ + id: `${email.id}_complaint`, + type: ActivityType.EMAIL_COMPLAINT, + timestamp: email.complainedAt, + contactEmail: email.contact.email, + contactId: email.contactId, + metadata: { + ...baseMetadata, + error: email.error, + }, + }); + } } return activities; diff --git a/apps/web/src/components/ActivityItem.tsx b/apps/web/src/components/ActivityItem.tsx index 0152c72..386d34d 100644 --- a/apps/web/src/components/ActivityItem.tsx +++ b/apps/web/src/components/ActivityItem.tsx @@ -11,6 +11,7 @@ import { Eye, MousePointerClick, Send, + ShieldAlert, Workflow, XCircle, Zap, @@ -95,7 +96,14 @@ function getUpcomingTime(date: Date): string { * Check if an activity is an email activity */ function isEmailActivity(type: string): boolean { - return ['email.sent', 'email.delivered', 'email.opened', 'email.clicked', 'email.bounced'].includes(type); + return [ + 'email.sent', + 'email.delivered', + 'email.opened', + 'email.clicked', + 'email.bounced', + 'email.complaint', + ].includes(type); } interface ActivityItemProps { @@ -226,6 +234,23 @@ function getActivityConfig(activity: Activity): ActivityConfig { }, }; + case 'email.complaint': + return { + icon: ShieldAlert, + color: 'text-red-600', + bgColor: 'bg-red-100', + title: (typeof metadata.subject === 'string' ? metadata.subject : undefined) || 'Spam complaint', + description: metadata.campaignName + ? `Campaign: ${String(metadata.campaignName)}` + : metadata.workflowName + ? `Workflow: ${String(metadata.workflowName)}` + : 'Recipient marked as spam', + badge: { + label: 'Complaint', + variant: 'destructive', + }, + }; + case 'workflow.started': return { icon: Workflow, diff --git a/apps/web/src/pages/activity/index.tsx b/apps/web/src/pages/activity/index.tsx index ef41795..ebb9b0b 100644 --- a/apps/web/src/pages/activity/index.tsx +++ b/apps/web/src/pages/activity/index.tsx @@ -119,12 +119,14 @@ export default function ActivityPage() { All Activity Types Events - + Emails Emails Sent Emails Opened Emails Clicked + Emails Bounced + Email Complaints Workflows diff --git a/packages/types/src/api/activity.ts b/packages/types/src/api/activity.ts index 48717f8..edb4256 100644 --- a/packages/types/src/api/activity.ts +++ b/packages/types/src/api/activity.ts @@ -12,6 +12,7 @@ export enum ActivityType { EMAIL_OPENED = 'email.opened', EMAIL_CLICKED = 'email.clicked', EMAIL_BOUNCED = 'email.bounced', + EMAIL_COMPLAINT = 'email.complaint', CAMPAIGN_SENT = 'campaign.sent', CAMPAIGN_SCHEDULED = 'campaign.scheduled', WORKFLOW_STARTED = 'workflow.started',