243 lines
8.8 KiB
JavaScript
243 lines
8.8 KiB
JavaScript
|
|
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 = {};
|
||
|
|
}
|
||
|
|
}));
|
||
|
|
});
|