document.addEventListener('alpine:init', () => { Alpine.data('searchApp', () => ({ searchParams: { q: '', numero_diario: '', data_inicio: '', data_fim: '', modo_busca: 'exata', ordenar_por: 'data_asc', page: 1, page_size: 10 }, searchResults: null, isLoading: false, hasSearched: false, error: null, showAdvanced: false, expandedContents: {}, suggestion: null, ultimoTermoBuscado: '', get shouldShowSuggestion() { if (!this.suggestion || !this.searchParams.q) return false; // Função para remover acentos e converter para minúsculas const normalize = (text) => { return text.toLowerCase() .normalize('NFD') .replace("/", " ") .replace(/[^a-z0-9\s]/g, " ") // Substitui todos os outros símbolos por espaço .replace(/[\u0300-\u036f]/g, ''); }; const normalizedQuery = normalize(this.searchParams.q); const normalizedSuggestion = normalize(this.suggestion); // Só mostra a sugestão se for diferente do termo buscado (ignorando acentos e caixa) return normalizedQuery !== normalizedSuggestion; }, // Usa a sugestão como novo termo de busca usesuggestion() { this.searchParams.q = this.suggestion; this.searchParams.page = 1; this.performSearch(); }, // Verifica se um diário tem uma melhor correspondência hasBestMatch(diario) { return diario.paginas && diario.paginas.length > 0; }, // Muda a ordenação e faz uma nova busca changeOrder(order) { if (this.searchParams.ordenar_por !== order) { this.searchParams.ordenar_por = order; this.searchParams.page = 1; // Volta para a primeira página this.performSearch(); } }, // Obter sugestão da API async getSuggestion(query) { if (!query) return null; try { const url = new URL('http://109.199.98.226:8005/api/v1/diarios/sugestao'); url.searchParams.append('q', query); const response = await fetch(url); if (response.ok) { const data = await response.json(); return data.sugestao; } return null; } catch (error) { console.error('Erro ao buscar sugestão:', error); return null; } }, get totalPages() { if (!this.searchResults) return 0; return Math.ceil(this.searchResults.total / this.searchResults.por_pagina); }, get paginationArray() { const pages = []; const currentPage = this.searchParams.page; const totalPages = this.totalPages; // Função auxiliar para adicionar páginas const addPage = (page) => { if (page >= 1 && page <= totalPages && !pages.includes(page)) { pages.push(page); } }; // Sempre mostrar primeira página, página atual, última página // e 1-2 páginas adjacentes à página atual addPage(1); addPage(currentPage - 2); addPage(currentPage - 1); addPage(currentPage); addPage(currentPage + 1); addPage(currentPage + 2); addPage(totalPages); // Ordenar e adicionar separadores const result = pages.sort((a, b) => a - b); return result; }, // Retorna a melhor página (maior score) de um diário getBestPage(paginas) { if (!paginas || paginas.length === 0) return null; // Ordena as páginas por score (se disponível) ou pelo número da página se não houver score const sortedPages = [...paginas].sort((a, b) => { if (a.score === undefined || b.score === undefined) return 0; if (a.score === undefined) return 1; if (b.score === undefined) return -1; return b.score - a.score; }); return sortedPages[0]; }, // Retorna todas as páginas exceto a melhor getOtherPages(paginas) { if (!paginas || paginas.length <= 1) return []; const bestPage = this.getBestPage(paginas); if (!bestPage) return paginas; return paginas.filter(p => p.numero !== bestPage.numero) .sort((a, b) => a.numero - b.numero); // Ordena por número da página }, // Controla a exibição do conteúdo completo de uma página toggleFullContent(diarioIndex, paginaNumero) { const key = `${diarioIndex}-${paginaNumero}`; this.expandedContents[key] = !this.expandedContents[key]; }, // Verifica se um conteúdo está expandido isFullContentVisible(diarioIndex, paginaNumero) { const key = `${diarioIndex}-${paginaNumero}`; return this.expandedContents[key] === true; }, async performSearch() { this.isLoading = true; this.error = null; this.hasSearched = true; this.expandedContents = {}; // Resetar estados expandidos this.suggestion = null; // Resetar a sugestão try { let suggestionPromise = null; if (this.searchParams.q) { suggestionPromise = this.getSuggestion(this.searchParams.q); } if (this.searchParams.q !== this.ultimoTermoBuscado) { this.searchParams.page = 1; } this.ultimoTermoBuscado = this.searchParams.q; // Usando agora o endpoint busca const url = new URL('http://109.199.98.226:8005/api/v1/diarios/busca'); // Adicionar parâmetros à URL Object.entries(this.searchParams).forEach(([key, value]) => { if (value !== '' && value !== null) { url.searchParams.append(key, value); } }); const response = await fetch(url); if (!response.ok) { const errorData = await response.json().catch(() => null); throw new Error(errorData?.message || `Erro HTTP: ${response.status}`); } this.searchResults = await response.json(); // Processar os resultados para garantir que as páginas tenham score if (this.searchResults && this.searchResults.resultados) { this.searchResults.resultados.forEach(diario => { if (diario.paginas) { // Atribuir scores padrão se não existirem diario.paginas.forEach((pagina, index) => { if (pagina.score === undefined || pagina.score === null) { pagina.score = diario.paginas.length - index; // Score inversamente proporcional ao índice } }); } }); } if (suggestionPromise) { this.suggestion = await suggestionPromise; } } catch (error) { console.error('Erro na busca:', error); this.error = `Erro ao buscar diários: ${error.message}`; } finally { this.isLoading = false; } }, formatDate(dateString) { const options = { day: '2-digit', month: '2-digit', year: 'numeric' }; return new Date(dateString + 'T00:00:00').toLocaleDateString('pt-BR', options); }, goToPage(page) { if (page < 1 || page > this.totalPages) return; this.searchParams.page = page; this.performSearch(); window.scrollTo({ top: 0, behavior: 'smooth' }); }, resetSearch() { this.searchParams = { q: '', numero_diario: '', data_inicio: '', data_fim: '', modo_busca: 'exata', ordenar_por: 'relevancia', page: 1, page_size: 10 }; this.searchResults = null; this.hasSearched = false; this.error = null; this.expandedContents = {}; } })); });