/ frontend / src / components / overview / QueueCard.tsx
QueueCard.tsx
  1  import { useQueue } from '@/hooks/useDashboard'
  2  
  3  export function QueueCard() {
  4    const { data, isLoading, isError } = useQueue()
  5  
  6    // Handle both new format (running/pending) and old format (flat queue)
  7    let running = data?.running ?? []
  8    let pending = data?.pending ?? []
  9    const queue = data?.queue ?? []
 10  
 11    if (running.length === 0 && pending.length === 0 && queue.length > 0) {
 12      running = queue.filter(item => item.status === 'running')
 13      pending = queue.filter(item => item.status !== 'running')
 14    }
 15  
 16    const totalCount = running.length + pending.length
 17  
 18    return (
 19      <section
 20        className="rounded-lg overflow-hidden"
 21        style={{ background: 'var(--bg-secondary)', border: '1px solid var(--border-color)' }}
 22      >
 23        <h2
 24          className="px-6 py-4 text-base font-semibold flex items-center gap-3"
 25          style={{ background: 'var(--bg-tertiary)', borderBottom: '1px solid var(--border-color)', color: 'var(--text-primary)' }}
 26        >
 27          Queue
 28          <span
 29            className="px-2 py-0.5 rounded-full text-xs font-semibold text-white"
 30            style={{ background: 'var(--accent-blue)' }}
 31          >
 32            {totalCount}
 33          </span>
 34        </h2>
 35  
 36        <ul className="list-none" style={{ maxHeight: '400px', overflowY: 'auto' }}>
 37          {isLoading && (
 38            <li className="px-4 py-8 text-center" style={{ color: 'var(--text-muted)' }}>Loading...</li>
 39          )}
 40          {isError && (
 41            <li className="px-4 py-8 text-center" style={{ color: 'var(--text-muted)' }}>Failed to load queue</li>
 42          )}
 43          {!isLoading && !isError && totalCount === 0 && (
 44            <li className="px-4 py-8 text-center" style={{ color: 'var(--text-muted)' }}>No active runs</li>
 45          )}
 46  
 47          {running.length > 0 && (
 48            <li>
 49              <div
 50                className="px-4 py-2 text-xs font-semibold uppercase tracking-wider"
 51                style={{ color: 'var(--text-secondary)', borderBottom: '1px solid var(--border-color)' }}
 52              >
 53                Running ({running.length})
 54              </div>
 55              {running.map((item, i) => (
 56                <div
 57                  key={i}
 58                  className="px-4 py-3 flex items-center justify-between"
 59                  style={{ borderBottom: '1px solid var(--border-color)' }}
 60                >
 61                  <span className="font-medium" style={{ color: 'var(--text-primary)' }}>
 62                    {item.repo}
 63                  </span>
 64                  {item.agent && (
 65                    <span className="text-xs" style={{ color: 'var(--text-secondary)' }}>
 66                      on {item.agent}
 67                    </span>
 68                  )}
 69                </div>
 70              ))}
 71            </li>
 72          )}
 73  
 74          {pending.length > 0 && (
 75            <li>
 76              <div
 77                className="px-4 py-2 text-xs font-semibold uppercase tracking-wider"
 78                style={{ color: 'var(--text-secondary)', borderBottom: '1px solid var(--border-color)' }}
 79              >
 80                Pending ({pending.length})
 81              </div>
 82              {pending.map((item, i) => (
 83                <div
 84                  key={i}
 85                  className="px-4 py-3 flex items-center justify-between"
 86                  style={{ borderBottom: '1px solid var(--border-color)' }}
 87                >
 88                  <span className="font-medium" style={{ color: 'var(--text-primary)' }}>
 89                    {item.repo}
 90                  </span>
 91                  {item.waiting_for && (
 92                    <span className="text-xs" style={{ color: 'var(--text-secondary)' }}>
 93                      awaiting {item.waiting_for}
 94                    </span>
 95                  )}
 96                </div>
 97              ))}
 98            </li>
 99          )}
100        </ul>
101      </section>
102    )
103  }