From 414315a63a8f4ace74b71714b8ec78e13bcf9229 Mon Sep 17 00:00:00 2001 From: Oscar Cedano Date: Fri, 6 Nov 2026 13:46:24 -0600 Subject: [PATCH] =?UTF-8?q?=F0=9F=92=BB=20wip:=20add=20/reportes=20mock=20?= =?UTF-8?q?search=20and=20visible=20/busqueda=20title?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Cursor Composer 2.5 --- src/common/app-routes.ts | 1 + src/presentation/App.tsx | 4 + .../pages/reports-search/ReportsSearch.tsx | 189 ++++++++++++++++++ .../components/ReportTextSearchForm.tsx | 39 ++++ .../pages/reports-search/mock-reports.ts | 24 +++ src/presentation/pages/search/Search.tsx | 5 +- .../pages/search/components/LookupForm.tsx | 2 +- .../shared/components/SearchInput.tsx | 4 +- 8 files changed, 265 insertions(+), 3 deletions(-) create mode 100644 src/presentation/pages/reports-search/ReportsSearch.tsx create mode 100644 src/presentation/pages/reports-search/components/ReportTextSearchForm.tsx create mode 100644 src/presentation/pages/reports-search/mock-reports.ts diff --git a/src/common/app-routes.ts b/src/common/app-routes.ts index 374f4f4d..64683e32 100644 --- a/src/common/app-routes.ts +++ b/src/common/app-routes.ts @@ -2,6 +2,7 @@ const APP_ROUTES = { home: "/", contact: "/contacto", search: "/busqueda", + reportsSearch: "/reportes", report: "/reportar", terms: "/terminos-y-condiciones", scammer: "/estafadores/:id", diff --git a/src/presentation/App.tsx b/src/presentation/App.tsx index 7d9b8d71..26d24756 100644 --- a/src/presentation/App.tsx +++ b/src/presentation/App.tsx @@ -6,6 +6,9 @@ import { APP_ROUTES } from "@/common/app-routes"; const Home = lazy(() => import("@presentation/pages/home/Home")); const Contact = lazy(() => import("@presentation/pages/contact/Contact")); const Search = lazy(() => import("@presentation/pages/search/Search")); +const ReportsSearch = lazy( + () => import("@presentation/pages/reports-search/ReportsSearch"), +); const NotFound = lazy(() => import("@presentation/pages/404/NotFound")); const Report = lazy(() => import("@presentation/pages/report/Report")); const ReportForm = lazy(() => import("@presentation/pages/report-form/ReportForm")); @@ -31,6 +34,7 @@ function App() { } /> } /> } /> + } /> } /> } /> 0; + const normalizedQuery = Formatter.toSearchQuery(formattedUrlQuery); + const filterActive = hasSubmittedSearch && normalizedQuery.length > 0; + + const matches = useMemo(() => { + if (!filterActive) { + return MOCK_TEXT_REPORT_HITS; + } + + const q = normalizedQuery.toLowerCase(); + return MOCK_TEXT_REPORT_HITS.filter((hit) => { + const haystack = `${hit.title} ${hit.snippet}`.toLowerCase(); + return haystack.includes(q); + }); + }, [filterActive, normalizedQuery]); + + const pageSize = filterActive ? SEARCH_PAGE_SIZE : BROWSE_PAGE_SIZE; + const totalResults = matches.length; + const totalPages = + pageSize > 0 ? Math.ceil(totalResults / pageSize) : 0; + const currentPage = + totalPages > 0 ? Math.min(requestedPage, totalPages) : 1; + + useEffect(() => { + if ( + filterActive && + normalizedQuery && + totalPages > 0 && + requestedPage !== currentPage + ) { + setSearchParams( + `?${Formatter.buildSearchQueryString(urlQuery, currentPage)}`, + { replace: true }, + ); + } + }, [ + currentPage, + filterActive, + normalizedQuery, + requestedPage, + setSearchParams, + totalPages, + urlQuery, + ]); + const pageOffset = (currentPage - 1) * pageSize; + const pageResults = matches.slice(pageOffset, pageOffset + pageSize); + + const handleInputChange = (event: React.InputEvent) => { + setQuery(Formatter.FormatInput(event.currentTarget.value)); + }; + + const handleSubmit = () => { + const formatted = Formatter.FormatInput(query); + const nextSearch = formatted.trim() + ? `?${Formatter.buildSearchQueryString(formatted, 1)}` + : ""; + + setSearchParams(nextSearch); + }; + + const handlePageChange = (page: number) => { + if (page < 1 || page > totalPages || page === currentPage) { + return; + } + + setSearchParams(`?${Formatter.buildSearchQueryString(urlQuery, page)}`); + }; + + return ( + <> + FraudeBot - Búsqueda de reportes + +
+ + + {/* mt-28 clears the fixed header (h-20); matches /busqueda form offset */} +

+ Búsqueda de reportes +

+ + + + {!filterActive && ( +

+ Ejemplos de resultados. Usa el buscador para filtrar por palabras + clave. +

+ )} + + {pageResults.length > 0 && + pageResults.map((hit) => ( + +
+

+ #{hit.displayId} - {hit.title} +

+ + {/* Diagonal arrow only — avoids a square outline that can read like a checkbox */} + + + + +
+

{hit.snippet}

+ + ))} + + {filterActive && normalizedQuery && totalPages > 1 && ( + + )} + + {filterActive && normalizedQuery && totalResults === 0 && ( + + )} + + {hasSubmittedSearch && !normalizedQuery && ( +

+ Ingresa un término de búsqueda o revisa que no esté vacío. +

+ )} +
+ +