'use client'; import { useQuery, useQueryClient } from '@tanstack/react-query'; import Link from 'next/link'; import { useEffect, useMemo, useState } from 'react'; import { Suspense } from 'react'; import { format } from 'date-fns'; import { Bot, Download, ExternalLink, NotebookPen, Search, TimerReset } from 'lucide-react'; import { useRouter, 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 { useAuthGuard } from '@/hooks/use-auth-guard'; import { useLinkPrefetch } from '@/hooks/use-link-prefetch'; import { createResearchArtifact, queueFilingAnalysis, queueFilingSync } from '@/lib/api'; import type { Filing } from '@/lib/types'; import { formatCurrencyByScale, type NumberScaleUnit } from '@/lib/format'; import { queryKeys } from '@/lib/query/keys'; import { filingsQueryOptions } from '@/lib/query/options'; const FINANCIAL_VALUE_SCALE_OPTIONS: Array<{ value: NumberScaleUnit; label: string }> = [ { value: 'thousands', label: 'Thousands (K)' }, { value: 'millions', label: 'Millions (M)' }, { value: 'billions', label: 'Billions (B)' } ]; const FILINGS_QUERY_LIMIT = 120; export default function FilingsPage() { return ( Opening filings stream...}> ); } function formatFilingDate(value: string) { const date = new Date(value); if (Number.isNaN(date.getTime())) { return 'Unknown'; } return format(date, 'MMM dd, yyyy'); } function hasFinancialSnapshot(filing: Filing) { return filing.filing_type === '10-K' || filing.filing_type === '10-Q'; } function parseTagsInput(input: string) { const unique = new Set(); for (const segment of input.split(',')) { const tag = segment.trim(); if (!tag) { continue; } unique.add(tag); } return [...unique]; } function normalizeTickerParam(value: string | null) { if (typeof value !== 'string') { return null; } const normalized = value.trim().toUpperCase(); return normalized.length > 0 ? normalized : null; } function asScaledFinancialSnapshot( value: number | null | undefined, scale: NumberScaleUnit ) { if (value === null || value === undefined) { return 'n/a'; } return formatCurrencyByScale(value, scale); } function resolveOriginalFilingUrl(filing: Filing) { if (filing.filing_url) { return filing.filing_url; } if (!filing.primary_document) { return null; } const cikDigits = filing.cik.replace(/\D/g, ''); const cikValue = Number.parseInt(cikDigits, 10); if (!cikDigits || Number.isNaN(cikValue)) { return null; } const compactAccession = filing.accession_number.replace(/-/g, ''); if (!compactAccession) { return null; } return `https://www.sec.gov/Archives/edgar/data/${cikValue}/${compactAccession}/${filing.primary_document}`; } type FilingExternalLinkProps = { href: string; label: string; }; function FilingExternalLink({ href, label }: FilingExternalLinkProps) { return ( {label} ); } function FilingsPageContent() { const { isPending, isAuthenticated } = useAuthGuard(); const searchParams = useSearchParams(); const router = useRouter(); const queryClient = useQueryClient(); const { prefetchReport } = useLinkPrefetch(); const activeTickerFilter = useMemo(() => normalizeTickerParam(searchParams.get('ticker')), [searchParams]); const activeFilingsQueryKey = useMemo( () => queryKeys.filings(activeTickerFilter, FILINGS_QUERY_LIMIT), [activeTickerFilter] ); const filingsQuery = useQuery({ ...filingsQueryOptions({ ticker: activeTickerFilter ?? undefined, limit: FILINGS_QUERY_LIMIT }), enabled: !isPending && isAuthenticated }); const [syncTickerInput, setSyncTickerInput] = useState(() => activeTickerFilter ?? ''); const [syncCategoryInput, setSyncCategoryInput] = useState(''); const [syncTagsInput, setSyncTagsInput] = useState(''); const [filterTickerInput, setFilterTickerInput] = useState(() => activeTickerFilter ?? ''); const [financialValueScale, setFinancialValueScale] = useState('millions'); const [actionNotice, setActionNotice] = useState(null); const [actionError, setActionError] = useState(null); useEffect(() => { setSyncTickerInput(activeTickerFilter ?? ''); setFilterTickerInput(activeTickerFilter ?? ''); }, [activeTickerFilter]); const filings = filingsQuery.data?.filings ?? []; const loading = filingsQuery.isPending; const filingsError = filingsQuery.error instanceof Error ? filingsQuery.error.message : filingsQuery.error ? 'Unable to fetch filings' : null; const triggerSync = async () => { if (!syncTickerInput.trim()) { return; } try { setActionError(null); await queueFilingSync({ ticker: syncTickerInput.trim().toUpperCase(), limit: 20, category: syncCategoryInput.trim() || undefined, tags: parseTagsInput(syncTagsInput) }); void queryClient.invalidateQueries({ queryKey: queryKeys.recentTasks(20) }); void queryClient.invalidateQueries({ queryKey: activeFilingsQueryKey }); } catch (err) { setActionError(err instanceof Error ? err.message : 'Failed to queue filing sync'); } }; const triggerAnalysis = async (accessionNumber: string) => { try { setActionError(null); await queueFilingAnalysis(accessionNumber); void queryClient.invalidateQueries({ queryKey: queryKeys.recentTasks(20) }); void queryClient.invalidateQueries({ queryKey: ['report'] }); } catch (err) { setActionError(err instanceof Error ? err.message : 'Failed to queue filing analysis'); } }; const saveToLibrary = async (filing: Filing) => { try { setActionError(null); await createResearchArtifact({ ticker: filing.ticker, kind: 'filing', source: 'system', subtype: 'filing_snapshot', accessionNumber: filing.accession_number, title: `${filing.filing_type} filing snapshot`, summary: filing.analysis?.text ?? filing.analysis?.legacyInsights ?? `Captured filing ${filing.accession_number}.`, bodyMarkdown: [ `Captured filing note for ${filing.company_name} (${filing.ticker}).`, `Filed: ${formatFilingDate(filing.filing_date)}`, `Accession: ${filing.accession_number}`, '', filing.analysis?.text ?? filing.analysis?.legacyInsights ?? 'Follow up on this filing from the stream.' ].join('\n'), metadata: { filingType: filing.filing_type, filingDate: filing.filing_date, filingUrl: filing.filing_url, submissionUrl: filing.submission_url ?? null, primaryDocument: filing.primary_document ?? null } }); void queryClient.invalidateQueries({ queryKey: queryKeys.researchWorkspace(filing.ticker) }); void queryClient.invalidateQueries({ queryKey: queryKeys.researchPacket(filing.ticker) }); void queryClient.invalidateQueries({ queryKey: queryKeys.researchJournal(filing.ticker) }); void queryClient.invalidateQueries({ queryKey: queryKeys.companyAnalysis(filing.ticker) }); void queryClient.invalidateQueries({ queryKey: queryKeys.watchlist() }); setActionNotice(`Saved ${filing.accession_number} to the ${filing.ticker} research library.`); } catch (err) { setActionError(err instanceof Error ? err.message : 'Failed to save filing to library'); } }; const replaceTickerFilter = (ticker: string | null) => { const nextParams = new URLSearchParams(searchParams.toString()); if (ticker) { nextParams.set('ticker', ticker); } else { nextParams.delete('ticker'); } const nextQuery = nextParams.toString(); router.replace(nextQuery ? `/filings?${nextQuery}` : '/filings', { scroll: false }); }; 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]); const selectedFinancialScaleLabel = useMemo(() => { return FINANCIAL_VALUE_SCALE_OPTIONS.find((option) => option.value === financialValueScale)?.label ?? 'Millions (M)'; }, [financialValueScale]); if (isPending || !isAuthenticated) { return
Opening filings stream...
; } return ( Ask with RAG )} >
{ event.preventDefault(); void triggerSync(); }} > setSyncTickerInput(event.target.value.toUpperCase())} placeholder="Ticker (AAPL)" className="w-full sm:max-w-xs" /> setSyncCategoryInput(event.target.value)} placeholder="Category (optional)" className="w-full sm:max-w-xs" /> setSyncTagsInput(event.target.value)} placeholder="Tags (comma-separated)" className="w-full sm:max-w-xs" />
{ event.preventDefault(); const nextTicker = normalizeTickerParam(filterTickerInput); setFilterTickerInput(nextTicker ?? ''); replaceTickerFilter(nextTicker); }} > setFilterTickerInput(event.target.value.toUpperCase())} placeholder="Ticker filter" className="w-full sm:max-w-xs" />
{FINANCIAL_VALUE_SCALE_OPTIONS.map((option) => ( ))} )} > {actionError ?

{actionError}

: null} {filingsError ?

{filingsError}

: null} {actionNotice ?

{actionNotice}

: null} {loading ? (

Fetching filings...

) : filings.length === 0 ? (

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

) : (
{filings.map((filing) => { const financialForm = hasFinancialSnapshot(filing); const revenue = filing.metrics?.revenue; const hasAnalysis = Boolean(filing.analysis?.text || filing.analysis?.legacyInsights); const originalFilingUrl = resolveOriginalFilingUrl(filing); return (

{filing.ticker} ยท {filing.filing_type}

{formatFilingDate(filing.filing_date)}

{hasAnalysis ? 'AI ready' : 'AI pending'}

{filing.company_name}

Financial Snapshot
{financialForm ? asScaledFinancialSnapshot(revenue, financialValueScale) : 'Qualitative filing'}
Accession
{filing.accession_number}
{originalFilingUrl ? ( ) : ( Original filing unavailable )} {filing.submission_url ? ( ) : null} {hasAnalysis ? ( prefetchReport(filing.ticker, filing.accession_number)} onFocus={() => prefetchReport(filing.ticker, filing.accession_number)} className="inline-flex items-center rounded-md border border-[color:var(--line-weak)] px-2 py-1 text-xs text-[color:var(--accent)] transition hover:border-[color:var(--line-strong)] hover:text-[color:var(--accent-strong)]" > Open summary ) : null}
); })}
{filings.map((filing) => { const financialForm = hasFinancialSnapshot(filing); const revenue = filing.metrics?.revenue; const hasAnalysis = Boolean(filing.analysis?.text || filing.analysis?.legacyInsights); const originalFilingUrl = resolveOriginalFilingUrl(filing); return ( ); })}
Ticker Type Filed Revenue Snapshot Company AI Links Action
{filing.ticker}
{groupedByTicker.get(filing.ticker)} filings
{filing.filing_type} {formatFilingDate(filing.filing_date)} {financialForm ? asScaledFinancialSnapshot(revenue, financialValueScale) : 'Qualitative filing'} {filing.company_name} {hasAnalysis ? 'Ready' : 'Not generated'}
{originalFilingUrl ? ( ) : ( Unavailable )} {filing.submission_url ? ( ) : null}
{hasAnalysis ? ( prefetchReport(filing.ticker, filing.accession_number)} onFocus={() => prefetchReport(filing.ticker, filing.accession_number)} className="inline-flex items-center rounded-md border border-[color:var(--line-weak)] px-2 py-1 text-xs text-[color:var(--accent)] transition hover:border-[color:var(--line-strong)] hover:text-[color:var(--accent-strong)]" > Summary ) : null}
)}
); }