diff --git a/ordinis-admin-ui/src/components/layout/TopBar.tsx b/ordinis-admin-ui/src/components/layout/TopBar.tsx index 370b56e..12a0b98 100644 --- a/ordinis-admin-ui/src/components/layout/TopBar.tsx +++ b/ordinis-admin-ui/src/components/layout/TopBar.tsx @@ -1,10 +1,8 @@ import { useTranslation } from 'react-i18next' -import { Link, useLocation, useNavigate } from '@tanstack/react-router' +import { Link, useLocation } from '@tanstack/react-router' import { useDictionaries, useDictionaryDetail } from '@/api/queries' import { VersionBadge } from '@/components/version/VersionBadge' -import { SearchInput } from '@/ui/components/search-input' import { Bell, Menu } from 'lucide-react' -import { useEffect, useRef, useState } from 'react' /** * TopBar — sticky header (h=56) per handoff design. @@ -17,78 +15,8 @@ import { useEffect, useRef, useState } from 'react' */ export function TopBar({ onMenuClick }: { onMenuClick?: () => void }) { const { t } = useTranslation() - const navigate = useNavigate() - const location = useLocation() - const isCatalog = location.pathname === '/dictionaries' - const catalogQ = isCatalog - ? ((location.search as Record)?.q as string | undefined) ?? '' - : '' - const [searchValue, setSearchValue] = useState(catalogQ) - const inputRef = useRef(null) const breadcrumb = useBreadcrumb() - // Sync local input value c URL `?q=` when navigating between routes. - useEffect(() => { - setSearchValue(catalogQ) - }, [catalogQ]) - - // ⌘K / Ctrl+K focus shortcut. - useEffect(() => { - const handler = (e: KeyboardEvent) => { - if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') { - const target = e.target as HTMLElement - if (target && (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA')) { - if (target === inputRef.current) return - } - e.preventDefault() - inputRef.current?.focus() - inputRef.current?.select() - } - } - window.addEventListener('keydown', handler) - return () => window.removeEventListener('keydown', handler) - }, []) - - // Context-aware search: - // - На /dictionaries — live filter каталога через URL `?q=` - // - На остальных routes — local state, submit redirect'ит на /search - const handleSearchInput = (e: React.ChangeEvent) => { - const v = e.target.value - setSearchValue(v) - if (isCatalog) { - void navigate({ - to: '/dictionaries', - search: (prev: Record) => ({ - ...prev, - q: v.length > 0 ? v : undefined, - }), - replace: true, - }) - } - } - - const handleSearchSubmit = (e: React.FormEvent) => { - e.preventDefault() - const q = searchValue.trim() - if (q.length === 0) return - if (isCatalog) return - void navigate({ to: '/search', search: { q } }) - } - - const handleSearchClear = () => { - setSearchValue('') - if (isCatalog) { - void navigate({ - to: '/dictionaries', - search: (prev: Record) => { - const { q: _q, ...rest } = prev - return rest - }, - replace: true, - }) - } - } - return (
{/* Hamburger (lg:hidden) — toggle MobileSidebar */} @@ -144,24 +72,9 @@ export function TopBar({ onMenuClick }: { onMenuClick?: () => void }) { })} - {/* Search center — context-aware (catalog mode = live filter, else = - * records search submit). Двойной X fixed в SearchInput component - * (type="text" вместо "search" — убрал native browser X). */} -
- - + {/* TopBar search убран per user — catalog имеет свой input в toolbar, + * для records search используется /search route через sidebar nav. + * "Search из TopBar убран — все верно". */} {/* Right cluster — broadcast slot per user: "руководство и версию * оставить в топбар чтобы подсвечивать новинки. туда же и сообщения". diff --git a/ordinis-admin-ui/src/routes/dictionaries.index.tsx b/ordinis-admin-ui/src/routes/dictionaries.index.tsx index 0ea9637..f85ba76 100644 --- a/ordinis-admin-ui/src/routes/dictionaries.index.tsx +++ b/ordinis-admin-ui/src/routes/dictionaries.index.tsx @@ -232,9 +232,9 @@ function DictionariesPage() { * Узкая: px-3 py-1.5 (~6px vertical) — per user feedback ("бар поужать"). */}
{/* Catalog search — filter dicts by name/displayName/description. - * type="text" (не "search") чтобы избежать native X — мы рендерим - * свой clear button если нужно. */} -
+ * type="text" чтобы избежать native browser X — рендерим свой + * custom clear button справа когда есть value. Single X. */} +
+ {search.q && ( + + )}
{/* Scope filter: PUBLIC / INTERNAL / RESTRICTED — pill chips с border */}