feat: Implement Account Lifecycle Tracking

This commit is contained in:
gpt-engineer-app[bot]
2025-10-17 20:26:11 +00:00
parent 09090c29f8
commit 7dcf8156b9
2 changed files with 322 additions and 4 deletions

View File

@@ -21,7 +21,11 @@ import {
CheckCircle,
ChevronDown,
ChevronUp,
Trash2
Trash2,
UserPlus,
UserX,
Ban,
UserCheck
} from 'lucide-react';
import { formatDistanceToNow } from 'date-fns';
import {
@@ -33,7 +37,8 @@ import {
SubmissionReviewDetails,
ReportResolutionDetails,
ReviewModerationDetails,
PhotoApprovalDetails
PhotoApprovalDetails,
AccountLifecycleDetails
} from '@/lib/systemActivityService';
export interface SystemActivityLogRef {
@@ -82,6 +87,42 @@ const activityTypeConfig = {
bgColor: 'bg-teal-500/10',
label: 'Photo Approval',
},
account_created: {
icon: UserPlus,
color: 'text-green-600',
bgColor: 'bg-green-600/10',
label: 'Account Created',
},
account_deletion_requested: {
icon: UserX,
color: 'text-orange-600',
bgColor: 'bg-orange-600/10',
label: 'Deletion Requested',
},
account_deletion_confirmed: {
icon: UserX,
color: 'text-red-600',
bgColor: 'bg-red-600/10',
label: 'Deletion Confirmed',
},
account_deletion_cancelled: {
icon: UserCheck,
color: 'text-blue-600',
bgColor: 'bg-blue-600/10',
label: 'Deletion Cancelled',
},
user_banned: {
icon: Ban,
color: 'text-red-700',
bgColor: 'bg-red-700/10',
label: 'User Banned',
},
user_unbanned: {
icon: UserCheck,
color: 'text-green-700',
bgColor: 'bg-green-700/10',
label: 'User Unbanned',
},
};
export const SystemActivityLog = forwardRef<SystemActivityLogRef, SystemActivityLogProps>(
@@ -322,6 +363,123 @@ export const SystemActivityLog = forwardRef<SystemActivityLogRef, SystemActivity
);
}
case 'account_created': {
const details = activity.details as AccountLifecycleDetails;
return (
<div className="space-y-2">
<div className="flex items-center gap-2 text-sm">
<Badge className="bg-green-600/10 text-green-600">New Account</Badge>
{details.username && (
<span className="font-medium">@{details.username}</span>
)}
</div>
</div>
);
}
case 'account_deletion_requested': {
const details = activity.details as AccountLifecycleDetails;
return (
<div className="space-y-2">
<div className="flex items-center gap-2 text-sm flex-wrap">
<Badge className="bg-orange-600/10 text-orange-600">Deletion Requested</Badge>
{details.scheduled_date && (
<span className="text-muted-foreground text-xs">
Scheduled: {new Date(details.scheduled_date).toLocaleDateString()}
</span>
)}
</div>
{isExpanded && details.request_id && (
<p className="text-xs text-muted-foreground font-mono">
Request ID: {details.request_id}
</p>
)}
</div>
);
}
case 'account_deletion_confirmed': {
const details = activity.details as AccountLifecycleDetails;
return (
<div className="space-y-2">
<div className="flex items-center gap-2 text-sm flex-wrap">
<Badge className="bg-red-600/10 text-red-600">Deletion Confirmed</Badge>
{details.scheduled_date && (
<span className="text-muted-foreground text-xs">
Will be deleted: {new Date(details.scheduled_date).toLocaleDateString()}
</span>
)}
</div>
<div className="flex items-center gap-2 p-2 bg-red-500/5 rounded text-sm">
<AlertCircle className="h-4 w-4 text-red-600" />
<span className="text-muted-foreground">
Account will be permanently deleted after 7 days
</span>
</div>
</div>
);
}
case 'account_deletion_cancelled': {
const details = activity.details as AccountLifecycleDetails;
return (
<div className="space-y-2">
<div className="flex items-center gap-2 text-sm">
<Badge className="bg-blue-600/10 text-blue-600">Deletion Cancelled</Badge>
</div>
{isExpanded && details.reason && (
<div className="flex items-start gap-2 p-2 bg-muted rounded text-sm">
<AlertCircle className="h-4 w-4 mt-0.5 flex-shrink-0" />
<span className="text-muted-foreground">
<strong>Reason:</strong> {details.reason}
</span>
</div>
)}
</div>
);
}
case 'user_banned': {
const details = activity.details as AccountLifecycleDetails;
return (
<div className="space-y-2">
<div className="flex items-center gap-2 text-sm">
<Badge variant="destructive">Banned</Badge>
{details.username && (
<span className="font-medium">@{details.username}</span>
)}
</div>
{isExpanded && details.reason && (
<div className="flex items-start gap-2 p-2 bg-destructive/10 rounded text-sm">
<AlertCircle className="h-4 w-4 mt-0.5 flex-shrink-0 text-destructive" />
<span className="text-muted-foreground">
<strong>Reason:</strong> {details.reason}
</span>
</div>
)}
</div>
);
}
case 'user_unbanned': {
const details = activity.details as AccountLifecycleDetails;
return (
<div className="space-y-2">
<div className="flex items-center gap-2 text-sm">
<Badge className="bg-green-700/10 text-green-700">Unbanned</Badge>
{details.username && (
<span className="font-medium">@{details.username}</span>
)}
</div>
{isExpanded && details.reason && (
<p className="text-sm text-muted-foreground pl-4 border-l-2">
Reason: {details.reason}
</p>
)}
</div>
);
}
default:
return null;
}