~bigbes/lethe

ref: 6806748f7302141c5259dd82474f3655ccc231c8 lethe/web/src/features/search/SearchTable.tsx -rw-r--r-- 2.1 KiB
6806748f — Eugene Blikh chore: track task file and dist update for search UI 23 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import React from 'react'
import { useNavigate } from '@tanstack/react-router'
import { EmptyState, ToolDot } from '../../primitives'
import type { SearchRow } from '../../api/adapters'
import { highlightSnippet } from './highlightSnippet'

interface SearchTableProps {
  rows: SearchRow[]
  hasMore: boolean
  loadingMore: boolean
  onLoadMore: () => void
}

const COLS = '80px 1fr 1fr 2fr 60px'

export function SearchTable({ rows, hasMore, loadingMore, onLoadMore }: SearchTableProps): React.JSX.Element {
  const navigate = useNavigate()

  if (rows.length === 0) {
    return (
      <div className="body body-pad">
        <EmptyState glyph="∅" copy="no matches" />
      </div>
    )
  }

  return (
    <div className="search-table body">
      <div className="search-thead search-cols" style={{ gridTemplateColumns: COLS }}>
        <span>tool</span>
        <span>host</span>
        <span>cwd</span>
        <span>snippet</span>
        <span className="right">rank</span>
      </div>
      {rows.map((r, i) => (
        <div
          key={`${r.sessionId}-${r.turnId}-${i}`}
          className="search-row search-cols"
          style={{ gridTemplateColumns: COLS }}
          onClick={() => {
            void navigate({
              to: '/session/$tool/$host/$id',
              params: { tool: r.tool, host: r.host, id: r.sessionId },
              hash: `turn-${r.turnId}`,
            })
          }}
        >
          <span className="mono"><ToolDot tool={r.tool} /> {r.tool}</span>
          <span className="mono truncate">{r.host}</span>
          <span className="mono muted truncate">{r.cwd}</span>
          <span className="snippet truncate">{highlightSnippet(r.snippet)}</span>
          <span className="right mono muted">{r.rank}</span>
        </div>
      ))}
      {hasMore && (
        <div className="load-more-wrap">
          <button
            className="load-more"
            type="button"
            disabled={loadingMore}
            onClick={onLoadMore}
          >
            {loadingMore ? 'loading…' : 'load more'}
          </button>
        </div>
      )}
    </div>
  )
}