feat: migrate task jobs to workflow notifications + timeline
This commit is contained in:
40
app/page.tsx
40
app/page.tsx
@@ -9,10 +9,8 @@ import { Panel } from '@/components/ui/panel';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { MetricCard } from '@/components/dashboard/metric-card';
|
||||
import { TaskFeed } from '@/components/dashboard/task-feed';
|
||||
import { StatusPill } from '@/components/ui/status-pill';
|
||||
import { useAuthGuard } from '@/hooks/use-auth-guard';
|
||||
import { useLinkPrefetch } from '@/hooks/use-link-prefetch';
|
||||
import { useTaskPoller } from '@/hooks/use-task-poller';
|
||||
import {
|
||||
queuePortfolioInsights,
|
||||
queuePriceRefresh
|
||||
@@ -25,7 +23,6 @@ import {
|
||||
latestPortfolioInsightQueryOptions,
|
||||
portfolioSummaryQueryOptions,
|
||||
recentTasksQueryOptions,
|
||||
taskQueryOptions,
|
||||
watchlistQueryOptions
|
||||
} from '@/lib/query/options';
|
||||
|
||||
@@ -58,7 +55,6 @@ export default function CommandCenterPage() {
|
||||
const [state, setState] = useState<DashboardState>(EMPTY_STATE);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [activeTaskId, setActiveTaskId] = useState<string | null>(null);
|
||||
|
||||
const loadData = useCallback(async () => {
|
||||
const summaryOptions = portfolioSummaryQueryOptions();
|
||||
@@ -102,30 +98,16 @@ export default function CommandCenterPage() {
|
||||
}
|
||||
}, [isPending, isAuthenticated, loadData]);
|
||||
|
||||
const trackedTask = useTaskPoller({
|
||||
taskId: activeTaskId,
|
||||
onTerminalState: () => {
|
||||
setActiveTaskId(null);
|
||||
void queryClient.invalidateQueries({ queryKey: queryKeys.portfolioSummary() });
|
||||
void queryClient.invalidateQueries({ queryKey: queryKeys.latestPortfolioInsight() });
|
||||
void queryClient.invalidateQueries({ queryKey: queryKeys.recentTasks(20) });
|
||||
void queryClient.invalidateQueries({ queryKey: ['filings'] });
|
||||
void loadData();
|
||||
}
|
||||
});
|
||||
|
||||
const headerActions = (
|
||||
<>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={async () => {
|
||||
try {
|
||||
const { task } = await queuePriceRefresh();
|
||||
setActiveTaskId(task.id);
|
||||
const latest = await queryClient.fetchQuery(taskQueryOptions(task.id));
|
||||
setState((prev) => ({ ...prev, tasks: [latest.task, ...prev.tasks] }));
|
||||
await queuePriceRefresh();
|
||||
void queryClient.invalidateQueries({ queryKey: queryKeys.recentTasks(20) });
|
||||
void queryClient.invalidateQueries({ queryKey: queryKeys.portfolioSummary() });
|
||||
await loadData();
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Failed to queue price refresh');
|
||||
}
|
||||
@@ -137,12 +119,10 @@ export default function CommandCenterPage() {
|
||||
<Button
|
||||
onClick={async () => {
|
||||
try {
|
||||
const { task } = await queuePortfolioInsights();
|
||||
setActiveTaskId(task.id);
|
||||
const latest = await queryClient.fetchQuery(taskQueryOptions(task.id));
|
||||
setState((prev) => ({ ...prev, tasks: [latest.task, ...prev.tasks] }));
|
||||
await queuePortfolioInsights();
|
||||
void queryClient.invalidateQueries({ queryKey: queryKeys.recentTasks(20) });
|
||||
void queryClient.invalidateQueries({ queryKey: queryKeys.latestPortfolioInsight() });
|
||||
await loadData();
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Failed to queue AI insight');
|
||||
}
|
||||
@@ -169,18 +149,6 @@ export default function CommandCenterPage() {
|
||||
subtitle={`Welcome back${session?.user?.name ? `, ${session.user.name}` : ''}. Review tasks, portfolio health, and AI outputs.`}
|
||||
actions={headerActions}
|
||||
>
|
||||
{activeTaskId && trackedTask ? (
|
||||
<Panel title="Live Task" subtitle={`Task ${activeTaskId.slice(0, 8)} is active.`}>
|
||||
<div className="flex items-center justify-between gap-3 rounded-lg border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-3 py-2">
|
||||
<p className="text-sm text-[color:var(--terminal-bright)]">{trackedTask.task_type.replace('_', ' ')}</p>
|
||||
<StatusPill status={trackedTask.status} />
|
||||
</div>
|
||||
{trackedTask.error ? (
|
||||
<p className="mt-3 text-sm text-[#ff9898]">{trackedTask.error}</p>
|
||||
) : null}
|
||||
</Panel>
|
||||
) : null}
|
||||
|
||||
{error ? (
|
||||
<Panel>
|
||||
<p className="text-sm text-[#ffb5b5]">{error}</p>
|
||||
|
||||
Reference in New Issue
Block a user