feat: el buscador de Proyectos y Actividades tambien busca en tareas

Buscador de Proyectos: ahora busca tambien en actividades y tareas de cualquier proyecto (antes
solo nombre/codigo del proyecto). Resultados en un panel flotante con la ruta completa
"Proyecto - Actividad - Tarea"; clic navega al proyecto y abre la actividad encontrada
(pestaña Tareas si el resultado era una tarea).

Buscador de Actividades (dentro de un proyecto): busca tambien en las tareas de esa actividad,
mismo panel con "Actividad - Tarea".

Nuevo GET /api/search?q=...&projectId= (global o acotado a un proyecto). Nuevos componentes/hooks
reutilizables: SearchResultsDropdown, useDebouncedValue.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Milton Gonzalez
2026-09-16 15:04:53 -05:00
parent 528a1e7cae
commit 67cb58ed0b
19 changed files with 267 additions and 13 deletions
@@ -0,0 +1,24 @@
// Generico: el llamador arma `items` como [{ key, breadcrumb: [..partes..], onClick }] — este
// componente solo los pinta como "parte1 - parte2 - parte3", clicables, en un panel flotante bajo
// el buscador. Reutilizado por el buscador global de Proyectos ("Proyecto - Actividad - Tarea") y
// por el buscador de Actividades dentro de un proyecto ("Actividad - Tarea").
export function SearchResultsDropdown({ items, emptyLabel }) {
return (
<div className="search-results-dropdown">
{items.length === 0 ? (
<div className="search-results-empty">{emptyLabel}</div>
) : (
items.map((item) => (
<button key={item.key} type="button" className="search-results-item" onClick={item.onClick}>
{item.breadcrumb.map((part, i) => (
<span key={i}>
{i > 0 && <span className="search-results-sep"> — </span>}
{part}
</span>
))}
</button>
))
)}
</div>
);
}