Add research workspace and graphing flows

This commit is contained in:
2026-03-07 16:52:35 -05:00
parent db01f207a5
commit 62bacdf104
37 changed files with 5494 additions and 434 deletions

View File

@@ -14,7 +14,7 @@ import { aiReportQueryOptions } from '@/lib/query/options';
import type { CompanyAiReportDetail } from '@/lib/types';
import { Button } from '@/components/ui/button';
import { Panel } from '@/components/ui/panel';
import { createResearchJournalEntry } from '@/lib/api';
import { createResearchArtifact } from '@/lib/api';
function formatFilingDate(value: string) {
const date = new Date(value);
@@ -87,6 +87,7 @@ export default function AnalysisReportPage() {
const resolvedTicker = report?.ticker ?? tickerFromRoute;
const analysisHref = resolvedTicker ? `/analysis?ticker=${encodeURIComponent(resolvedTicker)}` : '/analysis';
const researchHref = resolvedTicker ? `/research?ticker=${encodeURIComponent(resolvedTicker)}` : '/research';
const filingsHref = resolvedTicker ? `/filings?ticker=${encodeURIComponent(resolvedTicker)}` : '/filings';
return (
@@ -135,6 +136,15 @@ export default function AnalysisReportPage() {
<ArrowLeft className="size-3" />
Back to filings
</Link>
<Link
href={researchHref}
onMouseEnter={() => prefetchResearchTicker(resolvedTicker)}
onFocus={() => prefetchResearchTicker(resolvedTicker)}
className="inline-flex items-center gap-1 text-xs uppercase tracking-[0.12em] text-[color:var(--accent)] hover:text-[color:var(--accent-strong)]"
>
<ArrowLeft className="size-3" />
Open research
</Link>
</div>
</Panel>
@@ -193,11 +203,14 @@ export default function AnalysisReportPage() {
setJournalNotice(null);
try {
await createResearchJournalEntry({
await createResearchArtifact({
ticker: report.ticker,
kind: 'ai_report',
source: 'system',
subtype: 'filing_analysis',
accessionNumber: report.accessionNumber,
entryType: 'filing_note',
title: `${report.filingType} AI memo`,
summary: report.summary,
bodyMarkdown: [
`Stored AI memo for ${report.companyName} (${report.ticker}).`,
`Accession: ${report.accessionNumber}`,
@@ -205,19 +218,21 @@ export default function AnalysisReportPage() {
report.summary
].join('\n')
});
void queryClient.invalidateQueries({ queryKey: queryKeys.researchWorkspace(report.ticker) });
void queryClient.invalidateQueries({ queryKey: queryKeys.researchPacket(report.ticker) });
void queryClient.invalidateQueries({ queryKey: queryKeys.researchJournal(report.ticker) });
void queryClient.invalidateQueries({ queryKey: queryKeys.companyAnalysis(report.ticker) });
void queryClient.invalidateQueries({ queryKey: queryKeys.watchlist() });
setJournalNotice('Saved to the company research journal.');
setJournalNotice('Saved to the company research library.');
} catch (err) {
setError(err instanceof Error ? err.message : 'Unable to save report to journal');
setError(err instanceof Error ? err.message : 'Unable to save report to library');
} finally {
setSavingToJournal(false);
}
}}
>
<NotebookPen className="size-4" />
{savingToJournal ? 'Saving...' : 'Add to journal'}
{savingToJournal ? 'Saving...' : 'Save to library'}
</Button>
</div>
<p className="whitespace-pre-wrap text-sm leading-7 text-[color:var(--terminal-bright)]">