From 610fce8db3532cefc6b452346faf479a8a3776d1 Mon Sep 17 00:00:00 2001 From: francy51 Date: Tue, 3 Mar 2026 23:10:08 -0500 Subject: [PATCH] Add category and tags granularity to company sync flows --- app/analysis/page.tsx | 15 +++ app/filings/page.tsx | 36 +++++- app/watchlist/page.tsx | 75 ++++++++++-- drizzle/0004_watchlist_company_taxonomy.sql | 3 + drizzle/meta/_journal.json | 7 ++ lib/api.ts | 15 ++- lib/server/api/app.ts | 107 +++++++++++++++--- .../api/task-workflow-hybrid.e2e.test.ts | 77 ++++++++++++- lib/server/db/schema.ts | 2 + lib/server/repos/watchlist.ts | 56 ++++++++- lib/server/task-processors.ts | 47 +++++++- lib/types.ts | 4 + 12 files changed, 415 insertions(+), 29 deletions(-) create mode 100644 drizzle/0004_watchlist_company_taxonomy.sql diff --git a/app/analysis/page.tsx b/app/analysis/page.tsx index 8e0e8db..3cf88a5 100644 --- a/app/analysis/page.tsx +++ b/app/analysis/page.tsx @@ -275,6 +275,21 @@ function AnalysisPageContent() {

{analysis?.company.companyName ?? ticker}

{analysis?.company.ticker ?? ticker}

{analysis?.company.sector ?? 'Sector unavailable'}

+ {analysis?.company.category ? ( +

{analysis.company.category}

+ ) : null} + {analysis?.company.tags.length ? ( +
+ {analysis.company.tags.map((tag) => ( + + {tag} + + ))} +
+ ) : null} diff --git a/app/filings/page.tsx b/app/filings/page.tsx index 6da6e94..084e729 100644 --- a/app/filings/page.tsx +++ b/app/filings/page.tsx @@ -47,6 +47,21 @@ 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 asScaledFinancialSnapshot( value: number | null | undefined, scale: NumberScaleUnit @@ -111,6 +126,8 @@ function FilingsPageContent() { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [syncTickerInput, setSyncTickerInput] = useState(''); + const [syncCategoryInput, setSyncCategoryInput] = useState(''); + const [syncTagsInput, setSyncTagsInput] = useState(''); const [filterTickerInput, setFilterTickerInput] = useState(''); const [searchTicker, setSearchTicker] = useState(''); const [financialValueScale, setFinancialValueScale] = useState('millions'); @@ -156,7 +173,12 @@ function FilingsPageContent() { } try { - await queueFilingSync({ ticker: syncTickerInput.trim().toUpperCase(), limit: 20 }); + 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: ['filings'] }); await loadFilings(searchTicker || undefined); @@ -227,6 +249,18 @@ function FilingsPageContent() { 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" + /> Sector setForm((prev) => ({ ...prev, sector: event.target.value }))} /> +
+ + setForm((prev) => ({ ...prev, category: event.target.value }))} placeholder="e.g. Core, Speculative, Watch only" /> +
+
+ + setForm((prev) => ({ ...prev, tags: event.target.value }))} placeholder="Comma-separated tags" /> +