refactor(research): replace hardcoded data with TanStack Query API integration
This commit is contained in:
parent
999f0aab4f
commit
cadd965796
1 changed files with 54 additions and 54 deletions
|
|
@ -1,74 +1,49 @@
|
||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
|
import { useQuery } from "@tanstack/react-query"
|
||||||
import { IconBook, IconDatabase, IconCircleCheck, IconSparkles, IconShield, IconActivity, IconCpu, IconFileText, IconSettings } from "@tabler/icons-react"
|
import { IconBook, IconDatabase, IconCircleCheck, IconSparkles, IconShield, IconActivity, IconCpu, IconFileText, IconSettings } from "@tabler/icons-react"
|
||||||
import { ResearchAgents } from "./research-agents"
|
import { ResearchAgents } from "./research-agents"
|
||||||
import { ResearchGraph } from "./research-graph"
|
import { ResearchGraph } from "./research-graph"
|
||||||
import { ResearchConfig } from "./research-config"
|
import { ResearchConfig } from "./research-config"
|
||||||
import { ResearchReports } from "./research-reports"
|
import { ResearchReports } from "./research-reports"
|
||||||
import { Badge } from "@/components/ui/badge"
|
import { Badge } from "@/components/ui/badge"
|
||||||
|
import { listResearchAgents, listResearchGraph, listResearchReports, ResearchAgent, ResearchNode, ResearchReport } from "@/api/research"
|
||||||
|
|
||||||
interface ResearchAgent {
|
const agentIcons: Record<string, React.ComponentType<{ className?: string }>> = {
|
||||||
id: string
|
literature: IconBook,
|
||||||
name: string
|
extractor: IconDatabase,
|
||||||
icon: React.ComponentType<{ className?: string }>
|
validator: IconCircleCheck,
|
||||||
active: boolean
|
synthesizer: IconSparkles,
|
||||||
progress: number
|
|
||||||
ram: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ResearchReport {
|
function mapAgentIcon(type: string): React.ComponentType<{ className?: string }> {
|
||||||
id: string
|
return agentIcons[type] || IconBook
|
||||||
title: string
|
|
||||||
status: "in-progress" | "complete"
|
|
||||||
timestamp: string
|
|
||||||
pages?: number
|
|
||||||
words?: number
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ResearchNode {
|
|
||||||
name: string
|
|
||||||
abbr: string
|
|
||||||
x: number
|
|
||||||
y: number
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultAgents: ResearchAgent[] = [
|
|
||||||
{ id: "literature", name: "Literature Analyzer", icon: IconBook, active: true, progress: 94, ram: "2.4GB" },
|
|
||||||
{ id: "extractor", name: "Data Extractor", icon: IconDatabase, active: true, progress: 87, ram: "1.8GB" },
|
|
||||||
{ id: "validator", name: "Fact Validator", icon: IconCircleCheck, active: true, progress: 76, ram: "1.2GB" },
|
|
||||||
{ id: "synthesizer", name: "Synthesizer", icon: IconSparkles, active: false, progress: 65, ram: "0.9GB" },
|
|
||||||
]
|
|
||||||
|
|
||||||
const defaultReports: ResearchReport[] = [
|
|
||||||
{ id: "1", title: "AI trends 2026", status: "in-progress", timestamp: "2 min ago", pages: 24, words: 7200 },
|
|
||||||
{ id: "2", title: "Quantum computing", status: "complete", timestamp: "1 hour ago", pages: 45, words: 13500 },
|
|
||||||
]
|
|
||||||
|
|
||||||
const defaultNodes: ResearchNode[] = [
|
|
||||||
{ name: "Neural Networks", abbr: "NN", x: 150, y: 80 },
|
|
||||||
{ name: "Transformers", abbr: "TR", x: 150, y: 120 },
|
|
||||||
{ name: "LLM Optimization", abbr: "LO", x: 150, y: 160 },
|
|
||||||
{ name: "Edge Computing", abbr: "EC", x: 150, y: 210 },
|
|
||||||
{ name: "Multi-Agent Systems", abbr: "MA", x: 150, y: 260 },
|
|
||||||
{ name: "Vision Models", abbr: "VM", x: 650, y: 100 },
|
|
||||||
{ name: "RAG Systems", abbr: "RA", x: 650, y: 200 },
|
|
||||||
{ name: "Knowledge Graphs", abbr: "KG", x: 400, y: 150 },
|
|
||||||
{ name: "Agent Architecture", abbr: "AA", x: 400, y: 180 },
|
|
||||||
{ name: "Fine-tuning Methods", abbr: "FT", x: 400, y: 250 },
|
|
||||||
]
|
|
||||||
|
|
||||||
export function ResearchPage() {
|
export function ResearchPage() {
|
||||||
const [agents, setAgents] = useState<ResearchAgent[]>(defaultAgents)
|
|
||||||
const [researchType, setResearchType] = useState<string>("1.5")
|
const [researchType, setResearchType] = useState<string>("1.5")
|
||||||
const [depth, setDepth] = useState<string>("1.5")
|
const [depth, setDepth] = useState<string>("1.5")
|
||||||
const [restrictToGraph, setRestrictToGraph] = useState(false)
|
const [restrictToGraph, setRestrictToGraph] = useState(false)
|
||||||
const [selectedNodes, setSelectedNodes] = useState<Set<string>>(new Set())
|
const [selectedNodes, setSelectedNodes] = useState<Set<string>>(new Set())
|
||||||
|
|
||||||
|
const { data: agents = [], isLoading: agentsLoading, error: agentsError } = useQuery({
|
||||||
|
queryKey: ["researchAgents"],
|
||||||
|
queryFn: listResearchAgents,
|
||||||
|
})
|
||||||
|
|
||||||
|
const { data: nodes = [], isLoading: nodesLoading, error: nodesError } = useQuery({
|
||||||
|
queryKey: ["researchGraph"],
|
||||||
|
queryFn: listResearchGraph,
|
||||||
|
})
|
||||||
|
|
||||||
|
const { data: reports = [], isLoading: reportsLoading, error: reportsError } = useQuery({
|
||||||
|
queryKey: ["researchReports"],
|
||||||
|
queryFn: listResearchReports,
|
||||||
|
})
|
||||||
|
|
||||||
const handleToggleAgent = (id: string) => {
|
const handleToggleAgent = (id: string) => {
|
||||||
setAgents(agents.map(agent =>
|
console.log("Toggle agent:", id)
|
||||||
agent.id === id ? { ...agent, active: !agent.active } : agent
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const activeAgents = agents.filter(a => a.active)
|
const activeAgents = agents.filter(a => a.active)
|
||||||
|
|
@ -76,6 +51,31 @@ export function ResearchPage() {
|
||||||
? Math.round(activeAgents.reduce((sum, a) => sum + a.progress, 0) / activeAgents.length)
|
? Math.round(activeAgents.reduce((sum, a) => sum + a.progress, 0) / activeAgents.length)
|
||||||
: 0
|
: 0
|
||||||
|
|
||||||
|
const completedReports = reports.filter(r => r.status === "complete")
|
||||||
|
|
||||||
|
const isLoading = agentsLoading || nodesLoading || reportsLoading
|
||||||
|
const hasError = agentsError || nodesError || reportsError
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<div className="relative min-h-screen bg-[#050505] overflow-hidden">
|
||||||
|
<div className="absolute inset-0 flex items-center justify-center">
|
||||||
|
<div className="text-[#F27D26] animate-pulse">Loading research data...</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasError) {
|
||||||
|
return (
|
||||||
|
<div className="relative min-h-screen bg-[#050505] overflow-hidden">
|
||||||
|
<div className="absolute inset-0 flex items-center justify-center">
|
||||||
|
<div className="text-red-500">Failed to load research data</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative min-h-screen bg-[#050505] overflow-hidden">
|
<div className="relative min-h-screen bg-[#050505] overflow-hidden">
|
||||||
{/* Ghost Background Typography */}
|
{/* Ghost Background Typography */}
|
||||||
|
|
@ -116,7 +116,7 @@ export function ResearchPage() {
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<IconFileText className="w-4 h-4 text-white/40" />
|
<IconFileText className="w-4 h-4 text-white/40" />
|
||||||
<span className="text-xs text-white/60">Reports:</span>
|
<span className="text-xs text-white/60">Reports:</span>
|
||||||
<span className="text-sm font-semibold text-[#F2F2F2]">{defaultReports.filter(r => r.status === "complete").length}</span>
|
<span className="text-sm font-semibold text-[#F2F2F2]">{completedReports.length}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -135,7 +135,7 @@ export function ResearchPage() {
|
||||||
{/* Center Column - Graph */}
|
{/* Center Column - Graph */}
|
||||||
<div className="flex-1 bg-[#050505] relative">
|
<div className="flex-1 bg-[#050505] relative">
|
||||||
<ResearchGraph
|
<ResearchGraph
|
||||||
nodes={defaultNodes}
|
nodes={nodes}
|
||||||
selectedNodes={selectedNodes}
|
selectedNodes={selectedNodes}
|
||||||
onNodeToggle={(name: string) => {
|
onNodeToggle={(name: string) => {
|
||||||
setSelectedNodes(prev => {
|
setSelectedNodes(prev => {
|
||||||
|
|
@ -162,7 +162,7 @@ export function ResearchPage() {
|
||||||
setRestrictToGraph={setRestrictToGraph}
|
setRestrictToGraph={setRestrictToGraph}
|
||||||
/>
|
/>
|
||||||
<ResearchReports
|
<ResearchReports
|
||||||
reports={defaultReports}
|
reports={reports}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
@ -173,7 +173,7 @@ export function ResearchPage() {
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<span>PicoClaw Research Engine v2.4.1</span>
|
<span>PicoClaw Research Engine v2.4.1</span>
|
||||||
<span className="text-white/20">|</span>
|
<span className="text-white/20">|</span>
|
||||||
<span>Nodes: {defaultNodes.length}</span>
|
<span>Nodes: {nodes.length}</span>
|
||||||
<span className="text-white/20">|</span>
|
<span className="text-white/20">|</span>
|
||||||
<span>Agents: {activeAgents.length} active</span>
|
<span>Agents: {activeAgents.length} active</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue