'use client'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { Suspense } from 'react'; import { format } from 'date-fns'; import { Bot, Download, Search, TimerReset } from 'lucide-react'; import { useSearchParams } from 'next/navigation'; import { AppShell } from '@/components/shell/app-shell'; import { Panel } from '@/components/ui/panel'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { StatusPill } from '@/components/ui/status-pill'; import { useAuthGuard } from '@/hooks/use-auth-guard'; import { useTaskPoller } from '@/hooks/use-task-poller'; import { getTask, listFilings, queueFilingAnalysis, queueFilingSync } from '@/lib/api'; import type { Filing, Task } from '@/lib/types'; import { formatCompactCurrency } from '@/lib/format'; export default function FilingsPage() { return ( Opening filings stream...}> ); } function FilingsPageContent() { const { isPending, isAuthenticated } = useAuthGuard(); const searchParams = useSearchParams(); const [filings, setFilings] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [syncTickerInput, setSyncTickerInput] = useState(''); const [filterTickerInput, setFilterTickerInput] = useState(''); const [searchTicker, setSearchTicker] = useState(''); const [activeTask, setActiveTask] = useState(null); useEffect(() => { const ticker = searchParams.get('ticker'); if (ticker) { const normalized = ticker.toUpperCase(); setSyncTickerInput(normalized); setFilterTickerInput(normalized); setSearchTicker(normalized); } }, [searchParams]); const loadFilings = useCallback(async (ticker?: string) => { setLoading(true); setError(null); try { const response = await listFilings({ ticker, limit: 120 }); setFilings(response.filings); } catch (err) { setError(err instanceof Error ? err.message : 'Unable to fetch filings'); } finally { setLoading(false); } }, []); useEffect(() => { if (!isPending && isAuthenticated) { void loadFilings(searchTicker || undefined); } }, [isPending, isAuthenticated, searchTicker, loadFilings]); const polledTask = useTaskPoller({ taskId: activeTask?.id ?? null, onTerminalState: async () => { setActiveTask(null); await loadFilings(searchTicker || undefined); } }); const liveTask = polledTask ?? activeTask; const triggerSync = async () => { if (!syncTickerInput.trim()) { return; } try { const { task } = await queueFilingSync({ ticker: syncTickerInput.trim().toUpperCase(), limit: 20 }); const latest = await getTask(task.id); setActiveTask(latest.task); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to queue filing sync'); } }; const triggerAnalysis = async (accessionNumber: string) => { try { const { task } = await queueFilingAnalysis(accessionNumber); const latest = await getTask(task.id); setActiveTask(latest.task); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to queue filing analysis'); } }; const groupedByTicker = useMemo(() => { const counts = new Map(); for (const filing of filings) { counts.set(filing.ticker, (counts.get(filing.ticker) ?? 0) + 1); } return counts; }, [filings]); if (isPending || !isAuthenticated) { return
Opening filings stream...
; } return ( void loadFilings(searchTicker || undefined)}> Refresh table )} > {liveTask ? (

{liveTask.id}

{liveTask.error ?

{liveTask.error}

: null}
) : null}
{ event.preventDefault(); void triggerSync(); }} > setSyncTickerInput(event.target.value.toUpperCase())} placeholder="Ticker (AAPL)" className="max-w-xs" />
{ event.preventDefault(); setSearchTicker(filterTickerInput.trim().toUpperCase()); }} > setFilterTickerInput(event.target.value.toUpperCase())} placeholder="Ticker filter" className="max-w-xs" />
{error ?

{error}

: null} {loading ? (

Fetching filings...

) : filings.length === 0 ? (

No filings available. Queue a sync job to ingest fresh SEC data.

) : (
{filings.map((filing) => { const revenue = filing.metrics?.revenue; const hasAnalysis = Boolean(filing.analysis?.text || filing.analysis?.legacyInsights); return ( ); })}
Ticker Type Filed Revenue Snapshot Company AI Action
{filing.ticker}
{groupedByTicker.get(filing.ticker)} filings
{filing.filing_type} {format(new Date(filing.filing_date), 'MMM dd, yyyy')} {revenue ? formatCompactCurrency(revenue) : 'n/a'} {filing.company_name} {hasAnalysis ? 'Ready' : 'Not generated'}
{filing.filing_url ? ( SEC ) : null}
)}
); }