import { useEffect, useMemo, useRef, useState } from 'react'; import { useVirtualizer } from '@tanstack/react-virtual'; import type { MirrorJob } from '@/lib/db/schema'; import Fuse from 'fuse.js'; import { Button } from '../ui/button'; import { RefreshCw, Check, X, Loader2, Import } from 'lucide-react'; import { Card } from '../ui/card'; import { formatDate, getStatusColor } from '@/lib/utils'; import { Skeleton } from '../ui/skeleton'; import type { FilterParams } from '@/types/filter'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from '../ui/tooltip'; type MirrorJobWithKey = MirrorJob & { _rowKey: string }; interface ActivityListProps { activities: MirrorJobWithKey[]; isLoading: boolean; isLiveActive?: boolean; filter: FilterParams; setFilter: (filter: FilterParams) => void; } export default function ActivityList({ activities, isLoading, isLiveActive = false, filter, setFilter, }: ActivityListProps) { const [expandedItems, setExpandedItems] = useState>( () => new Set(), ); const parentRef = useRef(null); // We keep the ref only for possible future scroll-to-row logic. const rowRefs = useRef>(new Map()); // eslint-disable-line @typescript-eslint/no-unused-vars const filteredActivities = useMemo(() => { let result = activities; if (filter.status) { result = result.filter((a) => a.status === filter.status); } if (filter.type) { result = filter.type === 'repository' ? result.filter((a) => !!a.repositoryId) : filter.type === 'organization' ? result.filter((a) => !!a.organizationId) : result; } if (filter.name) { result = result.filter( (a) => a.repositoryName === filter.name || a.organizationName === filter.name, ); } if (filter.searchTerm) { const fuse = new Fuse(result, { keys: ['message', 'details', 'organizationName', 'repositoryName'], threshold: 0.3, }); result = fuse.search(filter.searchTerm).map((r) => r.item); } return result; }, [activities, filter]); const virtualizer = useVirtualizer({ count: filteredActivities.length, getScrollElement: () => parentRef.current, estimateSize: (idx) => expandedItems.has(filteredActivities[idx]._rowKey) ? 217 : 100, overscan: 5, measureElement: (el) => el.getBoundingClientRect().height + 8, }); useEffect(() => { virtualizer.measure(); }, [expandedItems, virtualizer]); /* ------------------------------ render ------------------------------ */ if (isLoading) { return (
{Array.from({ length: 5 }, (_, i) => ( ))}
); } if (filteredActivities.length === 0) { const hasFilter = filter.searchTerm || filter.status || filter.type || filter.name; return (

No activities found

{hasFilter ? 'Try adjusting your search or filter criteria.' : 'No mirroring activities have been recorded yet.'}

{hasFilter && ( )}
); } return (
{virtualizer.getVirtualItems().map((vRow) => { const activity = filteredActivities[vRow.index]; const isExpanded = expandedItems.has(activity._rowKey); return (
{ rowRefs.current.set(activity._rowKey, node); if (node) virtualizer.measureElement(node); }} style={{ position: 'absolute', top: 0, left: 0, width: '100%', transform: `translateY(${vRow.start}px)`, paddingBottom: '8px', }} className='border-b px-4 pt-4' >
{/* Mobile: Show simplified status-based message */}

{activity.status === 'synced' ? ( <> Sync successful ) : activity.status === 'mirrored' ? ( <> Mirror successful ) : activity.status === 'failed' ? ( <> Operation failed ) : activity.status === 'syncing' ? ( <> Syncing in progress ) : activity.status === 'mirroring' ? ( <> Mirroring in progress ) : activity.status === 'imported' ? ( <> Imported ) : ( {activity.message} )}

{/* Desktop: Show status with icon and full message in tooltip */}

{activity.status === 'synced' ? ( <> Sync successful ) : activity.status === 'mirrored' ? ( <> Mirror successful ) : activity.status === 'failed' ? ( <> Operation failed ) : activity.status === 'syncing' ? ( <> Syncing in progress ) : activity.status === 'mirroring' ? ( <> Mirroring in progress ) : activity.status === 'imported' ? ( <> Imported ) : ( {activity.message} )}

{activity.message}

{formatDate(activity.timestamp)}

{activity.repositoryName && (

Repo: {activity.repositoryName}

)} {activity.organizationName && (

Org: {activity.organizationName}

)}
{activity.details && (
{isExpanded && (
                          {activity.details}
                        
)}
)}
); })}
{/* Status Bar */}
{filteredActivities.length} {filteredActivities.length === 1 ? 'activity' : 'activities'} total
{/* Center - Live active indicator */} {isLiveActive && (
Live active
)} {(filter.searchTerm || filter.status || filter.type || filter.name) && ( Filters applied )}
); }