import { useState } from 'react'
import { useQuery } from '@tanstack/react-query'
import { queryApi } from '../lib/api'
import LoadingSpinner from '../components/LoadingSpinner'
type QueryType = 'nips' | 'flows' | 'types' | 'shared-types' | 'data-flow'
export default function Query() {
const [activeTab, setActiveTab] = useState<QueryType>('nips')
const [typeSearch, setTypeSearch] = useState('')
const [typeRepo, setTypeRepo] = useState('')
const [typeKind, setTypeKind] = useState('')
const nipsQuery = useQuery({
queryKey: ['query', 'nips'],
queryFn: async () => {
const response = await queryApi.nips()
return response.data
},
enabled: activeTab === 'nips',
})
const flowsQuery = useQuery({
queryKey: ['query', 'flows'],
queryFn: async () => {
const response = await queryApi.flows()
return response.data
},
enabled: activeTab === 'flows',
})
const typesQuery = useQuery({
queryKey: ['query', 'types', typeSearch, typeRepo, typeKind],
queryFn: async () => {
const response = await queryApi.types({
name: typeSearch || undefined,
repo: typeRepo || undefined,
kind: typeKind || undefined,
limit: 50,
})
return response.data
},
enabled: activeTab === 'types',
})
const sharedTypesQuery = useQuery({
queryKey: ['query', 'shared-types'],
queryFn: async () => {
const response = await queryApi.sharedTypes({ limit: 20 })
return response.data
},
enabled: activeTab === 'shared-types',
})
const dataFlowQuery = useQuery({
queryKey: ['query', 'data-flow'],
queryFn: async () => {
const response = await queryApi.dataFlow()
return response.data
},
enabled: activeTab === 'data-flow',
})
const tabs = [
{ id: 'nips' as QueryType, label: 'NIPs', query: nipsQuery },
{ id: 'flows' as QueryType, label: 'User Flows', query: flowsQuery },
{ id: 'types' as QueryType, label: 'Types', query: typesQuery },
{ id: 'shared-types' as QueryType, label: 'Shared Types', query: sharedTypesQuery },
{ id: 'data-flow' as QueryType, label: 'Data Flow', query: dataFlowQuery },
]
const activeQuery = tabs.find((t) => t.id === activeTab)?.query
return (
<div>
<h1 className="text-3xl font-bold mb-6">Query Interface</h1>
<div className="bg-gray-800 rounded-lg p-4 mb-6">
<div className="flex gap-2 border-b border-gray-700">
{tabs.map((tab) => (
<button
key={tab.id}
onClick={() => setActiveTab(tab.id)}
className={`px-4 py-2 border-b-2 transition-colors ${
activeTab === tab.id
? 'border-blue-500 text-blue-500'
: 'border-transparent text-gray-400 hover:text-white'
}`}
>
{tab.label}
</button>
))}
</div>
</div>
{activeTab === 'types' && (
<div className="bg-gray-800 rounded-lg p-4 mb-6">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
<label className="block text-sm font-medium mb-2">Search by name</label>
<input
type="text"
value={typeSearch}
onChange={(e) => setTypeSearch(e.target.value)}
placeholder="Type name..."
className="w-full bg-gray-700 border border-gray-600 rounded px-3 py-2"
/>
</div>
<div>
<label className="block text-sm font-medium mb-2">Repository</label>
<input
type="text"
value={typeRepo}
onChange={(e) => setTypeRepo(e.target.value)}
placeholder="Repo name..."
className="w-full bg-gray-700 border border-gray-600 rounded px-3 py-2"
/>
</div>
<div>
<label className="block text-sm font-medium mb-2">Kind</label>
<select
value={typeKind}
onChange={(e) => setTypeKind(e.target.value)}
className="w-full bg-gray-700 border border-gray-600 rounded px-3 py-2"
>
<option value="">All</option>
<option value="struct">Struct</option>
<option value="class">Class</option>
<option value="interface">Interface</option>
<option value="enum">Enum</option>
</select>
</div>
</div>
</div>
)}
{activeQuery?.isLoading && <LoadingSpinner />}
{activeQuery?.error && (
<div className="text-red-500 p-4">
Error: {activeQuery.error instanceof Error ? activeQuery.error.message : 'Unknown error'}
</div>
)}
{activeQuery?.data && (
<div className="bg-gray-800 rounded-lg p-6">
<pre className="bg-gray-900 p-4 rounded overflow-auto text-sm">
{JSON.stringify(activeQuery.data, null, 2)}
</pre>
</div>
)}
</div>
)
}
export { Query }