import { Button, Filter as BaseFilter, FilterProvider, FilterBtn, FilterBar, FilterClear, FilterGroup } from '@vertesia/ui/core'; import { useEffect, useMemo, useRef, useState } from 'react'; import { VInteractionFacet } from './utils/VInteractionFacet'; import { VStringFacet } from './utils/VStringFacet'; import { VUserFacet } from './utils/VUserFacet'; import { SearchInterface } from './utils/SearchInterface'; import { RefreshCw } from 'lucide-react'; interface AgentRunnerFacetsNavProps { facets: { statuses?: any[]; initiated_by?: any[]; interactions?: any[]; }; search: SearchInterface; actions?: React.ReactNode[]; selectionCount?: number; } // Hook to create filter groups for agent runners export function useAgentRunnerFilterGroups(facets: AgentRunnerFacetsNavProps['facets']): FilterGroup[] { const customFilterGroups: FilterGroup[] = []; customFilterGroups.push({ name: 'id', placeholder: 'Agent Run ID', type: 'text', multiple: false }); customFilterGroups.push(VInteractionFacet({ buckets: facets.interactions || [], name: 'interaction', placeholder: 'Interaction', })); customFilterGroups.push(VStringFacet({ search: null as any, // This will be provided by the search context buckets: facets.statuses || [], name: 'status', placeholder: 'Status', })); customFilterGroups.push(VUserFacet({ buckets: facets.initiated_by || [], name: 'initiated_by', placeholder: 'Initiated By' })); customFilterGroups.push({ name: 'start', placeholder: 'Started After', type: 'date' as const, multiple: false }); customFilterGroups.push({ name: 'end', placeholder: 'Started Before', type: 'date' as const, multiple: false }); return customFilterGroups; } // Create filter change handler for agent runners export function createAgentRunnerFilterHandler(search: SearchInterface) { return (newFilters: BaseFilter[]) => { // Clear all filters first, then apply new ones search.clearFilters(false, false); newFilters.forEach(filter => { if (filter.value && filter.value.length > 0) { const filterName = filter.name; let filterValue; if (filter.multiple) { filterValue = Array.isArray(filter.value) ? filter.value.map((v: any) => typeof v === 'object' && v.value ? v.value : v) : [typeof filter.value === 'object' && (filter.value as any).value ? (filter.value as any).value : filter.value]; } else { // Single value - don't wrap in array filterValue = Array.isArray(filter.value) && filter.value[0] && typeof filter.value[0] === 'object' ? (filter.value[0] as any).value : Array.isArray(filter.value) && filter.value[0] ? filter.value[0] : filter.value; } search.query[filterName] = filterValue; } }); search.search(); }; } // Legacy component for backward compatibility export function AgentRunnerFacetsNav({ facets, search, selectionCount, actions }: AgentRunnerFacetsNavProps) { const [filters, setFilters] = useState([]); const didMountRef = useRef(false); const skipNextSearchRef = useRef( typeof window !== 'undefined' && Boolean(new URLSearchParams(window.location.search).get('filters')) ); const filterGroups = useAgentRunnerFilterGroups(facets); const handleFilterLogic = useMemo(() => createAgentRunnerFilterHandler(search), [search]); useEffect(() => { if (!didMountRef.current) { didMountRef.current = true; return; } if (skipNextSearchRef.current) { skipNextSearchRef.current = false; return; } handleFilterLogic(filters); }, [filters, handleFilterLogic]); const handleRefetch = () => { search.search(); }; return (
{!selectionCount && (
{search.initialized ? `${search.totalCount} agent runs` : 'Loading agent runs...'}
)} {actions && actions.length > 0 ? (
{actions.map((action, index) => (
{action}
))}
) : null}
{filters.length > 0 && (
)}
); }