'use client'; import { useCallback, useEffect, useState } from 'react'; import { ArrowRight, Eye, Plus, Trash2 } from 'lucide-react'; import Link from 'next/link'; 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 { deleteWatchlistItem, getTask, listWatchlist, queueFilingSync, upsertWatchlistItem } from '@/lib/api'; import type { Task, WatchlistItem } from '@/lib/types'; type FormState = { ticker: string; companyName: string; sector: string; }; export default function WatchlistPage() { const { isPending, isAuthenticated } = useAuthGuard(); const [items, setItems] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [activeTask, setActiveTask] = useState(null); const [form, setForm] = useState({ ticker: '', companyName: '', sector: '' }); const loadWatchlist = useCallback(async () => { setLoading(true); setError(null); try { const response = await listWatchlist(); setItems(response.items); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load watchlist'); } finally { setLoading(false); } }, []); useEffect(() => { if (!isPending && isAuthenticated) { void loadWatchlist(); } }, [isPending, isAuthenticated, loadWatchlist]); const polledTask = useTaskPoller({ taskId: activeTask?.id ?? null, onTerminalState: () => { setActiveTask(null); } }); const liveTask = polledTask ?? activeTask; const submit = async (event: React.FormEvent) => { event.preventDefault(); try { await upsertWatchlistItem({ ticker: form.ticker.toUpperCase(), companyName: form.companyName, sector: form.sector || undefined }); setForm({ ticker: '', companyName: '', sector: '' }); await loadWatchlist(); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to save watchlist item'); } }; const queueSync = async (ticker: string) => { try { const { task } = await queueFilingSync({ ticker, limit: 20 }); const latest = await getTask(task.id); setActiveTask(latest.task); } catch (err) { setError(err instanceof Error ? err.message : `Failed to queue sync for ${ticker}`); } }; if (isPending || !isAuthenticated) { return
Loading watchlist terminal...
; } return ( {liveTask ? (

{liveTask.task_type}

) : null}
{error ?

{error}

: null} {loading ? (

Loading watchlist...

) : items.length === 0 ? (

No symbols yet. Add one from the right panel.

) : (
{items.map((item) => (

{item.sector ?? 'Unclassified'}

{item.ticker}

{item.company_name}

Open stream
))}
)}
setForm((prev) => ({ ...prev, ticker: event.target.value.toUpperCase() }))} required />
setForm((prev) => ({ ...prev, companyName: event.target.value }))} required />
setForm((prev) => ({ ...prev, sector: event.target.value }))} />
); }