import { useState } from 'react' import { createFileRoute, Link, useNavigate } from '@tanstack/react-router' import { useTranslation } from 'react-i18next' import { Badge, EmptyState, LoadingBlock, PageHeader, Panel, QueryErrorState, SearchInput, } from '@/ui' import { useSearch } from '@/api/queries' type SearchSearch = { q?: string } const validateSearch = (raw: Record): SearchSearch => { if (typeof raw.q === 'string' && raw.q.length > 0) return { q: raw.q } return {} } export const Route = createFileRoute('/search')({ component: SearchPage, validateSearch, }) /** * Smart JSONB search across all dictionaries (CEO plan v1 stretch). * *

Backend: GET /api/v1/search?q=&size&perDict — ILIKE с trigram-индексом * на dictionary_records.data::text. Min query length = 3 (trigram threshold). * *

UI: search input → grouped results per dict с per-row link на full * record. URL state ?q=… — share-friendly. */ function SearchPage() { const { t } = useTranslation() const urlSearch = Route.useSearch() const navigate = useNavigate({ from: Route.fullPath }) const [input, setInput] = useState(urlSearch.q ?? '') const result = useSearch(urlSearch.q) const handleSubmit = (e: React.FormEvent) => { e.preventDefault() const trimmed = input.trim() void navigate({ search: trimmed ? { q: trimmed } : {}, replace: true }) } const tooShort = input.length > 0 && input.length < 3 const hasQuery = Boolean(urlSearch.q && urlSearch.q.length >= 3) return (

setInput(e.target.value)} placeholder={t('search.placeholder')} aria-label={t('search.placeholder')} autoFocus />
{tooShort && (

{t('search.tooShort')}

)} {hasQuery && result.isLoading && ( )} {hasQuery && result.error && ( result.refetch()} /> )} {hasQuery && result.data && result.data.total === 0 && ( )} {hasQuery && result.data && result.data.total > 0 && ( <>

{t('search.totalHits', { count: result.data.total })}

{result.data.groups.map((g) => (
{g.dictDisplayName ?? g.dictName} {g.count}
    {g.items.map((it) => (
  • {it.businessKey}
    {it.dataScope} {new Date(it.createdAt).toLocaleString()}
  • ))}
))}
)} {!hasQuery && !tooShort && (

{t('search.intro')}

)}
) }