@@ -0,0 +1,54 @@
import { Head , Link } from '@inertiajs/react' ;
import { useEffect , useState } from 'react' ;
import { Search as SearchIcon } from 'lucide-react' ;
type Result = { title : string ; description : string | null ; url : string ; category : string } ;
type Results = { data : Result [ ] ; total : number ; current_page : number ; last_page : number ; per_page : number ; unavailable : string [ ] } ;
function pageNumbers ( current : number , last : number ) : ( number | string ) [ ] {
const pages = [ . . . new Set ( [ 1 , last , . . . Array . from ( { length : 5 } , ( _ , i ) = > current - 2 + i ) ] ) ]
. filter ( ( page ) = > page >= 1 && page <= last ) . sort ( ( a , b ) = > a - b ) ;
return pages . flatMap ( ( page , i ) = > i > 0 && page - pages [ i - 1 ] > 1 ? [ ` gap- ${ page } ` , page ] : [ page ] ) ;
}
export default function Search ( { query , results } : { query : string ; results : Results } ) {
const [ input , setInput ] = useState ( query ) ;
useEffect ( ( ) = > setInput ( query ) , [ query ] ) ;
const { data , total , current_page : current , last_page : last , per_page : perPage , unavailable } = results ;
const pageUrl = ( page : number ) = > ` /pesquisa? ${ new URLSearchParams ( { q : query , page : String ( page ) } )} ` ;
const start = total ? ( current - 1 ) * perPage + 1 : 0 ;
const end = Math . min ( start + data . length - 1 , total ) ;
return < main className = "min-h-[65vh] bg-white text-[#101820]" >
< Head title = "Pesquisa" / >
< div className = "border-b border-slate-200 bg-[#101820] text-white" >
< div className = "mx-auto max-w-5xl px-4 py-8 sm:px-6" >
< h1 className = "text-3xl font-bold tracking-tight" > Pesquisa no InvesteMoz < / h1 >
< form action = "/pesquisa" role = "search" className = "mt-5 flex max-w-3xl flex-col gap-2 sm:flex-row" >
< label htmlFor = "search-query" className = "sr-only" > Pesquisar no InvesteMoz < / label >
< input id = "search-query" type = "search" name = "q" value = { input } onChange = { ( event ) = > setInput ( event . target . value ) } maxLength = { 120 } className = "min-h-12 min-w-0 flex-1 rounded-lg border border-slate-300 bg-white px-4 text-base text-[#101820] outline-none focus:ring-2 focus:ring-[#ed1c24]" placeholder = "Oportunidades, documentos, sectores..." / >
< button className = "inline-flex min-h-12 items-center justify-center gap-2 rounded-lg bg-[#ed1c24] px-6 font-semibold text-white hover:bg-[#c9141b] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white" > < SearchIcon size = { 18 } aria-hidden = "true" / > Pesquisar < / button >
< / form >
< / div >
< / div >
< div className = "mx-auto max-w-5xl px-4 py-7 sm:px-6" >
< p className = "max-w-3xl text-sm leading-relaxed text-slate-600" > Pesquise por palavras em qualquer ordem . Pode escrever com ou sem acentos . Os documentos são pesquisados pelos seus dados descritivos . < / p >
{ unavailable . length > 0 && < p role = "alert" className = "mt-4 rounded-lg border border-amber-400 bg-amber-50 p-3 text-sm" > Não foi possível consultar : { unavailable . join ( ', ' ) } . Os restantes resultados continuam disponíveis ; tente novamente mais tarde . < / p > }
{ query && < p className = "mt-6 text-sm text-slate-600" aria-live = "polite" > { total > 0 ? ` Resultados ${ start } – ${ end } de ${ total } ` : 'Nenhum resultado nas fontes consultadas' } para “ { query } ” . < / p > }
{ query && total === 0 && < p className = "mt-4 text-slate-600" > Experimente outras palavras ou uma expressão mais curta . < / p > }
< ol start = { start || 1 } className = "mt-2 max-w-3xl divide-y divide-slate-200" >
{ data . map ( ( item ) = > < li key = { ` ${ item . category } : ${ item . url } ` } className = "py-5" >
< p className = "mb-1 text-xs font-semibold uppercase tracking-wide text-slate-600" > { item . category } < / p >
< Link href = { item . url } className = "text-lg font-semibold text-[#b5121b] underline-offset-4 hover:underline focus-visible:rounded focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-[#ed1c24]" > { item . title } < / Link >
{ item . description && < p className = "mt-1 line-clamp-3 text-sm leading-relaxed text-slate-600" > { item . description } < / p > }
< / li > ) }
< / ol >
{ last > 1 && < nav className = "mt-8 flex flex-wrap items-center gap-2" aria-label = "Páginas de resultados" >
{ current > 1 && < Link href = { pageUrl ( current - 1 ) } rel = "prev" className = "rounded-md px-3 py-2 text-sm font-semibold text-[#b5121b] hover:bg-red-50" > Anterior < / Link > }
{ pageNumbers ( current , last ) . map ( ( page ) = > typeof page === 'string' ? < span key = { page } className = "px-1 text-slate-500" aria-hidden = "true" > … < / span > :
< Link key = { page } href = { pageUrl ( page ) } aria-label = { ` Página ${ page } ` } aria-current = { page === current ? 'page' : undefined } className = { page === current ? 'rounded-md bg-[#101820] px-3 py-2 text-sm font-bold text-white' : 'rounded-md px-3 py-2 text-sm font-semibold text-[#b5121b] hover:bg-red-50' } > { page } < / Link > ) }
{ current < last && < Link href = { pageUrl ( current + 1 ) } rel = "next" className = "rounded-md px-3 py-2 text-sm font-semibold text-[#b5121b] hover:bg-red-50" > Seguinte < / Link > }
< / nav > }
< / div >
< / main > ;
}