SPB Git

Repository Public

page.tsx 2.4 KB 50 lines tsx

1'use client';2import { useState } from 'react';3import { useWaits } from '@/lib/queries';4import { FilterChips } from '@/components/ui/chips';5import { EmptyState, ErrorState, Skeleton } from '@/components/ui/misc';6import { IllusAllClear } from '@/components/ui/illustrations';7import { WaitCard } from '@/components/waits/wait-card';89type Filter = 'all' | 'approval' | 'question';1011export default function ApprovalsPage() {12  const q = useWaits();13  const [filter, setFilter] = useState<Filter>('all');14  const all = q.data ?? [];15  const list = all.filter((w) => filter === 'all' || w.kind === filter);16  const n = (k: Filter) => all.filter((w) => k === 'all' || w.kind === k).length;17  return (18    <div className="h-full overflow-y-auto" data-testid="approvals-page">19      <div className="mx-auto flex w-full max-w-3xl flex-col gap-4 px-4 pb-32 pt-1 md:px-8 md:pb-12 md:pt-6">20        <div className="hidden md:block">21          <h1 className="text-xl font-bold tracking-tight">Approvals</h1>22          <p className="text-[13px] text-text-2">Agents are suspended on these requests. Nothing here runs until you decide; an expired request counts as a denial.</p>23        </div>24        {all.length > 0 && (25          <FilterChips label="Kind" value={filter} onChange={setFilter} options={[{ id: 'all', label: 'All', count: n('all') }, { id: 'approval', label: 'Approvals', count: n('approval') }, { id: 'question', label: 'Questions', count: n('question') }]} />26        )}27        {q.isError ? (28          <div className="card"><ErrorState error={q.error} onRetry={() => q.refetch()} /></div>29        ) : q.isPending ? (30          <><Skeleton className="h-44 rounded-md" /><Skeleton className="h-44 rounded-md" /></>31        ) : list.length === 0 ? (32          <div className="card" data-testid="approvals-empty">33            <EmptyState34              illustration={<IllusAllClear />}35              title={all.length === 0 ? 'Inbox zero' : 'Nothing of this kind'}36              description={all.length === 0 ? 'No agent is waiting for you. Requests for sensitive actions and questions land here, oldest first.' : 'Switch the filter to see the other requests.'}37            />38          </div>39        ) : (40          <ol className="flex flex-col gap-4" data-testid="approvals-list">41            {list.map((w) => (42              <li key={w.id}><WaitCard wait={w} /></li>43            ))}44          </ol>45        )}46      </div>47    </div>48  );49}50
Files main
Menu

Theme