'use client'; import Link from 'next/link'; import { ParticipantListItem } from '@/app/actions/participants'; import { useState, useMemo } from 'react'; interface ParticipantsListProps { experimentId: number; participants: ParticipantListItem[]; } type SortField = 'userId' | 'email' | 'createdAt' | 'annotationCount'; type SortOrder = 'asc' | 'desc'; export default function ParticipantsList({ experimentId, participants }: ParticipantsListProps) { const [searchQuery, setSearchQuery] = useState(''); const [sortField, setSortField] = useState('createdAt'); const [sortOrder, setSortOrder] = useState('desc'); const handleSort = (field: SortField) => { if (sortField === field) { setSortOrder(sortOrder === 'asc' ? 'desc' : 'asc'); } else { setSortField(field); setSortOrder('asc'); } }; const getSortIndicator = (field: SortField) => { if (sortField !== field) return ' ↑↓'; return sortOrder === 'asc' ? ' ↑' : ' ↓'; }; const filteredAndSortedParticipants = useMemo(() => { let filtered = participants.filter((p) => { const query = searchQuery.toLowerCase(); return ( p.userId.toLowerCase().includes(query) || p.email.toLowerCase().includes(query) ); }); filtered.sort((a, b) => { let aValue: any = a[sortField]; let bValue: any = b[sortField]; if (sortField === 'createdAt') { aValue = new Date(aValue).getTime(); bValue = new Date(bValue).getTime(); } const comparison = aValue < bValue ? -1 : aValue > bValue ? 1 : 0; return sortOrder === 'asc' ? comparison : -comparison; }); return filtered; }, [participants, searchQuery, sortField, sortOrder]); if (participants.length === 0) { return (

No participants yet

); } return (
{/* Search Bar */}
setSearchQuery(e.target.value)} className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" />
{/* Table */}
{filteredAndSortedParticipants.map((participant) => ( ))}
handleSort('userId')}> User ID{getSortIndicator('userId')} handleSort('email')}> Email{getSortIndicator('email')} Onboarding Calibration handleSort('annotationCount')}> Annotations{getSortIndicator('annotationCount')} handleSort('createdAt')}> Joined{getSortIndicator('createdAt')} Action
{participant.userId} {participant.email} {participant.completedOnboarding ? '✓ Done' : '○ Pending'} {participant.completedCalibration ? '✓ Done' : '○ Pending'} {participant.annotationCount} {new Date(participant.createdAt).toLocaleDateString()} View
{filteredAndSortedParticipants.length === 0 && (
No participants match your search
)}
); }