diff --git a/console/src/pages/agent-turns.tsx b/console/src/pages/agent-turns.tsx index 3eb3d01..13beecb 100644 --- a/console/src/pages/agent-turns.tsx +++ b/console/src/pages/agent-turns.tsx @@ -1,4 +1,4 @@ -import { useState, useCallback } from "react" +import { useCallback } from "react" import { ArrowUpDown, ArrowUp, ArrowDown, ChevronLeft, ChevronRight, Loader2, Filter } from "lucide-react" import { cn } from "@/lib/utils" import { useAgentTurns } from "@/hooks/use-agent-turns" @@ -93,7 +93,7 @@ export function AgentTurnsPage() { const statusFilter = statusStr ? statusStr.split(",") : [] const agentKindFilter = agentKindStr ? agentKindStr.split(",") : [] - const [selectedId, setSelectedId] = useState(null) + const [selectedId, setSelectedId] = useSearchParamState("selected", "") const { data, isLoading, isError, error } = useAgentTurns({ page, @@ -283,7 +283,7 @@ export function AgentTurnsPage() { {/* Slide-over detail panel */} {selectedId && ( - setSelectedId(null)} /> + setSelectedId("")} /> )} ) diff --git a/console/src/pages/http-exchanges.tsx b/console/src/pages/http-exchanges.tsx index 6c9ad37..4f16d0b 100644 --- a/console/src/pages/http-exchanges.tsx +++ b/console/src/pages/http-exchanges.tsx @@ -1,4 +1,4 @@ -import { useState, useCallback } from "react" +import { useCallback } from "react" import { ArrowUpDown, ArrowUp, @@ -131,8 +131,7 @@ export function HttpExchangesPage() { const statusFilter = statusStr ? statusStr.split(",") : [] const isSse = sseStr === "true" ? true : sseStr === "false" ? false : undefined - const [selectedId, setSelectedId] = useState(null) - const [selectedIndex, setSelectedIndex] = useState(-1) + const [selectedId, setSelectedId] = useSearchParamState("selected", "") const { data, isLoading, isError, error } = useHttpExchanges({ page, @@ -166,26 +165,33 @@ export function HttpExchangesPage() { [sortBy, sortOrder, setSortBy, setSortOrder, setPageStr], ) - const handleRowClick = useCallback((id: string, index: number) => { - setSelectedId(id) - setSelectedIndex(index) - }, []) + // Index derived from id so the selection survives URL paste / refresh: + // we own only one source of truth (the URL), and prev/next still works + // as long as the selected id is on the current page. + const selectedIndex = selectedId + ? items.findIndex((i) => i.id === selectedId) + : -1 + + const handleRowClick = useCallback( + (id: string, _index: number) => { + setSelectedId(id) + }, + [setSelectedId], + ) const handleNavigate = useCallback( (direction: "prev" | "next") => { const newIndex = direction === "prev" ? selectedIndex - 1 : selectedIndex + 1 if (newIndex >= 0 && newIndex < items.length) { - setSelectedIndex(newIndex) setSelectedId(items[newIndex].id) } }, - [selectedIndex, items], + [selectedIndex, items, setSelectedId], ) const handleClose = useCallback(() => { - setSelectedId(null) - setSelectedIndex(-1) - }, []) + setSelectedId("") + }, [setSelectedId]) return (
diff --git a/console/src/pages/llm-calls.tsx b/console/src/pages/llm-calls.tsx index cae64c9..de22dd3 100644 --- a/console/src/pages/llm-calls.tsx +++ b/console/src/pages/llm-calls.tsx @@ -1,4 +1,4 @@ -import { useState, useCallback, useMemo } from "react" +import { useCallback, useMemo } from "react" import { ArrowUpDown, ArrowUp, ArrowDown, ChevronLeft, ChevronRight, Loader2, Filter } from "lucide-react" import { cn } from "@/lib/utils" import { useLlmCalls } from "@/hooks/use-llm-calls" @@ -145,8 +145,7 @@ export function LlmCallsPage() { .map(([label, options]) => ({ label, options: [...options].sort() })) }, [finishReasonsData]) - const [selectedId, setSelectedId] = useState(null) - const [selectedIndex, setSelectedIndex] = useState(-1) + const [selectedId, setSelectedId] = useSearchParamState("selected", "") const { data, isLoading, isError, error } = useLlmCalls({ page, @@ -179,26 +178,33 @@ export function LlmCallsPage() { [sortBy, sortOrder, setSortBy, setSortOrder, setPageStr], ) - const handleRowClick = useCallback((id: string, index: number) => { - setSelectedId(id) - setSelectedIndex(index) - }, []) + // Index derived from id so the selection survives URL paste / refresh: + // we own only one source of truth (the URL), and prev/next still works + // as long as the selected id is on the current page. + const selectedIndex = selectedId + ? items.findIndex((i) => i.id === selectedId) + : -1 + + const handleRowClick = useCallback( + (id: string, _index: number) => { + setSelectedId(id) + }, + [setSelectedId], + ) const handleNavigate = useCallback( (direction: "prev" | "next") => { const newIndex = direction === "prev" ? selectedIndex - 1 : selectedIndex + 1 if (newIndex >= 0 && newIndex < items.length) { - setSelectedIndex(newIndex) setSelectedId(items[newIndex].id) } }, - [selectedIndex, items], + [selectedIndex, items, setSelectedId], ) const handleClose = useCallback(() => { - setSelectedId(null) - setSelectedIndex(-1) - }, []) + setSelectedId("") + }, [setSelectedId]) return (