"use client"; import { useState } from "react"; import { formatDistanceToNow } from "date-fns"; import { Activity, CheckCircle2, PlusCircle, MessageSquare, UserPlus, Edit3, FolderKanban, Filter, RefreshCw, } from "lucide-react"; import { cn } from "@/lib/utils"; import { useActivityFeed, ActivityFilterType } from "@/hooks/use-activity-feed"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Skeleton } from "@/components/ui/skeleton"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import type { ActivityItem, Database } from "@/lib/supabase/database.types"; type Project = Database["public"]["Tables"]["projects"]["Row"]; interface ActivityFeedContentProps { activities: ActivityItem[]; projects: Pick[]; loading: boolean; error: string | null; refresh: () => void; filterType: ActivityFilterType; onFilterTypeChange: (value: ActivityFilterType) => void; projectId: string; onProjectIdChange: (value: string) => void; } const activityTypeConfig: Record< ActivityItem["type"], { label: string; icon: React.ElementType; color: string } > = { task_created: { label: "Created", icon: PlusCircle, color: "bg-blue-500/10 text-blue-500", }, task_completed: { label: "Completed", icon: CheckCircle2, color: "bg-green-500/10 text-green-500", }, task_updated: { label: "Updated", icon: Edit3, color: "bg-yellow-500/10 text-yellow-500", }, comment_added: { label: "Comment", icon: MessageSquare, color: "bg-purple-500/10 text-purple-500", }, task_assigned: { label: "Assigned", icon: UserPlus, color: "bg-pink-500/10 text-pink-500", }, }; const filterOptions: { value: ActivityFilterType; label: string }[] = [ { value: "all", label: "All Activity" }, { value: "task_created", label: "Created" }, { value: "task_completed", label: "Completed" }, { value: "task_updated", label: "Updated" }, { value: "comment_added", label: "Comments" }, { value: "task_assigned", label: "Assigned" }, ]; function ActivityItemCard({ activity }: { activity: ActivityItem }) { const config = activityTypeConfig[activity.type]; const Icon = config.icon; const timestampMs = new Date(activity.timestamp).getTime(); const timeAgo = Number.isNaN(timestampMs) ? "just now" : formatDistanceToNow(new Date(timestampMs), { addSuffix: true }); return (
{/* Icon */}
{/* Content */}
{/* Header */}
{activity.user_name} {config.label} {activity.task_title}
{/* Project badge */}
{activity.project_name}
{/* Details */} {activity.details && (

{activity.details}

)} {/* Comment text */} {activity.comment_text && (

"{activity.comment_text}"

)} {/* Timestamp */}

{timeAgo}

{/* Avatar */} {activity.user_avatar_url ? ( {activity.user_name} ) : (
)}
); } function ActivitySkeleton() { return (
); } export function ActivityFeedContent({ activities, projects, loading, error, refresh, filterType, onFilterTypeChange, projectId, onProjectIdChange, }: ActivityFeedContentProps) { return (
Recent Activity
{/* Filter by type */} {/* Filter by project */} {/* Refresh button */}
{loading ? ( // Loading skeletons Array.from({ length: 5 }).map((_, i) => ( )) ) : error ? ( // Error state

Failed to load activities

{error}

) : activities.length === 0 ? ( // Empty state

No activity yet

Tasks and comments will appear here

) : ( // Activity list activities.map((activity) => ( )) )}
); } export function ActivityFeed() { const [filterType, setFilterType] = useState("all"); const [projectId, setProjectId] = useState("all"); const { activities, projects, loading, error, refresh } = useActivityFeed({ limit: 50, projectId: projectId === "all" ? undefined : projectId, filterType: filterType === "all" ? undefined : filterType, }); return ( ); }