fix(ui): handle URL params in search page for command palette navigation

The search page now reads `q` and `mode` query parameters from the URL,
enabling proper integration with the command palette's search/ask actions.

Changes:
- Read URL params using useSearchParams hook
- Initialize form fields and active tab from URL params
- Auto-trigger search/ask when arriving with URL params
- Handle subsequent navigations while on the search page
This commit is contained in:
LUIS NOVO 2025-12-01 20:46:49 -03:00
parent 728f036eeb
commit 33be80ab7c

View file

@ -1,6 +1,7 @@
'use client'
import { useMemo, useState } from 'react'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useSearchParams } from 'next/navigation'
import { AppShell } from '@/components/layout/AppShell'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { Input } from '@/components/ui/input'
@ -23,14 +24,24 @@ import { AdvancedModelsDialog } from '@/components/search/AdvancedModelsDialog'
import { SaveToNotebooksDialog } from '@/components/search/SaveToNotebooksDialog'
export default function SearchPage() {
// URL params
const searchParams = useSearchParams()
const urlQuery = searchParams.get('q') || ''
const urlMode = searchParams.get('mode') || 'ask'
// Tab state (controlled)
const [activeTab, setActiveTab] = useState<'ask' | 'search'>(
urlMode === 'search' ? 'search' : 'ask'
)
// Search state
const [searchQuery, setSearchQuery] = useState('')
const [searchQuery, setSearchQuery] = useState(urlMode === 'search' ? urlQuery : '')
const [searchType, setSearchType] = useState<'text' | 'vector'>('text')
const [searchSources, setSearchSources] = useState(true)
const [searchNotes, setSearchNotes] = useState(true)
// Ask state
const [askQuestion, setAskQuestion] = useState('')
const [askQuestion, setAskQuestion] = useState(urlMode === 'ask' ? urlQuery : '')
// Advanced models dialog
const [showAdvancedModels, setShowAdvancedModels] = useState(false)
@ -64,7 +75,11 @@ export default function SearchPage() {
const hasEmbeddingModel = !!modelDefaults?.default_embedding_model
const handleSearch = () => {
// Track if we've already auto-triggered from URL params
const hasAutoTriggeredRef = useRef(false)
const lastUrlParamsRef = useRef({ q: '', mode: '' })
const handleSearch = useCallback(() => {
if (!searchQuery.trim()) return
searchMutation.mutate({
@ -75,7 +90,7 @@ export default function SearchPage() {
search_notes: searchNotes,
minimum_score: 0.2
})
}
}, [searchQuery, searchType, searchSources, searchNotes, searchMutation])
const handleKeyPress = (e: React.KeyboardEvent) => {
if (e.key === 'Enter') {
@ -83,7 +98,7 @@ export default function SearchPage() {
}
}
const handleAsk = () => {
const handleAsk = useCallback(() => {
if (!askQuestion.trim() || !modelDefaults?.default_chat_model) return
const models = customModels || {
@ -93,14 +108,56 @@ export default function SearchPage() {
}
ask.sendAsk(askQuestion, models)
}
}, [askQuestion, modelDefaults, customModels, ask])
// Auto-trigger search/ask when arriving with URL params
useEffect(() => {
// Skip if already triggered or no query
if (hasAutoTriggeredRef.current || !urlQuery) return
// Wait for models to load before triggering ask
if (urlMode === 'ask' && modelsLoading) return
hasAutoTriggeredRef.current = true
if (urlMode === 'search') {
handleSearch()
} else if (urlMode === 'ask' && modelDefaults?.default_chat_model) {
handleAsk()
}
}, [urlQuery, urlMode, modelsLoading, modelDefaults, handleSearch, handleAsk])
// Handle URL param changes while on page (e.g., from command palette again)
useEffect(() => {
const currentQ = searchParams.get('q') || ''
const currentMode = searchParams.get('mode') || 'ask'
// Check if URL params have changed
if (currentQ !== lastUrlParamsRef.current.q || currentMode !== lastUrlParamsRef.current.mode) {
lastUrlParamsRef.current = { q: currentQ, mode: currentMode }
if (currentQ) {
// Update state based on mode
if (currentMode === 'search') {
setSearchQuery(currentQ)
setActiveTab('search')
// Reset trigger flag so we auto-trigger with new params
hasAutoTriggeredRef.current = false
} else {
setAskQuestion(currentQ)
setActiveTab('ask')
hasAutoTriggeredRef.current = false
}
}
}
}, [searchParams])
return (
<AppShell>
<div className="p-4 md:p-6">
<h1 className="text-xl md:text-2xl font-bold mb-4 md:mb-6">Ask and Search</h1>
<Tabs defaultValue="ask" className="w-full space-y-6">
<Tabs value={activeTab} onValueChange={(v) => setActiveTab(v as 'ask' | 'search')} className="w-full space-y-6">
<div className="space-y-2">
<p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Choose a mode</p>
<TabsList aria-label="Ask or search your knowledge base" className="w-full max-w-xl">