/* Global search — GET /search/fetch. Deep-links use live UUIDs so the target screen can resolve the row. Debounced so we don't fire on every keystroke. */ import { useEffect, useRef, useState } from 'react' import { useNavigate } from 'react-router-dom' import { useQuery } from '@tanstack/react-query' import { Avatar, Icon } from '../ui/primitives' import { qk } from '../lib/queryKeys' import * as searchApi from '../api/search' export default function GlobalSearch({ inputRef }) { const navigate = useNavigate() const [q, setQ] = useState('') const [debounced, setDebounced] = useState('') const [open, setOpen] = useState(false) const boxRef = useRef(null) useEffect(() => { const t = setTimeout(() => setDebounced(q.trim()), 250) return () => clearTimeout(t) }, [q]) const query = useQuery({ queryKey: qk.search.query({ q: debounced }), queryFn: async () => { const res = await searchApi.fetch({ q: debounced, limit: 4 }) return res?.data ?? { jobs: [], candidates: [], managers: [] } }, enabled: debounced.length > 0, }) const results = debounced ? (query.data ?? { jobs: [], candidates: [], managers: [] }) : null const jobs = results?.jobs ?? [] const candidates = results?.candidates ?? [] const managers = results?.managers ?? [] const empty = results && !query.isPending && !jobs.length && !candidates.length && !managers.length function go(path, state) { setQ('') setOpen(false) navigate(path, { state }) } return (
e.stopPropagation()}> { setQ(e.target.value) setOpen(Boolean(e.target.value.trim())) }} onFocus={() => setOpen(Boolean(q.trim()))} />
{results && ( <> {query.isPending &&
Searching…
} {query.isError &&
Couldn’t search. Try again.
} {!query.isPending && !query.isError && ( <> {jobs.length > 0 &&
Jobs
} {jobs.map((j) => (
go('/jobs', { openJob: j.id })}>
{j.title}
{[j.department, j.location].filter(Boolean).join(' · ') || 'Job'}
))} {candidates.length > 0 &&
Candidates
} {candidates.map((c) => (
go('/candidates', { openCandidate: c.id })}>
{c.name}
{c.email || 'Candidate'}
))} {managers.length > 0 &&
Hiring Managers
} {managers.map((m) => (
go('/managers', { openManager: m.id })}>
{m.name}
{m.role_name || m.email || 'Hiring manager'}
))} {empty &&
No results for “{q}”
} )} )}
⌘K
) }