/ src / hooks / useFilteredBlocks.ts
useFilteredBlocks.ts
  1  import { useMemo, useState } from 'react';
  2  import { useBlocks } from './useBlocks';
  3  import { getBlockConfidencePercentage } from '@/utils/blockUtils';
  4  
  5  // Define sort options
  6  export type SortOption =
  7      | 'confidenceDesc'
  8      | 'confidenceAsc'
  9      | 'createdAtDesc'
 10      | 'createdAtAsc'
 11      | 'typeAsc'
 12      | 'typeDesc';
 13  
 14  interface UseFilteredBlocksOptions {
 15      initialSearchQuery?: string;
 16      initialSortBy?: SortOption;
 17      initialBlockType?: string | null;
 18  }
 19  
 20  /**
 21   * Hook for fetching, filtering, and sorting memory blocks 
 22   */
 23  export function useFilteredBlocks(options: UseFilteredBlocksOptions = {}) {
 24      // Get blocks from the API
 25      const { blocks, isLoading, isError, mutate } = useBlocks();
 26  
 27      // State for filters
 28      const [searchQuery, setSearchQuery] = useState(options.initialSearchQuery || '');
 29      const [sortBy, setSortBy] = useState<SortOption>(options.initialSortBy || 'confidenceDesc');
 30      const [blockType, setBlockType] = useState<string | null>(options.initialBlockType || null);
 31  
 32      // Apply filters and sort
 33      const filteredAndSortedBlocks = useMemo(() => {
 34          if (!blocks) return [];
 35  
 36          // First, filter blocks by search query
 37          const filtered = blocks.filter(block => {
 38              const lowerQuery = searchQuery.toLowerCase();
 39  
 40              // Skip filtering if search is empty
 41              if (!searchQuery) return true;
 42  
 43              // Filter by text content
 44              if (block.text?.toLowerCase().includes(lowerQuery)) return true;
 45  
 46              // Filter by metadata (depends on block type)
 47              if (block.metadata) {
 48                  // For project blocks, also check name and description
 49                  if (block.type === 'project' && typeof block.metadata.name === 'string') {
 50                      if (block.metadata.name.toLowerCase().includes(lowerQuery)) return true;
 51                  }
 52  
 53                  // For doc blocks, also check title
 54                  if (block.type === 'doc' && typeof block.metadata.title === 'string') {
 55                      if (block.metadata.title.toLowerCase().includes(lowerQuery)) return true;
 56                  }
 57              }
 58  
 59              return false;
 60          });
 61  
 62          // Then, filter by block type if specified
 63          const typeFiltered = blockType
 64              ? filtered.filter(block => block.type === blockType)
 65              : filtered;
 66  
 67          // Finally, sort the blocks
 68          return [...typeFiltered].sort((a, b) => {
 69              switch (sortBy) {
 70                  case 'confidenceDesc':
 71                      return getBlockConfidencePercentage(b) - getBlockConfidencePercentage(a);
 72                  case 'confidenceAsc':
 73                      return getBlockConfidencePercentage(a) - getBlockConfidencePercentage(b);
 74                  case 'createdAtDesc':
 75                      return new Date(b.created_at || 0).getTime() - new Date(a.created_at || 0).getTime();
 76                  case 'createdAtAsc':
 77                      return new Date(a.created_at || 0).getTime() - new Date(b.created_at || 0).getTime();
 78                  case 'typeAsc':
 79                      return a.type.localeCompare(b.type);
 80                  case 'typeDesc':
 81                      return b.type.localeCompare(a.type);
 82                  default:
 83                      return 0;
 84              }
 85          });
 86      }, [blocks, searchQuery, sortBy, blockType]);
 87  
 88      return {
 89          blocks: filteredAndSortedBlocks,
 90          totalBlocks: blocks?.length || 0,
 91          filteredCount: filteredAndSortedBlocks.length,
 92          isLoading,
 93          isError,
 94          searchQuery,
 95          setSearchQuery,
 96          sortBy,
 97          setSortBy,
 98          blockType,
 99          setBlockType,
100          refresh: mutate
101      };
102  }